跳到主要内容
版本:27.2

快照测试

当您希望确保UI不会意外更改时,快照测试是一个非常有用的工具。

典型的快照测试用例呈现UI组件,拍摄快照,然后将其与存储在测试旁边的参考快照文件进行比较。如果两个快照不匹配,测试将失败:要么更改是意外的,要么引用快照需要更新到UI组件的新版本。

用Jest进行快照测试#

在测试React组件时,也可以采用类似的方法。您可以使用测试呈现器快速为React树生成可序列化的值,而不是呈现需要构建整个应用程序的图形UI。考虑这个示例测试暂时链接组件:

进口 反应 从…起 “反应” ;
进口 渲染器 从…起 “反应测试渲染器” ;
进口 链接 从…起 “../Link.react” ;
信息技术 ( “正确渲染” , ( ) => {
常数 = 渲染器
. 创造 ( < 链接 = " http://www.facebook.com " > 脸谱网 链接 > )
. toJSON ( ) ;
预料 ( ) . 托马奇斯纳普肖特 ( ) ;
} ) ;

第一次运行此测试时,Jest会创建快照文件看起来是这样的:

出口 [ ` 正确渲染1 ` ] = `
className=“正常”
href=”http://www.facebook.com"
onMouseCenter={[Function]}
onMouseLeave={[Function]}
>
脸谱网
` ;

快照工件应该与代码更改一起提交,并作为代码审查过程的一部分进行审查漂亮的格式使快照在代码审查期间可读。在后续的测试运行中,Jest将把呈现的输出与之前的快照进行比较。如果他们匹配,测试将通过。如果它们不匹配,要么测试运行者在代码中发现了一个bug(在组件),或者实现已更改,需要更新快照。

注意:快照的范围直接限定为您呈现的数据–在我们的示例中组件这意味着即使任何其他文件丢失了道具(例如,App.js)在组件,它仍将通过测试,因为测试不知道组件,它的作用域仅限于Link.react.js. 另外,在其他快照测试中使用不同的道具呈现同一组件不会影响第一个组件,因为测试彼此不了解。

有关快照测试如何工作以及我们为什么构建它的更多信息,请访问发布博客帖子yabo入口.我们推荐阅读这篇博文yabo入口为了更好地了解什么时候应该使用快照测试,我们还建议您观看以下内容书呆子视频使用Jest进行快照测试。

更新快照#

在引入错误后,很容易发现快照测试失败的时间。如果出现这种情况,请继续解决问题,并确保快照测试再次通过。现在,让我们讨论一下由于故意更改实现而导致快照测试失败的情况。

如果我们有意更改示例中链接组件所指向的地址,就会出现这种情况。

//已更新的测试用例,带有指向不同地址的链接
信息技术 ( “正确渲染” , ( ) => {
常数 = 渲染器
. 创造 ( < 链接 = " http://www.instagram.com " > 一款图片分享应用 链接 > )
. toJSON ( ) ;
预料 ( ) . 托马奇斯纳普肖特 ( ) ;
} ) ;

在这种情况下,Jest将打印此输出:

由于我们刚刚将组件更新为指向不同的地址,因此有理由期望此组件的快照发生更改。我们的快照测试用例失败,因为更新组件的快照不再与此测试用例的快照工件匹配。

要解决此问题,我们需要更新快照工件。您可以使用一个标志运行Jest,该标志将告诉Jest重新生成快照:

笑话——更新快照

继续并通过运行上述命令接受更改。也可以使用等效的单个字符-u标记以重新生成快照(如果愿意)。这将为所有失败的快照测试重新生成快照工件。如果由于意外错误导致任何其他快照测试失败,我们需要在重新生成快照之前修复错误,以避免记录错误行为的快照。

如果您想限制重新生成哪些快照测试用例,您可以通过额外的测试--testNamePattern仅为与模式匹配的测试重新记录快照的标志。

您可以通过克隆快照示例,修改链接组件,并运行笑话。

交互式快照模式#

也可以在监视模式下以交互方式更新失败的快照:

一旦进入交互式快照模式,Jest将一次一个测试引导您完成失败的快照,并让您有机会查看失败的输出。

从这里,您可以选择更新该快照或跳到下一个快照:

完成后,Jest将在返回观看模式之前为您提供一个摘要:

内联快照#

内联快照的行为与外部快照相同(断裂文件),但快照值会自动写入源代码中。这意味着您可以获得自动生成的快照的好处,而无需切换到外部文件以确保写入了正确的值。

