Jest使用

2021.12.21 星期二 :

实际

我在jest环境中工作,在寻找test coverage时,它显示在一行中,用符号E,这是什么?
我发现,E代表else path not taken,这意味着对于标记的if/else语句,if路径已经过测试,而不是else。

几个指标

%stmts是语句覆盖率(statement coverage):是不是每个语句都执行了?
%Branch分支覆盖率(branch coverage):是不是每个if代码块都执行了?
%Funcs函数覆盖率(function coverage):是不是每个函数都调用了?
%Lines行覆盖率(line coverage):是不是每一行都执行了?

文件结构设计

Jest 推荐你在被测试代码的所在目录下创建一个 __tests__ 目录,但你也可以为你的测试文件随意设计自己习惯的文件结构。不过要当心 Jest 会为快照测试在临近测试文件的地方创建一个 __snapshots__ 目录。

– 单测文件或者tests目录跟要测试的文件放在同个目录,方便我们查找

配置

npx jest --showConfig > test/jest.conf.output.json
onlyChanged: 只是针对修改的测试用例。

"automock": false,

“cacheDirectory”: “/private/var/folders/84/q_vxngn51816smpv9prjnx6h0000gp/T/jest_dy”,

“injectGlobals”: true,

"onlyFailures": false,

"onlyChanged": false,
"lastCommit": false,

–changedSince

"maxConcurrency": 5,

"maxWorkers": 9,

插件

js-dom
awesome-jest:https://github.com/jest-community/awesome-jest#results-processors

jest-dom: Custom Jest matchers to test the dom structure.

result

报告:
jest-html-reporters 比 jest-html-reporter 强一扭扭:
有dashboard,可以看到图表。列表有分组/折叠。直接跳转到lcov-report,查看每个文件的细节。

https://github.com/dkelosky/jest-stare

This is a Jest HTML reporter. It takes summary test results from jest and parses them into an HTML file for improved readability and filtering.

majestic Zero config UI for Jest.
jest-bamboo-formatter: https://github.com/adalbertoteixeira/jest-bamboo-formatter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// bail: 1,
preset: "ts-jest",
// verbose: true,
globals: {
"ts-jest": {
tsConfig: "<rootDir>/tsconfig.json",
importHelpers: true
}
},
testEnvironment: "jsdom",
rootDir: path.resolve(__dirname, "../"),

// 在jest inital之前执行,比setupFilesAfterEnv更早,例如可以设置全局变量到global
"setupFiles": [
// jsdom,不涉及dom可不引入
"react-app-polyfill/jsdom"
],
// 类似,在jest inital之后执行,这一步能拿到jest的api进行扩展(故名AfterEnv)
// 可以执行例如引入enzyme配置等
"setupFilesAfterEnv": [
"<rootDir>/src/setupTests.js"
],

moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
moduleNameMapper: {
'@tarojs/taro': '<rootDir>/test/mocks/taroMock.js', // tarojs mock
'@tarojs/components': '@tarojs/components/dist-h5/react',
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/test/mocks/fileMock.js",
"\\.(css|less|scss)$": "<rootDir>/test/mocks/styleMock.js",
'@/utils/Cookie': '<rootDir>/src/utils/Cookie/index.h5.js',
'@/utils/Track': '<rootDir>/test/mocks/emptyMock.js',
'^@/(.*)$': '<rootDir>/src/$1', // webpack alias 配置
},

testMatch: ["<rootDir>/test/**/*.spec.js", "<rootDir>/test/**/*.spec.jsx"],
testPathIgnorePatterns: [
"/node_modules",
"test/components/Dialog.spec.js*",
"test/pages/balance_confirm*",
],

"transform": {
// 用 `babel-jest` 处理 js
"^.+\\.js$": "<rootDir>/node_modules/babel-jest"
},

// 快照的序列化工具 || 否则测通过,但是快照文件没有内容生成。
snapshotSerializers: ["enzyme-to-json/serializer"],
// "snapshotSerializers":["jest-serializer-vue"],


collectCoverage: true,
coverageDirectory: "<rootDir>/test/coverage",

/**
* 可以用一个 通配模式 的数组来指出仅哪些文件需要收集覆盖率信息。
*
* 1)lcov-report 目录结构是根据这个配置生成的。
* 比如:同时配置 src/** 和src/utils 会生成两个utils的目录。
* src/** /*.ts?(x) 和 src/** /*.ts?(x) 是通一个目录 (ext: 空格是防止注释)
* 2)路径后面必须有`**`, 比如`!/src/enums/**`
*/
collectCoverageFrom: [
// "<rootDir>/src/utils/**",
// 'src/**/!(*.d).{js,ts}',
"<rootDir>/src/**/*.[jt]s?(x)",
"!/src/enums/**",
"!src/**/*-mock*",
],
/**
* An array of regexp pattern strings that are matched against all file paths before executing the test.
* 执行测试前 忽略掉的文件。
* 即不会运行test, 区别于上面的collectCoverageFrom。
* 防止某些文件输出意外的error等信息。
* `STACK: SyntaxError: /Users/user123/myprojects/xxx/pagev32614-mock.js:`
* collectCoverageFrom 和 coveragePathIgnorePatterns 都可以生效。
*/
coveragePathIgnorePatterns: [
'url-decode\\.json',
'.*-mock\..*',
],

/**
* clover -> clover.xml;
* json -> `coverage-final.json`;
* lcov -> lcov-report/目录, Icov.info; 每一个测试用例/文件的结果报告(详细)。
* text: 控制台视图.
* ?? Icov.info 文件记录了一堆问题。 TODO: 记录的什么
*/
"coverageReporters": [/* "clover", */ "json", "lcov", ["text", {"skipFull": true}]],

