在 TypeScript + Jest 的項目中,如果寫的測試代碼觸發了源碼中的 bug ,那么就需要 debug 了。此時主要有兩種 debug 工具:
- 借助於 Chrome 開發者工具調試。
- 使用 Visual Studio Code 內置的調試功能。
兩種方式各有優缺點,第一種主要是操作界面很熟悉,畢竟平時前端開發就是直接在使用 Chrome 開發者工具,但是第一種方案只有在代碼里面 import 了某個模塊,才能在 Sources 標簽下面找到那個文件。第二種主要是操作界面可能需要適應一段時間,但是文件還是很容易找到的。
本文主要介紹怎么配置第二種 debug 環境。
配置 Visual Studio Code 的 launch.json
- 切換到 debug 界面。
- 點擊新建 launch.json 文件(該文件會存放在
<project root>/.vscode/launch.json
路徑下)。
- 選擇調試類型為 node :
- 修改生成的 launch.json 文件內容為:
{
"version": "0.2.0",
"configurations": [
{
// 調試類型是 node
"type": "node",
// 使用 launch 方式,另一種 attach 方式可用於調試已存在的 node 進程。
"request": "launch",
// 該調試配置的名稱,主要用於在 select 控件里面選擇本配置。
"name": "test debug",
// 類似於命令行參數
"runtimeArgs": [
"--inspect-brk",
"${workspaceFolder}/node_modules/.bin/jest",
"--runInBand"
],
// node 的可執行程序
"runtimeExecutable": "/usr/local/bin/node",
// 使用什么終端工具。integratedTerminal 表示使用 Visual Studio Code 內置的終端工具,也可以配置成使用操作系統默認的終端工具。
"console": "integratedTerminal",
// 打開 console 的時機。這個 console 類似於 Chrome 開發者工具 console 的作用。
"internalConsoleOptions": "openOnSessionStart"
}
]
}
一般來說,在啟動調試的時候遇到
Cannot find runtime 'node' on PATH.
的時候,才去配置runtimeExecutable
,或者實在想用某個特定版本的 node 的時候。
對於上面的配置,啟動程序的時候,相當於運行
node --inspect-brk ${workspaceFolder}/node_modules/.bin/jest --runInBand
。--runInBank
是 Jest 特有的配置,默認情況下, Jest 是會使用子進程池去運行測試代碼的,這種多進程方式不利於 debug ,因此在 debug 的時候要使用--runInBank
去關閉 Jest 的多進程模式。
配置 Jest
在 package.json 中添加 Jest 配置:
{
...
"jest": {
// 對於 ts 代碼和當前 node 還不支持的 js 代碼,需要使用相應的轉換器轉換一下
"transform": {
// 使用 ts-jest 轉換 ts 代碼。 ts 文件路徑匹配 "^.+\\.tsx?$" 的,才會被轉換。
"^.+\\.tsx?$": "ts-jest",
// 使用 babel-jest 轉換 js 代碼。 js 文件路徑匹配 "^.+\\.jsx?$" 的,才會被轉換。
"^.+\\.jsx?$": "babel-jest"
},
// 轉換過程中,需要被忽略的文件。
"transformIgnorePatterns": [
"<rootDir>/node_modules/(moment|core-js|babel-runtime|regenerator-runtime|lodash)/"
],
// 是否搜集單測覆蓋率信息。
"collectCoverage": false,
// 匹配單測 spec 文件。
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(tsx?)$",
// 支持的源碼后綴名。
"moduleFileExtensions": [
"ts",
"js"
],
"globals": {
"ts-jest": {
// 過了 ts-jest 轉換器,就不要過 babel 轉換器了。
"skipBabel": true
}
},
"testPathIgnorePatterns": [
"/(node_modules|lib|coverage|types)/"
]
}
...
}
推薦默認關掉單測覆蓋率信息搜集: collectCoverage: false
,然后在 package.json 中配置如下 scripts :
{
...
"scripts": {
"test": "jest --coverage",
"test-debug": "node --inspect-brk node_modules/.bin/jest --runInBand"
}
...
}
其中 npm run test
用於跑正式的測試代碼,此時是需要生成覆蓋率報告的。而在對測試過程進行 debug 的時候,是不需要生成覆蓋率報告的:為了生成覆蓋率報告,要在源碼中插入很多代碼,然后默認又不會正確處理 Source Map ,因此會造成 debug 的時候將轉換后的代碼映射到源碼會出現問題。
ts-jest 默認情況下會自動查找 tsconfig.json 配置,查找邏輯為:從當前待轉換源碼文件所在目錄為起始目錄,依次往上找(包括當前目錄) tsconfig.json 配置文件。
babel-jest 尋找 .babelrc 配置文件的邏輯與 ts-jest
的類似。 .babelrc 中配置好測試環境就行了:
{
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": [
"istanbul",
[
"transform-runtime",
{
"polyfill": false,
"regenerator": false
}
]
]
}
}
}
安裝依賴
安裝如下依賴:
npm run @types/jest jest babel-plugin-transform-runtime babel-preset-env babel-preset-stage-2 ts-jest typescript -D
testEnvironment
Jest 默認在 jsdom 跑測試代碼, jsdom
是一個在 js 中模擬 DOM 環境的庫,少不了存在一些缺陷,比如 getComputedStyle
不會將 CSS 中 rule 的縮略寫法擴展成完整寫法,因此在某些條件下會有一些問題,這個時候,如果能全局 mock 掉這些問題就關系不大,如果不能 mock ,就只能切換執行測試代碼的環境了。不過對於大多數場景來說, jsdom
還是夠用的。
debug 測試
- 切換到 Visual Studio Code 的測試界面,選擇剛才的配置:
- 點擊“開始調試”按鈕,就可以進入 Visual Studio Code 調試了: