摘要:我在單元測試中主要用的庫有和,框架為。如果運行單元測試不想生成文檔,直接用就可以了,相應的配置如下如果不想為某個生成文檔,就不要調用的,直接按原生的寫法就可以了。生成的文檔內容形式如下原文地址通過單元測試為自動生成文檔
在開發中,為項目生成文檔是很常見的需求,很多第三方庫(如jsdoc、swagger等)的做法是為需要生成文檔的函數編寫相應的符合規范的注釋,然后運行相應的命令,生成一個靜態網頁形式的文檔。
用注釋生成文檔的好處是可以為無論是普通函數還是 API,只要編寫了相應的注釋都能生成相應的文檔,然而這種做法總覺得有點繁瑣,尤其是只需要為 API 生成文檔的時候,需要手動編寫大量的輸入和輸出作為使用示例。而且我只想需要 markdown 形式的文檔,丟在內部 Gitlab 的 wiki 上供前端人員査閱,然后可以根據 commit 的 history 查閱不同的版本。
不想手動為 API 文檔編寫大量的輸入輸出,那哪里會有輸入輸出呢,就很容易的想到了單元測試會產生輸入和輸出。好,那就用單元測試來為 API 生成文檔。
我在單元測試中主要用的庫有 mocha、supertest和power-assert,Web 框架為 express。
完整代碼示例:
// app.js const express = require("express"); const bodyParser = require("body-parser"); const app = express(); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.post("/user/create", function (req, res) { const name = req.body.name; res.json({ status: 200, error_code: 0, message: "success", data: { id: "123abc", name: "node", gender: "male", age: 23, }, }); }); app.get("/user/search", function (req, res) { const name = req.query.name; res.json({ status: 200, error_code: 0, message: "success", data: { id: "123abc", name: "node", gender: "male", age: 23, }, }); }); app.get("/user/:id", function (req, res) { const userId = req.params.id; res.json({ status: 200, error_code: 0, message: "success", data: { id: "123abc", name: "node", gender: "male", age: 23, }, }); }); app.listen(3000, function () { console.log(`Server is listening on 3000`); }); module.exports = app;
下面是測試文件。
// test/uset.test.js const assert = require("power-assert"); const supertest = require("supertest"); const U = require("../utils"); const app = require("../app"); const agent = supertest.agent(app); describe("Test", function () { it("should create user success", function (done) { U.test({ agent, file: "user", group: "用戶相關API", title: "創建用戶", method: "post", url: "/user/create" params: { name: { value: "node", type: "String", required: true, desc: "名稱" }, gender: { value: "male", type: "String", required: false, desc: "性別" }, age: { value: 23, type: "Int", required: false, desc: "" }, }, headers: { entrance: "client" }, expect: 200, callback (err, res) { if (err) return done(err); assert(res.body.data.name === "node"); assert(res.body.data.age === 23); done(); }, }); }); it("should search user success", function (done) { U.test({ agent, file: "user", group: "用戶相關API", title: "搜索用戶", method: "get", url: "/user/search" params: { name: { value: "node", type: "String", required: true, desc: "名稱" }, }, expect: 200, callback (err, res) { if (err) return done(err); assert(res.body.data.name === "node"); assert(res.body.data.age === 23); done(); }, }); }); it("should search user success", function (done) { U.test({ agent, file: "user", group: "用戶相關API", title: "獲取用戶信息", method: "get", url: "/user/:id" params: { id: { value: "123abc", type: "String", required: true, desc: "" }, }, expect: 200, callback (err, res) { if (err) return done(err); assert(res.body.data.name === "node"); assert(res.body.data.age === 23); done(); }, }); }); });
在測試文件中,測試用例的代碼調用到了 utils.js 中的 test 方法,該方法的主要作用是接收單元測試的輸入和輸出并生成相應的文檔,其中需要向 test 方法傳入一個對象作為參數,對象中的字段解讀如下:
agent:調用 API 的代理。
file:生成的文檔的文件名稱。
group:某一組文檔的名稱。
title:接口的名稱。
method:接口的方法。
params:接口的參數,即輸入。
headers: 添加到請求頭中的信息。
expect:supertest 的expect。
callback:supertest 方法的 end 的回調函數。
utils.js代碼如下:
// utils.js const path = require("path"); const fs = require("fs"); const mdStr = {}; exports.test = function (obj) { if (!mdStr[obj.group]) { mdStr[obj.group] = ""; mdStr[obj.group] += "## " + obj.group + " "; } const fields = {}; mdStr[obj.group] += `### ${ obj.title } `${ obj.method }` ${ obj.url } #### 參數 `; mdStr[obj.group] += " 參數名 | 類型 | 是否必填 | 說明 -----|-----|-----|----- "; Object.keys(obj.params).forEach(function (param) { const paramVal = obj.params[param]; fields[param] = paramVal["value"]; mdStr[obj.group] += `${ param } | ${ paramVal["type"] } | ${ paramVal["required"] ? "是" : "否" } | ${ paramVal["desc"] } `; }); mdStr[obj.group] += " #### 使用示例 請求參數: "; mdStr[obj.group] += "```json " + JSON.stringify(fields, null, 2) + " ``` "; mdStr[obj.group] += " 返回結果: "; if (obj.url.indexOf(":") > -1) { obj.url = obj.url.replace(/:w*/g, function (word) { return fields[word.substr(1)]; }); } obj.agent[obj.method](obj.url) .set(obj.header || {}) .query(fields) .send(fields) .expect(obj.expect) .end(function (err, res) { mdStr[obj.group] += "```json " + JSON.stringify(res.body, null, 2) + " ``` "; mdStr[obj.group] += " "; if (process.env["GEN_DOC"] > 0) { fs.writeFileSync(path.resolve(__dirname, "./docs/", obj.file + ".md"), mdStr[obj.group]); } obj.callback(err, res); }); }
這樣,在根目錄創建一個 docs 目錄,運行 npm run test:doc 命令,就會在 docs 目錄下生成文檔。如果運行單元測試不想生成文檔,直接用npm test就可以了,相應的package.json配置如下:
"scripts": { "test": "export NODE_ENV="test" && mocha", "test:doc": "export NODE_ENV="test" && export GEN_DOC=1 && mocha" }
如果不想為某個 API 生成文檔,就不要調用 utils 的 test,直接按原生的寫法就可以了。
若需要對參數進行簽名,可在調用 test 方法時,增加形如sign: true的配置,然后在 test 方法中做相應的判斷和實現相應的簽名。
生成的文檔內容形式如下:
原文地址:通過單元測試為API自動生成文檔
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88071.html
摘要:對模塊進行了打包,監聽文件更改刷新等功能,創建了個服務,分別為靜態資源服務用于代理本地資源,與自刷新瀏覽器請求服務用于接受,請求,返回數據服務用于收發消息。除了項目,還可以換成項目。項目地址如果覺得對你有所幫助,多謝支持 prince-cli 快速指南 這是一個為快速創建SPA所設計的腳手架,旨在為開發人員提供簡單規范的開發方式、服務端環境、與接近native應用的體驗。使用它你能夠獲...
摘要:首先安裝單元測試環境使用模塊來模擬定義的模型。根據刪除這是單元測試的最后一小節。需要根據需求和單元測試用例來編寫應用邏輯,使我們的程序更加穩定。我們會運行自動測試用例,一直重構,直到所有單元測試都通過。 本文轉載自:眾成翻譯譯者:文藺鏈接:http://www.zcfy.cc/article/746原文:https://semaphoreci.com/community/tutoria...
摘要:首先安裝單元測試環境使用模塊來模擬定義的模型。根據刪除這是單元測試的最后一小節。需要根據需求和單元測試用例來編寫應用邏輯,使我們的程序更加穩定。我們會運行自動測試用例,一直重構,直到所有單元測試都通過。 本文轉載自:眾成翻譯譯者:文藺鏈接:http://www.zcfy.cc/article/746原文:https://semaphoreci.com/community/tutoria...
摘要:塊就是測試用例,表示一個單獨的測試,塊可以包含多個斷言塊塊就是斷言,判斷預期結果和執行結果是否一致失敗的話會打印錯誤提示注意因為箭頭函數不能夠訪問的上下文,所以在需要用到上下文的時候不能使用,否則報錯。 前言 我的英文水平有點渣,所以就貼上原文給你們自己翻譯了,還有github地址,如果發現有些中文文檔的話也會順便贈送飛機票 mocha Mocha is a feature-rich ...
摘要:原文鏈接在中貫徹單元測試在團隊合作中,你寫好了一個函數,供隊友使用,跑去跟你的隊友說,你傳個值進去,他就會返回結果了。如果你也為社區貢獻過,想更多人使用的話,加上單元測試吧,讓你的值得別人信賴。 原文鏈接:BlueSun | 在Nodejs中貫徹單元測試 在團隊合作中,你寫好了一個函數,供隊友使用,跑去跟你的隊友說,你傳個A值進去,他就會返回B結果了。過了一會,你隊友跑過來說,我傳個A...
閱讀 2461·2023-04-26 02:18
閱讀 1262·2021-10-14 09:43
閱讀 3822·2021-09-26 10:00
閱讀 6945·2021-09-22 15:28
閱讀 2535·2019-08-30 15:54
閱讀 2600·2019-08-30 15:52
閱讀 474·2019-08-29 11:30
閱讀 3465·2019-08-29 11:05