例子:

首先,编写一个测试,调用.toMatchInlineSnapshot()没有任何论据:

信息技术 ( “正确渲染” , ( ) => {
常数 = 渲染器
. 创造 ( < 链接 = " https://example.com " > 实例 地点 链接 > )
. toJSON ( ) ;
预料 ( ) . toMatchInlineSnapshot ( ) ;
} ) ;

下次你开玩笑的时候,将进行计算,并将快照作为参数写入toMatchInlineSnapshot:

信息技术 ( “正确渲染” , ( ) => {
常数 = 渲染器
. 创造 ( < 链接 = " https://example.com " > 实例 地点 链接 > )
. toJSON ( ) ;
预料 ( ) . toMatchInlineSnapshot ( `
className=“正常”
href=”https://example.com"
onMouseCenter={[Function]}
onMouseLeave={[Function]}
>
示例站点
` ) ;
} ) ;

仅此而已!您甚至可以使用更新快照--更新快照或者使用U输入--监视模式

属性匹配器#

通常,要快照的对象中有一些字段是生成的(如ID和日期)。如果尝试快照这些对象,它们将强制快照在每次运行时失败:

信息技术 ( “每次都会失败” , ( ) => {
常数 使用者 = {
创建数据 : 刚出现的 日期 ( ) ,
身份证件 : 数学 . 地板 ( 数学 . 随机的 ( ) * 20 ) ,
名称 : “勒布朗·詹姆斯” ,
} ;
预料 ( 使用者 ) . 托马奇斯纳普肖特 ( ) ;
} ) ;
//快照
出口 [ ` 每次都会失败1 ` ] = `
反对{
“createdAt”:2018-05-19T23:36:09.816Z,
“id”:3,
“姓名”:“勒布朗·詹姆斯”,
}
` ;

对于这些情况,Jest允许为任何属性提供非对称匹配器。在写入或测试快照之前,将检查这些匹配器,然后将其保存到快照文件而不是接收到的值:

信息技术 ( '将检查匹配器并通过' , ( ) => {
常数 使用者 = {
创建数据 : 刚出现的 日期 ( ) ,
身份证件 : 数学 . 地板 ( 数学 . 随机的 ( ) * 20 ) ,
名称 : “勒布朗·詹姆斯” ,
} ;
预料 ( 使用者 ) . 托马奇斯纳普肖特 ( {
创建数据 : 预料 . 任何 ( 日期 ) ,
身份证件 : 预料 . 任何 ( 数字 ) ,
} ) ;
} ) ;
//快照
出口 [ ` 将检查匹配器并通过1 ` ] = `
反对{
“createdAt”:任何<日期>,
“id”:任何
“姓名”:“勒布朗·詹姆斯”,
}
` ;

将精确检查任何非匹配器的给定值,并将其保存到快照:

信息技术 ( '将检查值并通过' , ( ) => {
常数 使用者 = {
创建数据 : 刚出现的 日期 ( ) ,
名称 : “邦德……詹姆斯·邦德” ,
} ;
预料 ( 使用者 ) . 托马奇斯纳普肖特 ( {
创建数据 : 预料 . 任何 ( 日期 ) ,
名称 : “邦德……詹姆斯·邦德” ,
} ) ;
} ) ;
//快照
出口 [ ` 将检查值并通过1 ` ] = `
反对{
“createdAt”:任何<日期>,
“名称”:“债券…”。。。詹姆斯·邦德',
}
` ;

最佳做法#

快照是一个极好的工具,用于识别应用程序中意外的接口更改,无论该接口是API响应、UI、日志还是错误消息。与任何测试策略一样,为了有效地使用它们,您应该了解一些最佳实践,并遵循一些指导原则。

1.将快照视为代码#

提交快照并将其作为常规代码审查过程的一部分进行审查。这意味着要像对待项目中任何其他类型的测试或代码一样对待快照。

通过保持快照的焦点集中、简短,并使用强制执行这些风格约定的工具,确保快照的可读性。

如前所述,Jest使用漂亮的格式使快照具有可读性,但您可能会发现引入其他工具很有用,如eslint插件笑话带着它没有大快照选择权,或快照差异通过其组件快照比较功能,可以促进提交简短、集中的断言。

我们的目标是使查看拉请求中的快照变得容易,并克服在测试套件失败时重新生成快照的习惯,而不是检查其失败的根本原因。

2.测试应该是确定性的#

