Jest是什么?
Jest 是 Facebook 出品的一个测试框架,相对其他测试框架,其一大特点就是就是内置了常用的测试工具,比如自带断言、测试覆盖率工具,实现了开箱即用。
而作为一个面向前端的测试框架, Jest 可以利用其特有的快照测试功能,通过比对 UI 代码生成的快照文件,实现对 React 等常见框架的自动测试。
此外, Jest 的测试用例是并行执行的,而且只执行发生改变的文件所对应的测试,提升了测试速度。目前在 Github 上其 star 数已经破两万;而除了 Facebook 外,业内其他公司也开始从其它测试框架转向 Jest ,比如 Airbnb 的尝试 ,相信未来 Jest 的发展趋势仍会比较迅猛。
Jest的安装
Jest 可以通过 npm 或 yarn 进行安装。以 npm 为例,既可用npm install -g jest进行全局安装;也可以只局部安装、并在 package.json 中指定 test 脚本:
{ "scripts": { "test": "jest" }}
Jest 的测试脚本名形如*.test.js,不论 Jest 是全局运行还是通过npm run test运行,它都会执行当前目录下所有的*.test.js 或 *.spec.js 文件、完成测试。
Jest的用法
具体用法参考JEST官网,我们这里只是简单介绍几个常规用法。
用例的表示
表示测试用例是一个测试框架提供的最基本的 API , Jest 内部使用了 Jasmine 2 来进行测试,故其用例语法与 Jasmine 相同。test()函数来描述一个测试用例,举个简单的例子:
// hello.jsmodule.exports = () => 'Hello world'
// hello.test.jslet hello = require('hello.js')test('should get "Hello world"', () => { expect(hello()).toBe('Hello world') // 测试成功 // expect(hello()).toBe('Hello') // 测试失败})
其中toBe(‘Hello world’)便是一句断言( Jest 管它叫 “matcher” ,想了解更多 matcher 请参考文档)。写完了用例,运行在项目目录下执行npm test,即可看到测试结果。
Jest.config.js配置
vue环境下配置jest配置文件Jest.config.js。
module.exports = { moduleFileExtensions: ['js', 'jsx', 'json', 'vue'], transform: { '^.+\.vue$': 'vue-jest', '.+\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub', '^.+\.jsx?$': 'babel-jest' }, moduleNameMapper: { '^@/(.*)$': '<rootDir>/src/$1' }, snapshotSerializers: ['jest-serializer-vue'], testMatch: [ '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' ], collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'], coverageDirectory: '<rootDir>/tests/unit/coverage', // 'collectCoverage': true, 'coverageReporters': [ 'lcov', 'text-summary' ], testURL: 'http://localhost/'}
moduleFileExtensions
模块使用的文件扩展名。
moduleFileExtensions [array<string>]
Default: [“js”, “json”, “jsx”, “ts”, “tsx”, “node”]
An array of file extensions your modules use. If you require modules without specifying a file extension, these are the extensions Jest will look for, in left-to-right order.
模块使用的文件扩展名数组,如果未指定,则使用默认数组,按从左到右的顺序查找的扩展名。
We recommend placing the extensions most commonly used in your project on the left, so if you are using TypeScript, you may want to consider moving “ts” and/or “tsx” to the beginning of the array.
我们建议将项目中最常用的扩展名放在左侧,因此,如果您使用的是TypeScript,则可能需要考虑将“ ts”和/或“ tsx”移动到数组的开头。
transform
转变,转换器是提供同步功能以转换源文件的模块。
transform [object<string, pathToTransformer | [pathToTransformer, object]>]
A map from regular expressions to paths to transformers. A transformer is a module that provides a synchronous function for transforming source files. For example, if you wanted to be able to use a new language feature in your modules or tests that isn’t yet supported by node, you might plug in one of many compilers that compile a future version of JavaScript to a current one. Example: see the examples/typescript example or the webpack tutorial.
Examples of such compilers include:
- Babel
- TypeScript
- async-to-gen
- To build your own please visit the Custom Transformer section
moduleNameMapper
moduleNameMapper [object]
A map from regular expressions to module names that allow to stub out resources, like images or styles with a single module.
//从正则表达式到模块名称的映射,该模块名称允许将资源(例如图像或样式)存入一个模块。
Modules that are mapped to an alias are unmocked by default, regardless of whether automocking is enabled or not.
Use string token to refer to rootDir value if you want to use file paths.
Additionally, you can substitute captured regex groups using numbered backreferences.
示例:
{ "moduleNameMapper": { "^image![a-zA-Z0-9$_-]+$": "GlobalImageStub", "^[./a-zA-Z0-9$_-]+\.png$": "<rootDir>/RelativeImageStub.js", "module_name_(.*)": "<rootDir>/substituted_module_$1.js" }}
The order in which the mappings are defined matters. Patterns are checked one by one until one fits. The most specific rule should be listed first.
snapshotSerializers
快照序列化器。
snapshotSerializers [array<string>]
A list of paths to snapshot serializer modules Jest should use for snapshot testing.
testMatch
testMatch [array<string>]
(default: [ “ /tests/ / .[jt]s?(x)”, “**/?( .)+(spec|test).[jt]s?(x)” ])
The glob patterns Jest uses to detect test files. By default it looks for .js, .jsx, .ts and .tsx files inside of tests folders, as well as any files with a suffix of .test or .spec (e.g. Component.test.js or Component.spec.js). It will also find files called test.js or spec.js.
collectCoverageFrom
collectCoverageFrom [array]
参数是glob patterns 的列表,表明哪些集合的文件是需要收集的。如果文件匹配了,那么就会被收集作为coverage的基数,哪怕这个文件没有测试的用例。
示例:
{ "collectCoverageFrom": [ "**/*.{js,jsx}", "!**/node_modules/**", "!**/vendor/**" ]}
上面的例子中搜索在rootDir下面所有的以js或是jsx为后缀的文件,同时派出node_modules
和vendor目录下的文件。
coverageDirectory
coverageDirectory [string]
Jest输出覆盖信息文件的目录。
testURL
testURL [string]
Default: http://localhost
This option sets the URL for the jsdom environment. It is reflected in properties such as location.href.
前端自动化测试的价值
近几年前端工程化的发展风起云涌,但是前端自动化测试这块内容大家却似乎不太重视。虽然项目迭代过程中会有专门的测试人员进行测试,但等他们来进行测试时,代码已经开发完成的状态。与之相比,如果我们在开发过程中就进行了测试,会有如下的好处:
- 保障代码质量和功能的实现的完整度
- 提升开发效率,在开发过程中进行测试能让我们提前发现 bug ,此时进行问题定位和修复的速度自然比开发完再被叫去修 bug 要快许多
- 便于项目维护,后续任何代码更新也必须跑通测试用例,即使进行重构或开发人员发生变化也能保障预期功能的实现