PixelTest
PixelTest 是一个现代化、Swift-first 的快照测试工具,旨在让您尽可能快地编写快照测试。
快照测试将渲染到图像中的其中一个视图与之前记录的图像进行比较,允许 0% 的差异,否则测试将失败。
快照测试非常适合快速检查复杂的布局,同时也可以对未来可能发生的意外更改提供保护。
作为额外的好处,PixelTest 还会自动清理。如果您修复了失败的测试,则会自动从磁盘上删除失败和差分图像。
主要特性
PixelTest 是一个出色的替代品,因为它
- 使用 Swift 编写,因此能够利用现代 Swift 功能,如强大的枚举。
- 为您处理视图布局,使您的项目免于丑陋的布局代码。
- 支持在您的工作空间中的多个子项目/模块中,自动找到存储快照的正确目录。
- 通过在测试日志中直接显示失败的差异图像来帮助您,无需离开 Xcode。
- 如果测试失败,PixelTest 会自动创建带有交互式分割覆盖的 HTML 文件以查看哪里出错。
- 在修复和通过相应的测试时,自动清理磁盘上存储的失败/差异图像。
- 开箱即用,无需设置环境变量。
- 无依赖项。
为什么使用快照测试?
快照测试是一种优秀(且超级快速)的方式来确保您的布局永远不会出问题。
单元测试涵盖逻辑,自动化/UI测试涵盖行为,快照测试覆盖应用程序的实际外观。这确保了复杂的布局从一开始就不会出错,这意味着您或其他人可以放心地对视图进行重构,而不用担心它会破坏原有的外观。
安装
PixelTest 库可在 Cocoapods 上获取。
将 PixelTest 添加到您的 Podfile
中的 单元测试目标。
target 'YourAppTarget' do
target 'YourAppTestTarget' do
pod 'PixelTest'
end
end
然后在终端中导航到您的 Podfile
位于的位置,并运行 pod update
命令。
快速入门
步骤 1
开始时,您需要创建一个单元测试用例(不是 UI 测试用例,这很重要!)并从 PixelTestCase
继承。
import PixelTest
@testable import YourAppTarget
class TestClass: PixelTestCase {
}
步骤 2
开始编写测试!查看示例项目以获取一些简单的示例。一旦您编写了测试,您需要首先记录一些参考图像。要记录图像,重写 setUp()
并将 mode
设置为 .record
。
class TestClass: PixelTestCase {
override func setUp() {
super.setUp()
mode = .record
}
func test_someViewLaysOutProperly() {
let view = MyCustomView()
verify(view, layoutStyle: .dynamicHeight(fixedWidth: 100))
}
}
一旦重写了setUp()
方法,只需运行测试。当mode
设置为.record
时,每个运行的测试都将记录一个参考图像。一旦禁用记录模式(无论是通过删除代码行还是将mode
设置为.test
),接下来每次运行测试都将检查保存的参考图像。如果甚至连1个像素的差异都有,测试将失败。
如果测试失败,你将在测试文件同一目录下自动创建的.pixeltest
目录中的Diff
和Failure
目录中找到两张图片。
你可以使用这些图片来查看发生了什么变化以及出错的原因。如果是故意的更改,你可以重新录制快照。请注意,只有在记录模式下运行要重新录制的测试,因为这将覆盖运行后的任何测试。
选项
你可以决定PixelTest是否以动态高度或宽度、或固定高度和宽度来测试你的视图。在调用verify(view, ...)
时,你还必须传入一个LayoutStyle
。通常这将是.dynamicHeight(fixedWidth: 320)
,这意味着PixelTest将尝试使用固定宽度为320
的视图进行测试,但允许它根据其内容动态调整高度。
这使得你可以在项目中或模块中不添加丑陋的布局代码的情况下填充你的视图。
由于使用.dynamicHeight(fixedWidth: 320)
非常常见,PixelTest提供了简写,你可以在测试中使用.dynamicHeight
,它将自动使用fixedWidth
为320
。
此外,PixelTest现在提供了一些String常量,你可以用于填充视图模型中的短/长/非常长等内容
let viewModel = ViewModel(title: .shortContent, subtitle: .mediumContent)
PixelTest还会让你能生成任何大小的占位符图像,因此你不需要为测试目标添加任何资源
let viewModel = ViewModel(image: .sized(width: 250, height: 100))
无障碍功能
通过正确设置字体和视图,你可以使用PixelTest测试不同的动态字体大小。示例项目中在DynamicTypeViewSnapshotTests.swift
有一些如何做到这一点的示例。
值得了解的知识点
由于UIKit如何与可重用视图(如UITableViewCell
和UITableViewHeaderFooterView
)交互,因此有时视图需要以特定方式快照。
幸运的是,PixelTest再次帮到了你,如果你直接传入cell的contentView,它将自动使用cell的contentView。
您也可以对任何 UIViewController
的视图进行快照测试,但就像任何视图一样,如果高度无法动态确定(许多控制器的情况就是这样),您必须使用类似 LayoutStyle.fixed(width: 320, height: 640)
的方式明确指定高度。
更改模拟器或 iOS 版本
快照测试的唯一真正缺点是,由于 Mac 和 iOS 版本之间的 UI 渲染略有不同,这意味着您必须每次都在同一个模拟器上运行您的测试。
一旦培养起习惯,通常这不是问题,但在尝试迁移到新的 iOS 版本(例如,您不再支持测试所运行的旧 iOS 版本)时,就会产生问题。
PixelTest 也帮助您处理这个问题,并提供两种全局重录测试的方式。您可以选择强制记录整个套件,或者强制记录单个测试目标(适用于模块化应用程序)。
要在整个测试套件中全局记录,请添加一个名为 PTRecordAll
的环境变量,其值为 YES
。
要记录单个测试目标,请在 测试目标 的 Info.plist
中添加一个值为 YES
的 Boolean
条目。
设置其中的任何一个都将覆盖在合适位置设置为 .test
模式的任何测试。
要求
PixelTest 目前仅在 iOS 项目中工作。
作者
@KaneCheshire, kane.codes
许可
PixelTest 在 MIT 许可下可用。有关更多信息,请参阅 LICENSE 文件。
快照测试的原始想法是FBSnapshotTest,该工具已被弃用,后来由Uber继承。PixelTest是一个更加敏捷的替代方案,功能更多,代码更少,且代码结构更易于理解的开源项目。