大家好!
JavaScript开发人员课程将于本周四开始。 在这方面,我们决定分享另一种有趣的材料的翻译。 好好阅读。
笑话一直是我必不可少的单元测试工具。 它是如此可靠,以至于我开始认为我一直没有充分利用它。 尽管测试有效,但随着时间的流逝,我不时重构了它们,因为我不知道Jest可以做到这一点。 每当我检查Jest文档时,这都是一个新代码。
因此,我将分享一些您可能已经知道的我最喜欢的Jest技巧,这是因为您阅读了文档而不是像我一样(感到羞耻),但是我希望这对那些刚刚通过它的人有所帮助!
顺便说一下,我将Jest v24.8.0用作参考资料,因此请注意,某些事情可能不适用于您当前使用的Jest版本。 另外,这些示例并不代表实际的测试代码,这只是一个演示。
#1 .toBe与.toEqual
最初,所有这些声明对我来说都是正常的:
expect('foo').toEqual('foo') expect(1).toEqual(1) expect(['foo']).toEqual(['foo'])
基于对等式语句(to.equal)使用
chai ,这很自然。 实际上,Jest不会抱怨,这些陈述照常通过。
但是,Jest具有.toBe和.toEqual。 第一个用于使用
Object.is声明相等性,第二个用于提供对象和数组的深度比较。 如果事实证明您不需要深层比较(如断言原始值的相等性),. toEqual会使用
Object.is ,这可以解释为什么前面的示例运行得很好。
expect('foo').toBe('foo') expect(1).toBe(1) expect(['foo']).toEqual(['foo'])
这样,如果您已经知道要测试的值,则可以使用
.toBe
跳过
.toEqual
所有
if-else
。
一个常见的错误是您将使用
.toBe
声明原始值的相等性。
expect(['foo']).toBe(['foo'])
如果您在.toBe崩溃时查看
源代码 ,它将尝试通过
调用 .toEqual使用
的函数来确定您是否确实犯了此错误。 优化测试时可能会成为瓶颈。
如果确定使用的是原始值,则可以将代码重新组织为优化目的:
expect(Object.is('foo', 'foo')).toBe(true)
文档中有更多详细信息。
#2 比较合适的比较
从技术上讲,您可以使用
.toBe
来验证任何值。 使用Jest,您可以专门使用某些比较工具来使测试更具可读性(在某些情况下更短)。
这些只是我从文档的Jest编译器的长列表中选择的一部分,您可以自己看看其余部分。
#3 在没有用户界面的情况下对元素进行快照测试
您可能已经
在Jest中听说过
快照测试 ,它可以帮助您跟踪用户界面元素中的更改。 但是,使用快照进行测试不限于此。
考虑以下示例:
const allEmployees = getEmployees() const happyEmployees = giveIncrementByPosition(allEmployees) expect(happyEmployees[0].nextMonthPaycheck).toBe(1000) expect(happyEmployees[1].nextMonthPaycheck).toBe(5000) expect(happyEmployees[2].nextMonthPaycheck).toBe(4000)
如果您要求越来越多的员工,那会很累。 另外,如果事实证明每位员工需要更多的索赔,则将新索赔的数量乘以员工的数量,您将获得一个想法。
通过快照测试,所有这些都可以像这样简单地完成:
const allEmployees = getEmployees() const happyEmployees = giveIncrementByPosition(allEmployees) expect(happyEmployees).toMatchSnapshot()
每当发生回归时,您将确切知道节点中的哪棵树与图像不匹配。
但是便利是要付出代价的:这种方法更容易出错。 您可能不知道图片实际上是不正确的,最后无论如何您都会将其拍摄。 因此,请仔细检查您的快照,就像它是您自己的批准代码一样(因为是)。
当然,测试不仅限于快照。 阅读完整的
文档 。
#4 描述和测试
您是否编写过与此相似的测试?
describe('When I am a supervisor', () => { test('I should have a supervisor badge', () => { const employee = new Employee({ level: 'supervisor' }) expect(employee.badges).toContain('badge-supervisor') }) test('I should have a supervisor level', () => { const employee = new Employee({ level: 'supervisor' }) expect(employee.level).toBe('supervisor') }) }) describe('When I am a manager', () => { test('I should have a manager badge', () => { const employee = new Employee({ level: 'manager' }) expect(employee.badges).toContain('badge-manager') }) test('I should have a manager level', () => { const employee = new Employee({ level: 'manager' }) expect(employee.level).toBe('manager') }) })
这是单调和常规的,对吗? 想象在很多情况下都这样做。
使用
description.each
和
test.each
可以按以下方式压缩代码:
const levels = [['manager'], ['supervisor']] const privileges = [['badges', 'toContain', 'badge-'], ['level', 'toBe', '']] describe.each(levels)('When I am a %s', (level) => { test.each(privileges)(`I should have a ${level} %s`, (kind, assert, prefix) => { const employee = new Employee({ level }) expect(employee[kind])[assert](`${prefix}${level}`) }) })
但是,我还没有在自己的测试中使用它,因为我希望对测试进行详细说明,但我只是认为这将是一个有趣的技巧。
请参阅
文档以获取有关参数的更多详细信息(扰流器:表语法确实很酷)。
#5 单一模仿全局功能
在某个时候,您将不得不在特定的测试用例中测试一些依赖于全局函数的东西。 例如,一个使用Date javascript对象接收有关当前日期的信息的函数,或一个依赖于此的库。 困难在于,涉及到当前日期时,您永远无法获得正确的陈述。
function foo () { return Date.now() } expect(foo()).toBe(Date.now())
最后,您将不得不重新定义全局Date对象,以使其一致且可管理:
function foo () { return Date.now() } Date.now = () => 1234567890123 expect(foo()).toBe(1234567890123)
但是,这被认为是不好的做法,因为在测试之间保持重新定义。 如果没有基于Date.now的其他测试,您将不会注意到这一点,但是它也会泄漏。
test('First test', () => { function foo () { return Date.now() Date.now = () => 1234567890123 expect(foo()).toBe(1234567890123)
我曾经“破解”它,以便它不会泄漏:
test('First test', () => { function foo () { return Date.now() const oriDateNow = Date.now Date.now = () => 1234567890123 expect(foo()).toBe(1234567890123)
但是,有一种更好,更少黑客的方法来做到这一点:
test('First test', () => { function foo () { return Date.now() jest.spyOn(Date, 'now').mockImplementationOnce(() => 1234567890123) expect(foo()).toBe(1234567890123)
因此,
jest.spyOn
跟随全局Date对象,它仅模仿一次调用就模仿了now函数的实现。 反过来,其余的测试将使Date.now保持不变。
绝对有关于Jest中的存根的更多信息。 有关更多详细信息,请参见完整
文档 。
这篇文章已经足够长了,所以我认为目前为止。 这仅影响Jest功能的一小部分,我只介绍我的最爱。 如果您还有其他有趣的事实,请告诉我。
另外,如果您经常使用Jest,请查看
Majestic ,它是Jest的无GUI GUI,是无聊的终端输出的一种很好的替代方法。 我不确定作者是否从事开发,但仍然尊重这个人。
与往常一样,感谢您的关注!
仅此而已。 在课程中见。