摘要:單元測試一個合格的庫應(yīng)該包含完整的單元測試。是的支持版,和是一樣的,它能夠直接運(yùn)行為后綴的單元測試文件。在目錄下加入然后執(zhí)行即可看到單元測試結(jié)果。
這篇文章主要是講述如何使用 TypeScript 編寫一個完善,包含測試、文檔、持續(xù)集成的庫,涵蓋了編寫整個庫所需要的技術(shù)和工具,主要涵蓋:
項(xiàng)目目錄骨架
TypeScript 配置
使用 jest 單元測試
使用 vuepress 編寫文檔
使用 github pages 部署文檔
持續(xù)集成部署
原文首發(fā)于我的個人網(wǎng)站:聽說 - https://tasaid.com/,推薦在我的網(wǎng)站閱讀更多技術(shù)文章。
前端開發(fā) QQ 群:377786580
歡迎使用和了解滴滴金融出品的移動端組件庫 Mand-mobile。
為了迎合這篇文章,我編寫了一個可以開箱即用的庫模板:https://github.com/linkFly6/ts-lib-basic。
里面集成了這篇文章所闡述的所有內(nèi)容。
初始化項(xiàng)目目錄先初始化項(xiàng)目目錄,一般來說,src 放源碼,dist 放編譯后的代碼,tests 放單元測試,所以先初始化好基礎(chǔ)目錄。
. ├── .vscode # vscode 配置 │ └── launch.json # vscode 調(diào)試配置 ├── dist # 編譯產(chǎn)出目錄,編譯后才有 ├── src # 源碼 ├── tests # 單元測試 ├── .gitignore # git 忽略文件 ├── .npmrc # npm 配置 ├── .travis.yml # github 持續(xù)集成 ├── LICENSE # 開源協(xié)議 ├── README.md # README ├── package-lock.json # npm 鎖定依賴 ├── package.json # npm ├── tsconfig.json # typescript 配置 └── tslint.json # tslint 校驗(yàn)
先按照這個目錄文件結(jié)構(gòu),然后我們會一步步填上內(nèi)容。
通過 npm init 初始化一個 npm 配置:
初始化 TypeScript 相關(guān)工具既然包是基于 TypeScript 的,那么 TypeScript 工具必不可少。
ts-node在開發(fā)中,可以使用 ts-node(可以理解為可以直接執(zhí)行 ts 文件的 node)來直接運(yùn)行我們的 ts 代碼。
npm i --save-dev typescript npm i --save-dev ts-node
如果是 node 應(yīng)用,為了讓 TypeScript 能夠進(jìn)行 node 類型推導(dǎo),則需要安裝 Node 對應(yīng)的類型聲明:
npm i --save-dev @types/nodetsconfig.json
tsconfig.json 是 TypeScript 的配置文件,這里提供一份可供參考是配置,置于項(xiàng)目根目錄:
{ "compilerOptions": { "sourceMap": false, "module": "commonjs", // 模塊配置 "noImplicitAny": true, // 是否默認(rèn)禁用 any // "removeComments": true, // 是否移除注釋 "types": [ // 默認(rèn)引入的類型聲明 "node", // 默認(rèn)引入 node 的類型聲明 ], "baseUrl": ".", // 工作根目錄 "paths": { // ~/ 指向 server/types,types 目錄下都是 types 文件,所以不會編譯產(chǎn)出 "~/*": [ "./types/*" ] }, "target": "es6", // 編譯目標(biāo) "outDir": "dist", // 輸出目錄 "declaration": true, // 是否自動創(chuàng)建類型聲明 }, // 此配置生效范圍 "include": [ "src/**/*" ], }tslint.json
tslint 類似 eslint,是 TypeScript 中的代碼風(fēng)格約束工具。
關(guān)于 lint,個人方面比較傾向于非強(qiáng)制性的,所以只在 vscode 中安裝了擴(kuò)展 tslint,這樣 vscode 會根據(jù)項(xiàng)目根目錄配置的 tslint.json 標(biāo)出不符合規(guī)范的信息。
這里有一份推薦配置:
{ "defaultSeverity": "error", "extends": [ "tslint:recommended" ], "jsRules": {}, "rules": { "max-line-length": [ true, 140 ], // 禁止內(nèi)置原始類型 "ban-types": false, // 禁止給參數(shù)賦值 "no-parameter-reassignment": false, // 禁止空接口 "no-empty-interface": true, // 顯示類型代碼就不需要再加類型聲明了 "no-inferrable-types": true, // 不允許使用內(nèi)部模塊 "no-internal-module": true, // 不允許在變量賦值之外使用常量數(shù)值。如果未指定允許值的列表, 則默認(rèn)情況下允許-1、0和1 => 亂七八糟的數(shù)字會讓人混淆 // "no-magic-numbers": [true], // 不允許使用內(nèi)部 "modules" 和 "namespace" "no-namespace": true, // 非空斷言,強(qiáng)制使用 == null 之類的斷言 // "no-non-null-assertion": true // 禁止 ///package-lock.json,直接用 import 即可 "no-reference": true, // 禁止使用 require,應(yīng)該使用 import foo = require("foo") "no-var-requires": false, // import 的順序按照字母表 "ordered-imports": false, // 對象屬性聲明按照字母表 "object-literal-sort-keys": false, // // 結(jié)束語句后的分號 "semicolon": [ false, "always" ], // 字符串強(qiáng)制單引號 "quotemark": [ true, "single", "jsx-double" ], // 禁止 arguments.callee "no-arg": true, // if 語句的單行不用括號,多行用括號 "curly": false, // 是否強(qiáng)制使用箭頭函數(shù),禁止匿名函數(shù) "only-arrow-functions": false, // 是否禁止多個空行 "no-consecutive-blank-lines": false, // 在函數(shù)括號前要求或不允許空格 "space-before-function-paren": false, // 箭頭函數(shù)的參數(shù)使用括號 "arrow-parens": [ true, "ban-single-arg-parens" ], // 不固定變量類型 "no-shadowed-variable": false, // 行尾多余的空格 "no-trailing-whitespace": false, // == 和 === "triple-equals": false, // 禁止一些位運(yùn)算符 "no-bitwise": false, // 禁止 console "no-console": false, // 檢查變量名 "variable-name": [ true, "ban-keywords" // "check-format", // "allow-leading-underscore" ], // 一行聲明變量表達(dá)式 "one-variable-per-declaration": false, // 允許在一個文件里定義多個 class "max-classes-per-file": [ true, 5 ], // 判斷表達(dá)式 fn && fn() "no-unused-expression": [ true, "allow-fast-null-checks" ], // 空函數(shù) "no-empty": false, // forin 是否必須包含 hasOwnProperty 判斷 "forin": false, "no-debugger": false, // 強(qiáng)制要求必須要聲明類型 "typedef": [ true ] }, "rulesDirectory": [ "./src" ] }
package-lock.json 是 npm 5 之后引入的,為了解決 npm 過去使用的 package.json 版本依賴太寬松的問題。
比如說 package.json 中依賴了包 mand-mobile,使用了最常用的插入依賴(^):
"mand-mobile": "^4.16.4",
假設(shè)自己項(xiàng)目在上線階段, mand-mobile 更新到了 [email protected],而剛好 [email protected] 又不小心出現(xiàn)了一個新 bug 會導(dǎo)致頁面腳本錯誤。這時候上線安裝依賴的時候,由于 package.json 和 ^ 約束太寬松,就會導(dǎo)致 [email protected] 被安裝,從而導(dǎo)致上線出問題。
package-lock.json 就是為了解決這個問題,通過 npm 安裝包的時候,會檢測本地是否有 package-lock.json。
如果沒有 package-lock.json,就在安裝包的時候?qū)?dāng)前包依賴的詳細(xì)信息(包括子級依賴)都寫入生成 package-lock.json。
如果有 package-lock.json,則根據(jù) package.json,參考 pacakge-lock.json 來安裝包依賴。來保證依賴穩(wěn)定。
本質(zhì)上 ppackage-lock.json 的作用類似于 node_modules 包依賴的快照。
單元測試一個合格的庫應(yīng)該包含完整的單元測試。這里我們使用 jest 對應(yīng)的 TypeScript 版本:ts-jest。
ts-jestts-jest 是 jest 的 TypeScript 支持版,API 和 jest 是一樣的,它能夠直接運(yùn)行 .ts 為后綴的單元測試文件。
安裝 ts-jest 和對應(yīng)的類型聲明文件:
npm i --save-dev jest #ts-jest 依賴 jest npm i --save-dev ts-jest npm i --save-dev @types/jest
在 package.json 中加入 jest 配置和 npm run test 的腳本:
{ "name": "my-app", "main": "dist/index.js", "scripts": { "test": "jest --verbose" }, "jest": { "rootDir": "tests", "transform": { "^.+.tsx?$": "ts-jest" }, "testRegex": "(/__tests__/.*|(.|/)(test|spec)).tsx?$", "moduleFileExtensions": [ "ts", "tsx", "js", "jsx", "json", "node" ] } }
這時候就可以基于 jest 編寫單元測試了。在 tests/ 目錄下加入 example.test.ts:
import { isArrayLike } from "../src" describe("my-app:isArrayLike", () => { test("isArrayLike(): true", () => { expect( isArrayLike([]), ).toBe(true) }) test("isArrayLike(): false", () => { expect( isArrayLike({}), ).toBe(false) }) })
然后執(zhí)行 npm run test 即可看到單元測試結(jié)果。
express 測試如果要測試 express/koa 之類的 web 應(yīng)用框架程序,則可以使用 tj 大神的 supertest。
安裝對應(yīng)的包:
npm i --save-dev supertest npm i --save-dev @types/supertest
import * as express from "express" /** * 用于測試 express、koa 等 web 應(yīng)用框架的工具 */ import * as request from "supertest" import middleware from "../src" describe("my-app:basic", () => { test("locals", done => { const app = express() app.use(middleware) app.get("/example", (req, res) => { res.send({ code: 0 }) }) // 使用 supertest 進(jìn)行測試 request(app).get("/example").expect(200, { code: 0 }, done) }) })debug
debug 也是 tj 大神編寫的一個庫,用于在應(yīng)用程序中輸出 debug 信息,用于調(diào)試工具庫,著名的庫大部分都采用該庫進(jìn)行 debug 支持。
npm i --save debug npm i --save-dev @types/debug
import * as d from "debug" const debug = d(`my-app:basic`) debug("debug info")
在啟動應(yīng)用程序的時候,只需要在環(huán)境變量中注入 DEBUG 即可:
DEBUG=my-app* node app.js DEBUG=my-app* ts-node app.tsvscode 基于 ts-node 調(diào)試
在 .vscode/launch.json 中可以配置基于 ts-node 的調(diào)試:
{ // 使用 IntelliSense 了解相關(guān)屬性。 // 懸停以查看現(xiàn)有屬性的描述。 // 欲了解更多信息,請?jiān)L問: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "啟動程序", // 基于 ts-node 調(diào)試 "program": "${workspaceFolder}/node_modules/ts-node/dist/bin.js", "args": [ "-P", "${workspaceRoot}/tests/tsconfig.json", "${workspaceRoot}/tests/app.ts", // 入口文件 ] } ] }文檔
文檔方面,簡陋一點(diǎn)的,可以直接使用 README,也可以用 gitbook。不過我個人方便比較推薦 vuepress。
遠(yuǎn)程托管文檔方面,要么自建服務(wù)器,要么直接托管到 Github 的 Pages。
使用 vuepress 編寫文檔個人比較傾向于使用 vuepress 編寫文檔,是因?yàn)槔锩鏀U(kuò)展 Markdown 擴(kuò)展了許多豐富實(shí)用的語法,以及菜單結(jié)構(gòu)的強(qiáng)大可配置。
這里我們討論的是在項(xiàng)目中集成文檔。
在項(xiàng)目根目錄新建目錄 /docs
npm i --save-dev vuepress
在項(xiàng)目的 package.json 中加入腳本
"scripts": { "docs": "vuepress dev docs", "docs:build": "vuepress build docs" }
在 /docs 新增文件 README.md,寫入以下內(nèi)容:
--- home: true actionText: 開始使用 → actionLink: /readme footer: MIT Licensed | Copyright ? 2018-present linkFly features: - title: 快速 details: 快速創(chuàng)建庫 - title: 集成 details: 集成單元測試和自動化 doc 部署 - title: TypeScript details: TypeScript 支持 --- 集成了基礎(chǔ)工具的,使用 TypeScript 快速編寫一個應(yīng)用庫
然后執(zhí)行結(jié)合我們剛才配置的命令,執(zhí)行 npm run docs,終端 shell 會輸出 vuepress 啟動的服務(wù)地址:
訪問地址,即可看到文檔頁面:
使用 github pages 托管文檔github pages 是 Github 提供的一個免費(fèi)的頁面托管服務(wù),我們可以將 vuexpress 編譯出來的文檔托管到上面。
Github Pages 服務(wù)和 Github 已經(jīng)打通,可以從項(xiàng)目的 /docs 目錄自動部署,這也就是我們?yōu)槭裁匆陧?xiàng)目里新建 /docs 目錄的原因。
首先,我們將項(xiàng)目中 pageage.json 的腳本進(jìn)行更新:
"scripts": { "docs:build": "vuepress build docs && cp -rf ./docs/.vuepress/dist/* ./docs && rm -r ./docs/.vuepress/dist" }
這段腳本的大體意思就是先使用 vuepress 構(gòu)建產(chǎn)出文檔的 HTML 文件(在 /docs/.vuepress/dist 目錄下),然后將 dist 目錄移動到 docs/ 目錄下,因?yàn)?Github Pages 在識別 docs/ 的時候只能識別 docs/index.html。
執(zhí)行 npm run docs:build。
將本地的項(xiàng)目 push 到 Github 以后,打開該項(xiàng)目的 Setting:
在 Github Pages 配置項(xiàng)選擇 docs/ 文件夾:
然后訪問 https://
travis-ci 是一個持續(xù)集成服務(wù),它可以用來自動部署和構(gòu)建 Github 上的項(xiàng)目。
我們可以集成我們的單元測試。
在項(xiàng)目根目錄加入 .travis.yml,在 master 分支進(jìn)行提交的時候自動運(yùn)行 npm run test 命令(npm run test 命令配置參見 ts-jest 章節(jié)):
sudo: false language: node_js node_js: - "8" cache: directories: - node_modules branches: only: - master script: npm run test
打開 https://travis-ci.org/ 進(jìn)行注冊或登錄。新增接入的項(xiàng)目:
選擇要打開持續(xù)集成的項(xiàng)目:
然后我們更新文檔或代碼,提交代碼到 Github。
稍等大概幾十秒,就可以在 travis-ci 里面看到自己的單元測試任務(wù):
最后,在測試完畢的情況下,在 https://www.npmjs.com/ 進(jìn)行注冊。
在 npm 的源是官方的(npm config set registry https://registry.npmjs.org/)情況下,執(zhí)行 npm login 登錄 npm 以后,npm publish 發(fā)布包即可。
最后,為了迎合這篇文章,我編寫了一個可以開箱即用的庫模板:https://github.com/linkFly6/ts-lib-basic。
里面集成了這篇文章所闡述的所有內(nèi)容。
前端開發(fā) QQ 群:377786580
歡迎使用和了解金融出品的移動端組件庫 Mand-mobile。
原文首發(fā)于我的個人網(wǎng)站:聽說 - https://tasaid.com/,推薦在我的網(wǎng)站閱讀更多技術(shù)文章。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/100649.html
摘要:弄了一個持續(xù)更新的筆記,可以去看看,鏈接地址此篇文章的地址使用兩年后值得嗎基礎(chǔ)筆記的地址可以也可以。使用,你可以使用抽象類等功能。有關(guān)抽象類的更多信息支持,和方法,只讀屬性。 弄了一個持續(xù)更新的github筆記,可以去看看,鏈接地址:Front-End-Basics 此篇文章的地址:使用TypeScript兩年后-值得嗎? 基礎(chǔ)筆記的github地址:https://githu...
摘要:框架是和應(yīng)用程序的另一個測試和規(guī)范框架。它是為應(yīng)用程序編寫自動測試的最有用的庫之一。數(shù)據(jù)庫是許多應(yīng)用程序包括核心和應(yīng)用程序不可分割的一部分,可能是進(jìn)行單元測試時的最大障礙。 作為一名Java開發(fā)人員,我們從事不同的領(lǐng)域,從編寫核心Java代碼到創(chuàng)建JSP頁面、編寫RESTAPI,有時甚至創(chuàng)建Groovy腳本以實(shí)現(xiàn)構(gòu)建自動化...
摘要:在,我們剛剛使用發(fā)布了我們的客戶端的新版本。得到了最多的提及,排在第二位。根據(jù),這個許可證旨在保護(hù)他們免受專利巨魔的侵害。正在獲得更多開發(fā)者的支持,我們在開發(fā)過程中看到了這一點(diǎn),讓我們更加相信,我們的選擇是對的。 showImg(https://segmentfault.com/img/bVbdxdq?w=1960&h=960);在Rever(www.reverscore.com),我...
閱讀 1532·2023-04-25 17:41
閱讀 3054·2021-11-22 15:08
閱讀 852·2021-09-29 09:35
閱讀 1615·2021-09-27 13:35
閱讀 3336·2021-08-31 09:44
閱讀 2725·2019-08-30 13:20
閱讀 1947·2019-08-30 13:00
閱讀 2568·2019-08-26 12:12