您的测试应该是确定性的。在未更改的组件上多次运行相同的测试,每次都会产生相同的结果。您有责任确保生成的快照不包含特定于平台的数据或其他非确定性数据。

例如,如果您有时钟使用日期:现在(),每次运行测试用例时,从该组件生成的快照都会不同。在这种情况下,我们可以模拟Date.now()方法要在每次运行测试时返回一致的值,请执行以下操作:

日期 . 现在 = 开玩笑 . fn ( ( ) => 1482363367071 ) ;

现在,每次快照测试用例运行时,日期:现在()会回来的1482363367071一贯地这将导致为该组件生成相同的快照,无论测试何时运行。

3.使用描述性快照名称#

始终努力为快照使用描述性测试和/或快照名称。最佳名称描述了预期的快照内容。这使得审阅者可以更容易地在审阅期间验证快照,并且任何人都可以在更新之前知道过期的快照是否是正确的行为。

例如,比较:

出口 [ ` 应该处理一些测试用例 ` ] = ` 无效的 ` ;
出口 [ ` 应该处理其他一些测试用例 ` ] = `
阿兰图灵
` ;

致:

出口 [ ` 应呈现空值 ` ] = ` 无效的 ` ;
出口 [ ` 应该呈现Alan Turing ` ] = `
阿兰图灵
` ;

由于后者准确地描述了输出中的预期内容,因此更清楚地看到错误的时间:

出口 [ ` 应呈现空值 ` ] = `
阿兰图灵
` ;
出口 [ ` 应该呈现Alan Turing ` ] = ` 无效的 ` ;

常见问题#

快照是否在持续集成(CI)系统上自动写入?#

不,从Jest 20开始,当Jest在CI系统中运行时,Jest中的快照不会自动写入,而不会显式传递--更新快照. 所有快照都应该是在CI上运行的代码的一部分,因为新快照会自动通过,所以它们不应该通过CI系统上的测试运行。建议始终提交所有快照并将其保留在版本控制中。

是否应提交快照文件?#

是的,所有快照文件都应该与它们所涵盖的模块及其测试一起提交。它们应该被视为测试的一部分,类似于任何其他开玩笑的断言的值。事实上,快照表示源模块在任何给定时间点的状态。通过这种方式,当源模块被修改时,Jest可以判断与以前版本相比发生了什么变化。它还可以在代码评审期间提供大量额外的上下文,在这些上下文中,评审员可以更好地研究您的更改。

快照测试是否仅适用于React组件?#

反应自然反应组件是快照测试的良好用例。然而,快照可以捕获任何可序列化的值,并且应该在测试输出是否正确的任何时候使用。Jest存储库包含许多测试Jest本身输出、Jest断言库输出以及来自不同部分的日志消息的示例Jest代码库。参见快照CLI输出开玩笑地说。

快照测试和可视化回归测试之间有什么区别?#

快照测试和可视化回归测试是测试UI的两种截然不同的方法,它们有不同的用途。可视化回归测试工具对网页进行截屏,并逐像素比较生成的图像。使用快照,测试值被序列化,存储在文本文件中,并使用diff算法进行比较。有考虑不同的权衡,我们列出了为什么在笑话博客yabo入口.

快照测试是否取代了单元测试?#

快照测试只是Jest附带的20多个断言中的一个。快照测试的目的不是取代现有的单元测试,而是提供附加值并使测试变得轻松。在某些情况下,快照测试可能会消除对特定功能集的单元测试需求(例如,反应组分),但它们也可以一起工作。

快照测试在生成文件的速度和大小方面的性能如何?#

Jest的编写考虑到了性能,快照测试也不例外。由于快照存储在文本文件中,因此这种测试方法快速可靠。Jest为调用托马奇斯纳普肖特匹配器。快照的大小非常小:作为参考,Jest代码库本身中所有快照文件的大小都小于300 KB。

如何解决快照文件中的冲突?#

快照文件必须始终表示它们所覆盖的模块的当前状态。因此,如果要合并两个分支并在快照文件中遇到冲突,可以手动解决冲突,也可以通过运行Jest并检查结果来更新快照文件。

是否可以将测试驱动的开发原则应用于快照测试?#

虽然可以手动写入快照文件,但这通常是不可接近的。快照有助于确定测试所涵盖的模块的输出是否发生了更改,而不是在一开始就为代码的设计提供指导。亚搏取款

代码覆盖率与快照测试一起工作吗?#

是的,以及任何其他测试。

最近更新日期通过西门·贝克胡斯