概述
Jest 是 Facebook 的一个开放式javascript测试库。它的口号是“令人愉快的 JavaScript 测试”。虽然 Jest 可用于测试任何 javaScript 库,但它在 react 和 React Native 方面表现出色。
这并不奇怪,因为 React 和 Jest 都来自 Facebook,而 Facebook 是两者的主要用户。在本教程中,我将向您展示 Jest 的八个不同方面,它们使测试 React 应用程序变得如此有趣。
1. Jest 是轻而易举的设置
Jest 自己安装非常简单。你可以直接使用 npm 或 yarn 将它安装在一个空的位置。我更喜欢毛线。请参阅使 Yarn 成为最佳 JavaScript 包管理器的 6 件事 以了解原因。它很简单:
yarn add --dev jest
如果您更喜欢 npm,请输入:
npm install --save-dev jest
在我们可以测试之前,让我们编写一些代码来测试。这是回文.js:
function isPalindrome(s) { const count = s.length - 1 if count < 2 { return true } for (i = 0; i < (count + 1) / 2; ++i) { if (s[i] !== s[count - i]) return false } return true } module.exports = isPalindrome
这是一个名为 palindrome.test.js 的文件中的一个笑话测试:
const isPalindrome = require('./palindrome') test('it detects palindromes', () => { expect(isPalindrome('palindrome')).toBe(false) expect(isPalindrome('')).toBe(true) expect(isPalindrome('a')).toBe(true) expect(isPalindrome('gg')).toBe(true) expect(isPalindrome('pop')).toBe(true) expect(isPalindrome('1212')).toBe(false) })
要运行测试,请将其添加到 package.json:
"scripts": { "test": "jest" }
您现在可以使用yarn test
or运行测试npm test
:
> yarn test yarn run v1.1.0 warning package.json: No license field $ jest PASS ./palindrome.test.js it detects palindromes (6ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 1.667s Ran all test suites. Done in 3.15s.
这很简单。但是如果你使用react-create-app 来创建你的 React 项目,你甚至不必这样做。捆绑了 jest 包,您可以立即开始编写测试。
2. Jest 快如闪电
开玩笑很快。非常快。当您的测试受 CPU 限制时,它可以从您的测试运行中节省大量时间。Airbnb 从 Mocha 切换到Jest ,在 32 核的重型 CI 机器上,他们的总测试运行时间从 12 多分钟下降到仅 4.5 分钟。本地测试过去需要 45 分钟,现在下降到 14.5 分钟。
是什么让 Jest 这么快?这是几个因素的组合:
并行化:这很明显,其他测试框架也使用它。
首先运行最慢的测试:这可确保最大限度地利用所有内核。
缓存 babel 变换:减少 CPU 密集型 babel 变换。
3. Jest 是一站式商店
Jest 带有内置的匹配器、间谍和它自己广泛的模拟库。它曾经是基于茉莉的,所以继承了茉莉的所有优点。但在最近的版本中,Jest 离开了 Jasmine,但保留了相同的功能并添加了自己的风格和改进。
将其与基于 Mocha 的定制测试解决方案进行比较时,很明显易用性是 Jest 设计的主要关注点。
4. Jest 有很棒的模拟
模拟是单元测试中非常重要的一部分。如果您关心快速测试(谁不关心?),这一点尤其重要。
模拟允许您替换可能很慢的无关依赖项,甚至可以控制依赖时间的代码的时间。Jest 让你完全控制你的依赖和掌握时间。
简单的模拟函数
模拟依赖是单元测试的长期传统。如果您的代码正在读取文件、写入文件、调用某些远程服务或正在访问数据库,则它可能会很慢,并且在测试后配置和清理可能会很复杂。并行运行时,甚至可能无法正常控制。
在这些情况下,最好用一个只记录它被调用的事实的模拟函数替换真正的依赖关系,这样您就可以验证工作流程。模拟jest.fn()
函数允许您提供固定返回值(用于多次连续调用),并记录它被调用的次数以及每次调用中的参数。
手动模块模拟
有时您可能需要用其数据而不是几个函数替换整个模块。Jest 允许您通过将您自己的具有相同名称的模块放在__mocks__
子目录中来做到这一点。
每当您的代码使用目标模块时,它将访问您的模拟而不是真实模块。您甚至可以通过调用jest.Unmock('moduleName')
.
计时器模拟
时间是单元测试的祸根。如果你想测试一分钟后超时的代码怎么办?每 30 秒触发一次的代码?在月底运行对账算法的特殊代码?
这些很难测试。您可以屈服于原始代码的时序要求(然后您的测试将非常缓慢),或者您可以操纵时间,这更有用。Jest 允许您控制以下与计时器相关的功能:
设置超时()
设置间隔()
清除超时()
清除间隔()
ES6 类模拟
Jest 完全支持 ES6 类并提供各种模拟它们的方法:
自动模拟:让您监视对构造函数和所有方法的调用,但始终返回未定义。
__mocks__
手动模拟:在子目录中实现自己的模拟。用高阶函数模拟类工厂。
mockImplementation()
使用or进行选择性模拟mockImplementationOnce()
。
5. Jest 支持 typescript
TypeScript 是一种流行的 JavaScript 类型化超集,可编译为纯 JavaScript。Jest 通过ts-jest 包支持 TypeScript。它将自己描述为一个 TypeScript 预处理器,为 Jest 提供源映射支持,并且拥有一个非常活跃的社区。
6. Jest 为您提供保障
Jest 有内置的覆盖率报告。您的测试仅与它们的覆盖率一样好。如果您只测试 80% 的代码,那么其他 20% 的错误只会在生产中被发现。
有时,从业务角度来看,跳过系统某些部分的测试是有意义的。例如,您自己的专家工程师经常使用和更改的内部工具可能不需要与您的生产代码相同级别的严格测试。但是,无论如何,这应该是一个有意识的决定,您应该能够准确地看到系统不同部分的测试覆盖率。
以下是如何为简单回文示例生成覆盖率报告:
> yarn test --coverage yarn run v1.1.0 warning package.json: No license field $ jest "--coverage" PASS ./palindrome.test.js it detects palindromes (4ms) -------------- |----------|----------|----------|----------| File | % Stmts | % Branch | % Funcs | % Lines | -------------- |----------|----------|----------|----------| All files | 100 | 100 | 100 | 100 | palindrome.js | 100 | 100 | 100 | 100 | -------------- |----------|----------|----------|----------| Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 1.712s Ran all test suites. Done in 3.41s.
7. Jest 做快照
快照测试很棒。它使您可以捕获代表渲染组件的字符串并将其存储在文件中。然后您可以稍后进行比较以确保 UI 没有更改。虽然它非常适合 React 和 React Native 应用程序,但您可以使用快照来比较其他框架的序列化值。如果您确实更改了 UI,那么您当然需要更新快照文件以反映它。
8. Jest 使用 Watch 进行 Delta 测试
Jest 可以在监视模式下运行,只要您更改代码,它就会自动运行测试。您使用--watchAll
命令行参数运行它,它将监视您的应用程序的更改。我在监视模式下运行 jest 并故意向 palindrome.js 引入了一个错误,结果如下:
FAIL ./palindrome.test.js it detects palindromes (11ms) ● it detects palindromes expect(received).toBe(expected) // Object.is equality Expected value to be: true Received: false 6 | expect(isPalindrome('a')).toBe(true) 7 | expect(isPalindrome('gg')).toBe(true) > 8 | expect(isPalindrome('pop')).toBe(true) 9 | expect(isPalindrome('1212')).toBe(false) 10 | }) 11 | at Object.<anonymous>.test (palindrome.test.js:8:30) Test Suites: 1 failed, 1 total Tests: 1 failed, 1 total Snapshots: 0 total Time: 0.598s, estimated 1s Ran all test suites. Watch Usage: Press w to show more.
结论
Jest 是一个易于设置的快速测试框架。Facebook 积极开发和使用它来测试他们所有的 React 应用程序以及许多其他开发人员和公司。
它在一个方便的包中拥有您所需的一切,支持 TypeScript,IMO 是 React 和 React Native 应用程序测试的最佳选择。从其他测试解决方案迁移也很重要。
- 简单的模拟函数
- 手动模块模拟
- 计时器模拟
- ES6 类模拟