📸 SnapshotTesting
愉悦的 Swift 快照测试。
用法
安装后,不需要额外的配置。您可以导入SnapshotTesting
模块并调用assertSnapshot
函数。
import SnapshotTesting
import XCTest
class MyViewControllerTests: XCTestCase {
func testMyViewController() {
let vc = MyViewController()
assertSnapshot(matching: vc, as: .image)
}
}
第一次运行断言时,快照会自动记录到磁盘,测试将失败,并打印出任何新记录的参考文件的路径。
🛑 失败 - 磁盘上未找到参考。自动记录的快照:…打开“…/MyAppTests/__Snapshots__/MyViewControllerTests/testMyViewController.png”
再次运行“testMyViewController”以针对新记录的快照进行测试。
重复运行测试将加载该参考并与运行时值进行比较。如果不匹配,测试将失败并描述差异。可以从Xcode的报告导航器或检查失败文件的URL来检查失败。
您可以将record
参数设置为true
在断言或设置全局的isRecording
上记录一个新参考。
assertSnapshot(matching: vc, as: .image, record: true)
// or globally
isRecording = true
assertSnapshot(matching: vc, as: .image)
快照任何内容
虽然Swift社区中的大多数快照测试库仅限于UIView
的UIImage
,但SnapshotTesting可以为任何Swift平台上的任何值和任何格式工作!
assertSnapshot
函数接受一个值和该值支持的任何快照策略。这意味着可以测试视图或视图控制器与它的图像表示形式以及其属性和子视图层次结构的文本表示。
assertSnapshot(matching: vc, as: .image)
assertSnapshot(matching: vc, as: .recursiveDescription)
assertSnapshot(matching: vc, as: .image(on: .iPhoneSe))
assertSnapshot(matching: vc, as: .recursiveDescription(on: .iPhoneSe))
assertSnapshot(matching: vc, as: .image(on: .iPhoneSe(.landscape)))
assertSnapshot(matching: vc, as: .recursiveDescription(on: .iPhoneSe(.landscape)))
assertSnapshot(matching: vc, as: .image(on: .iPhoneX))
assertSnapshot(matching: vc, as: .recursiveDescription(on: .iPhoneX))
assertSnapshot(matching: vc, as: .image(on: .iPadMini(.portrait)))
assertSnapshot(matching: vc, as: .recursiveDescription(on: .iPadMini(.portrait)))
⚠️ 警告:必须使用与原始取参照的模拟器具有相同操作系统、设备范围和比例的模拟器来比较快照,以避免图像之间的差异。
更好的是,SnapshotTesting不仅限于视图和视图控制器!您可以从多种可用的快照策略中选择。
例如,您可以对URL请求进行快照测试(例如,您的API客户端准备的请求)。
assertSnapshot(matching: urlRequest, as: .raw)
// POST http://localhost:8080/account
// Cookie: pf_session={"userId":"1"}
//
// email=blob%40pointfree.co&name=Blob
您还可以对Encodable
值与它们的JSON和属性列表表示进行比较。
assertSnapshot(matching: user, as: .json)
// {
// "bio" : "Blobbed around the world.",
// "id" : 1,
// "name" : "Blobby"
// }
assertSnapshot(matching: user, as: .plist)
// <?xml version="1.0" encoding="UTF-8"?>
// <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
// <plist version="1.0">
// <dict>
// <key>bio</key>
// <string>Blobbed around the world.</string>
// <key>id</key>
// <integer>1</integer>
// <key>name</key>
// <string>Blobby</string>
// </dict>
// </plist>
assertSnapshot(matching: user, as: .dump)
// ▿ User
// - bio: "Blobbed around the world."
// - id: 1
// - name: "Blobby"
如果您的数据可以表示为图像、文本或数据,则可以为它编写快照测试!查看SnapshotTesting附带的所有快照策略,并了解如何定义您自己的自定义策略。
安装
Xcode 11
⚠️ 警告:默认情况下,Xcode会尝试将SnapshotTesting包添加到项目中主应用程序/框架目标。请确保如以下步骤中所述,将SnapshotTesting添加到测试目标中。
- 从
文件
菜单中,通过Swift Packages
,选择添加依赖包…
。 - 输入包仓库URL:
https://github.com/pointfreeco/swift-snapshot-testing.git
- 确认版本,并让Xcode解决包
- 在最终对话框中,更新SnapshotTesting的
添加到目标
列,以包含快照测试的测试目标(如果您有多个测试目标,您可以在稍后手动在构建阶段链接库,以将SnapshotTesting添加到它们)。
Swift包管理器
如果您要在任何使用SwiftPM的任何其他项目中使用SnapshotTesting,请将其添加到Package.swift
中的依赖项。
dependencies: [
.package(name: "SnapshotTesting", url: "https://github.com/pointfreeco/swift-snapshot-testing.git", from: "1.8.1"),
]
接下来,将SnapshotTesting
添加为测试目标的依赖项。
targets: [
.target(name: "MyApp", dependencies: [], path: "Sources"),
.testTarget(name: "MyAppTests", dependencies: ["MyApp", "SnapshotTesting"])
]
Carthage
如果你使用的是 Carthage,你可以在你的 Cartfile
中添加以下依赖项
github "pointfreeco/swift-snapshot-testing" ~> 1.8.0
⚠️ 警告:Carthage 会指导你将框架拖入你的 Xcode 项目中。Xcode 可能会自动尝试将这些框架链接到你的应用目标。SnapshotTesting.framework
仅与测试目标兼容,所以在你第一次将它们添加到项目中时
- 将
SnapshotTesting.framework
从可能添加的二进制目标(不包括测试目标)中移除。- 将
SnapshotTesting.framework
添加到任何相关的测试目标中。- 在相关的测试目标中添加一个 新的复制构建阶段,其 目标 设置为 "Frameworks",并将
SnapshotTesting.framework
添加到这一阶段作为项。- 不要在应用目标的 Carthage
copy-frameworks
运行脚本阶段 的 "输入文件" 或 "输出文件" 中添加SnapshotTesting.framework
。有关更多信息,请参阅 Carthage 的 "将框架添加到单元测试或框架" 文档。
CocoaPods
如果你的项目使用 CocoaPods,将 pod 添加到你的 Podfile
中任何相关的测试目标中
target 'MyAppTests' do
pod 'SnapshotTesting', '~> 1.8.1'
end
功能
- 数十种快照策略。快照测试不仅适用于
UIView
和CALayer
。你可以针对任何值编写快照。 - 编写你自己的快照策略。如果你可以将其转换为图像、字符串、数据或你自己的可比较格式,你就可以对它进行快照测试!从头开始构建你自己的快照策略或转换现有的策略。
- 无需配置。无需担心方案设置和环境变量。快照将自动与测试一起保存。
- 更少的手动操作。无论
isRecording
模式是否为true
,都会记录新快照。 - 无需子类化。从任何 XCTest 用例或 Quick spec 中断言。
- 设备无关的快照。从单个模拟器渲染特定设备和特性集合的视图和视图控制器。
- 一流的 Xcode 支持。图像差异作为 XCTest 附件捕获。文本差异在内联错误消息中渲染。
- 支持 Swift 支持的任何平台。为 iOS、Linux、macOS 和 tvOS 编写快照测试。
- 支持 SceneKit、SpriteKit 和 WebKit。大多数快照测试库不支持这些视图子类。
Codable
支持。将可编码的数据结构编码为其 JSON 和 属性列表 表示形式。- 自定义差异工具集成.
插件
-
swift-snapshot-testing-nimble 为 Nimble 添加了针对 SnapshotTesting 的匹配器。
-
swift-html 是用于创建类型安全、可扩展和可转换的 HTML 文档的 Swift DSL,包括用于进行 HTML 文档快照测试的
HtmlSnapshotTesting
模块。 -
GRDBSnapshotTesting 为使用 GRDB 创建的 SQLite 数据库迁移添加了快照策略。
-
AccessibilitySnapshot+SnapshotTesting 为 SnapshotTesting 添加了 AccessibilitySnapshot 支持。
你编写了自己的 SnapshotTesting 插件吗?在这里添加 并提交一个 pull 请求!
相关工具
-
iOSSnapshotTestCase
帮助将截图测试介绍给 iOS 社区的广大用户。使用该库的经验激发了本库的创建。 -
Jest 以精美的用户体验将通用的快照测试引入了 JavaScript 社区。本库的几个功能(差异、自动捕获新的快照)受到了直接影响。
了解更多
SnapshotTesting 是在 面向证人编程 思想指导下设计的。
在 Point-Free 这一视频系列中,这个概念(以及更多)得到了深入的探讨,该视频系列探讨了函数式编程和 Swift,由 Brandon Williams 和 Stephen Celis 主持。
在下面的 Point-Free 集中探讨了面向证人编程和本库的设计
- 第33集:协议证人:第一部分
- 第34集:协议证人:第二部分
- 第35集:高级协议证人:第一部分
- 第36集:高级协议证人:第二部分
- 第37集:面向协议的库设计:第一部分
- 第38集:面向协议的库设计:第二部分
- 第39集:面向见证的库设计
- 第40集:异步功能重构
- 第41集:快照测试综述
🆓
许可证
该库基于MIT许可证发布。详见LICENSE。