testResultsProcessor: "jest-bamboo-reporter",
// "coverageThreshold": {
// "global": {
// "branches": 50,
// "functions": 50,
// "lines": 50,
// "statements": 50
// },
// "./src/components/": {
// "branches": 40,
// "statements": 40
// },
// },

reporters: [
"default",
[
"./node_modules/jest-html-reporter",
{
pageTitle: "Test Report",
outputPath: "./test/report/test-report.html"
}
],
["jest-html-reporters", {
"publicPath": "./test/report",
"filename": "jest_html_reporters.html",
"openReport": true
}]
]

globals, globalSetup; setupFiles, setupFilesAfterEnv

小程序配置

小程序-自定义组件-单元测试
miniprogram-simulate: https://github.com/wechat-miniprogram/miniprogram-simulate

1
2
3
4
5
6
7
{
// jest 是直接在 nodejs 环境进行测试,使用 jsdom 进行 dom 环境的模拟。在使用时需要将 jest 的 `testEnvironment` 配置为 `jsdom`。
// jest 内置 jsdom,所以不需要额外引入。
"testEnvironment": "jsdom",
// 配置 jest-snapshot-plugin 从而在使用 jest 的 snapshot 功能时获得更加适合肉眼阅读的结构
"snapshotSerializers": ["miniprogram-simulate/jest-snapshot-plugin"]
}

问题
  1. getApp is not defined

    我们可以通过jest提供的global设置全局变量,可以在测试文件中单独编写,或者在package.json的jest块设置setupFiles属性,让jest自动加载。

由于小程序页面的构成包含Page和生命钩子等miniprogram-simulate不提供的能力,所以我们需要自己先进行全局配置Page。

1
2
3
4
5
6
{
globals: {
getApp: () => ""
},
"setupFiles": ["./setup.js"]
}

\$_PS: 但是实际中,通过globals 只有一个用例单独测试的时候可以通过。两个用例一起测试又回报错。??不解。

基础信息

通常,mock函数会提供以下三个功能,来实现替换:捕获函数调用情况,设置函数返回值,改变原函数的实现。

Jest单元测试入门和实例
\$_PS: 基础教程。
Jest 是 Facebook 出品的一个测试框架,相对其他测试框架,其一大特点就是就是内置了常用的测试工具,比如自带断言、Mock 功能、测试覆盖率工具,实现了开箱即用。

react(组件)测试

原文: Testing React Hooks With Enzyme and React Testing Library

enzyme 和 react-testing-library

enzyme

#1 【前端单元测试入门02】react的单元测试之Enzyme

简而言之,Enzyme主要包括三个测试:
一个是浅渲染的shallow,这个生成虚DOM对象,所以渲染最快,然而它并不能测试子组件的相关代码。
另一个是DOM渲染mount,它会生成完整的DOM节点,所以可以测试子组件。但是要依赖一个用jsdom模拟的浏览器环境。
最后一个是HTML文本渲染render,它会将react组件渲染为html文本,然后在内部通过Cheerio自动生成一个Cheerio对象。

enzyme 和 react-testing-library

原文: Difference between enzyme and react-testing-library

\$_PS: 从配置,概念(组件测试 or dom测试),渲染机制(enzyme 有3种方式),强制更新组件,实例方法,约束性(组件内部方法) 等5个方面详细比较了区别。

总结

虽然@testing-library/react 的目标是与 Enzyme 竞争,并鼓励你从用户的角度编写可测试的代码和对应测试,但它们都有用例。你不能用一个代替另一个。有时你确实需要测试组件内部的状态变化或功能,尽管从用户的角度来看,它可能没有意义。在这些情况下,需要用 Enzyme 来测试实例方法。React Testing Library 很适合测试组件的 DOM,因为它允许你像用户使用它一样进行测试。

Jest

# React单元测试— 以Jest为例

enzyme和@testing-library/react,怎么选择呢?现在倾向于@testing-library/react, -是因为它对react hooks支持比较好,二是,它的测试更符合用户形为,渲染组件,查找元素,和用户使用浏览器没有什么区别。@testing-library/react也鼓励我们,

\$_PS: 开文说明了@testing-library/react的优势;和enzyme有对比。

背景

Jest优势

在软件的测试领域,测试主要分为:单元测试、集成测试和功能测试。

前端的测试框架有很多:mocha, jasmine, ava, testcafe, jest,他们都有各自擅长的领域和特点,而我们采用的jest框架具有如下的一些特点:

适应性:Jest是模块化、可扩展和可配置的;
沙箱和快速:Jest虚拟化了JavaScript的环境,能模拟浏览器,并且并行执行;
快照测试:Jest能够对React 树进行快照或别的序列化数值快速编写测试,提供快速更新的用户体验;
支持异步代码测试:支持promises和async/await;
自动生成静态分析结果:不仅显示测试用例执行结果,也显示语句、分支、函数等覆盖率。

开发模式

TDD: 测试驱动开发,英文为Testing Driven Development,强调的是一种开发方式,以测试来驱动整个项目,即先根据接口完成测试编写,然后在完成功能是要不断通过测试,最终目的是通过所有测试
BDD: 行为驱动测试,英文为Behavior Driven Development,强调的是写测试的风格,即测试要写的像自然语言,让项目的各个成员甚至产品都能看懂测试,甚至编写测试

TDD和BDD有各自的使用场景,BDD一般偏向于系统功能和业务逻辑的自动化测试设计;而TDD在快速开发并测试功能模块的过程中则更加高效,以快速完成开发为目的。

两者不是一个层级的东西。 BDD 包含 TDD。

knowledge is no pay,reward is kindness
0%