前端自動化測試:Jest 測試框架應用
Jest : https://jestjs.io/zh-Hans/是 Facebook 出品的一個 JavaScript 開源測試框架。
相對其他測試框架,其一大特點就是就是內置了常用的測試工具,比如零配置、自帶斷言、測試覆蓋率工具等功能,實現了開箱即用。
Jest 適用但不局限于使用以下技術的項目:Babel、TypeScript、 Node、 React、Angular、Vue 等。
Jest 主要特點:
- 零配置
- 自帶斷言
- 作為一個面向前端的測試框架, Jest 可以利用其特有的快照測試功能,通過比對UI 代碼生成的快照文件,實現對 React 等常見前端框架的自動測試。
- Jest 的測試用例是并行執行的,而且只執行發生改變的文件所對應的測試,提升了測試速度。
- 測試覆蓋率
- Mock 模擬
快速體驗 Jest
安裝 Jest 到項目中:
- npm install --save-dev jest
- //math.js
- functionadd (a, b) {
- return a * b
- }
- functionsubtract (x, y) {
- return x - y
- }
- module.exports= {
- add,
- subtract
- }
- //test.js ==> math.test.js
- const { add, subtract } =require('./math')
- test('測試加法', () => {
- expect(add(1,2)).toBe(3)
- })
- test('測試減法', () => {
- expect(subtract(2,1)).toBe(1)
- })
- //package.json
- {
- "scripts":{
- "test":"jest"
- }
- }
jest 命令會運行項目中所有以 .test.js 結尾的文件
最后運行測試命令:
- npm run test
解析:
- jest 找到項目中所有以 .test.js 結尾的文件并運行
- jest 會給測試文件提供 test、expect 等全局函數,所以在測試文件中可以直接使用
- jest 為測試結果提供了良好的日志輸出
解決 vscode 中 jest 代碼提示問題
- npm i -D @types/jest
注意:@types/jest 必須安裝到項目的根目錄,并且以根目錄的方式在 vscode 中打開,否則不生效?;蛘哒f只要是 vscode 打開的項目根目錄有 @types/jest 這個包就可以了。
配置文件
- npx jest--init
配置文件生成選項:
- 是否使用 ts ;
- 使用哪種測試環境;
- 使用 jest 收集測試覆蓋率報告;
- 使用那種引擎檢測覆蓋率:v8 處于實驗性階段,建議 Node v14 后使用,babel 較為成熟
- 每次測試時,是否自動清除 mock 實例;
詳細配置信息參考:https://jestjs.io/docs/zh-Hans/configuration。
- //jest.config.js
- /*
- * For a detailedexplanation regarding each configuration property, visit:
- *https://jestjs.io/docs/en/configuration.html
- */
- module.exports= {
- // 自動 mock 所有導入的外部模塊
- // automock: false,
- // 在指定次數失敗后停止運行測試
- // bail: 0,
- // The directory where Jest should store its cached dependencyinformation
- // cacheDirectory:"/private/var/folders/5h/_98rffpj1z95b_0dm76lvzm40000gn/T/jest_dx",
- // 在每個測試之間自動清除 mock 調用和實例
- clearMocks:true,
- // 是否收集測試覆蓋率信息
- // collectCoverage: false,
- // 一個 glob 模式數組,指示應該為其收集覆蓋率信息的一組文件
- // collectCoverageFrom: undefined,
- // 測試覆蓋率報錯文件輸出的目錄
- coverageDirectory:"coverage",
- // 忽略測試覆蓋率統計
- // coveragePathIgnorePatterns: [
- // "/node_modules/"
- // ],
- // 指示應該使用哪個提供程序檢測代碼的覆蓋率,默認是 babel,可選 v8,但是 v8 不太穩定,建議Node 14 以上版本使用
- // coverageProvider: "babel",
- // A list of reporter names that Jest uses when writingcoverage reports
- // coverageReporters: [
- // "json",
- // "text",
- // "lcov",
- // "clover"
- // ],
- // An object that configures minimum threshold enforcement forcoverage results
- // coverageThreshold: undefined,
- // A path to a custom dependency extractor
- // dependencyExtractor: undefined,
- // Make calling deprecated APIs throw helpful error messages
- // errorOnDeprecated: false,
- // Force coverage collection from ignored files using an arrayof glob patterns
- // forceCoverageMatch: [],
- // A path to a module which exports an async function that istriggered once before all test suites
- // globalSetup: undefined,
- // A path to a module which exports an async function that istriggered once after all test suites
- // globalTeardown: undefined,
- // A set of global variables that need to be available in alltest environments
- // globals: {},
- // The maximum amount of workers used to run your tests. Canbe specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPUamount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2workers.
- // maxWorkers: "50%",
- // An array of directory names to be searched recursively upfrom the requiring module's location
- // moduleDirectories: [
- // "node_modules"
- // ],
- // An array of file extensions your modules use
- // moduleFileExtensions: [
- // "js",
- // "json",
- // "jsx",
- // "ts",
- // "tsx",
- // "node"
- // ],
- // A map from regular expressions to module names or to arraysof module names that allow to stub out resources with a single module
- // moduleNameMapper: {},
- // An array of regexp pattern strings, matched against allmodule paths before considered 'visible' to the module loader
- // modulePathIgnorePatterns: [],
- // Activates notifications for test results
- // notify: false,
- // An enum that specifies notification mode. Requires {notify: true }
- // notifyMode: "failure-change",
- // A preset that is used as a base for Jest's configuration
- // preset: undefined,
- // Run tests from one or more projects
- // projects: undefined,
- // Use this configuration option to add custom reporters toJest
- // reporters: undefined,
- // Automatically reset mock state between every test
- // resetMocks: false,
- // Reset the module registry before running each individualtest
- // resetModules: false,
- // A path to a custom resolver
- // resolver: undefined,
- // Automatically restore mock state between every test
- // restoreMocks: false,
- // The root directory that Jest should scan for tests andmodules within
- // rootDir: undefined,
- // A list of paths to directories that Jest should use tosearch for files in
- // roots: [
- // "<rootDir>"
- // ],
- // Allows you to use a custom runner instead of Jest's defaulttest runner
- // runner: "jest-runner",
- // The paths to modules that run some code to configure or setup the testing environment before each test
- // setupFiles: [],
- // A list of paths to modules that run some code to configureor set up the testing framework before each test
- // setupFilesAfterEnv: [],
- // The number of seconds after which a test is considered asslow and reported as such in the results.
- // slowTestThreshold: 5,
- // A list of paths to snapshot serializer modules Jest shoulduse for snapshot testing
- // snapshotSerializers: [],
- // The test environment that will be used for testing
- // testEnvironment: "jest-environment-jsdom",
- // Options that will be passed to the testEnvironment
- // testEnvironmentOptions: {},
- // Adds a location field to test results
- // testLocationInResults: false,
- // The glob patterns Jest uses to detect test files
- // testMatch: [
- // "**/__tests__/**/*.[jt]s?(x)",
- // "**/?(*.)+(spec|test).[tj]s?(x)"
- // ],
- // An array of regexp pattern strings that are matched againstall test paths, matched tests are skipped
- // testPathIgnorePatterns: [
- // "/node_modules/"
- // ],
- // The regexp pattern or array of patterns that Jest uses todetect test files
- // testRegex: [],
- // This option allows the use of a custom results processor
- // testResultsProcessor: undefined,
- // This option allows use of a custom test runner
- // testRunner: "jasmine2",
- // This option sets the URL for the jsdom environment. It isreflected in properties such as location.href
- // testURL: "http://localhost",
- // Setting this value to "fake" allows the use offake timers for functions such as "setTimeout"
- // timers: "real",
- // A map from regular expressions to paths to transformers
- // transform: undefined,
- // An array of regexp pattern strings that are matched againstall source file paths, matched files will skip transformation
- // transformIgnorePatterns: [
- // "/node_modules/",
- // "\\.pnp\\.[^\\/]+$"
- // ],
- // An array of regexp pattern strings that are matched againstall modules before the module loader will automatically return a mock for them
- // unmockedModulePathPatterns: undefined,
- // Indicates whether each individual test should be reportedduring the run
- // verbose: undefined,
- // An array of regexp patterns that are matched against allsource file paths before re-running tests in watch mode
- // watchPathIgnorePatterns: [],
- // Whether to use watchman for file crawling
- // watchman: true,
- };
Jest CLI Options
參考:https://jestjs.io/zh-Hans/docs/cli
指定測試文件運行
- "scripts":{
- "test":"jest ./math.test.js"
- },
Jest 監視模式
--watchAll 選項:監視文件的更改并在任何更改時重新運行所有測試。
- "scripts": {
- "test": "jest --watchAll"
- },
Jest API
在測試文件中,Jest 將所有這些方法和對象放入全局環境中。無需要求或導入任何內容即可使用它們。但是,如果喜歡顯式導入,則可以:
- import { describe, expect, test } from'@jest/globals'
Test 函數
test 函數別名:it(name, fn, timeout)。
- test(name,fn, timeout)
- test.concurrent(name, fn, timeout)
- test.concurrent.each(table)(name, fn, timeout)
- test.concurrent.only.each(table)(name, fn)
- test.concurrent.skip.each(table)(name, fn)
- test.each(table)(name, fn, timeout)
- test.only(name, fn, timeout)
只運行當前測試用例
- test.only.each(table)(name, fn)
- test.skip(name,fn)
- test.skip.each(table)(name, fn)
- test.todo(name)
創建 global-api.test.js 測試文件,注意,測試文件中必須有一個測試用例,如果沒有則直接報錯。
- test('should ', () => {
- console.log('test--api')
- })
- test('should ', () => {
- console.log('test--api')
- })
- test('should1 ', () => {
- console.log('test--api1')
- })
- // 上面兩個不運行
- test.only('should2 ', () => {
- console.log('test--api2')
- })
Expect 匹配器
在編寫測試時,通常需要檢查值是否滿足某些條件。Expect 讓我們可以訪問許多“匹配器”,以驗證不同的內容。
- test('two plus two is four', () => {
- expect(2+2).toBe(6)
- expect({ name:'jack' }).toEqual({ name:'jack' })
- expect('Christoph').toMatch(/stop/)
- expect(4).toBeGreaterThan(3)
- expect(4).toBeLessThan(5)
- })
完整的匹配器列表查看:https://jestjs.io/zh-Hans/docs/expect
describe 函數
describe 創建一個將幾個相關測試組合在一起的塊。
- const myBeverage = {
- delicious:true,
- sour:false,
- };
- describe('my beverage', () => {
- test('is delicious', () => {
- expect(myBeverage.delicious).toBeTruthy();
- });
- test('is not sour', () => {
- expect(myBeverage.sour).toBeFalsy();
- });
- });
分組最直觀的就是在測試提示中,有更加友好的信息輸出。
- describe(name,fn)
- describe.each(table)(name, fn, timeout)
- describe.only(name,fn)
- describe.only.each(table)(name, fn)
- describe.skip(name,fn)
- describe.skip.each(table)(name, fn)