一个构建在 Xcode 预览之上的全功能快照测试解决方案。自动生成可浏览的预览图库,并且无需编写代码即可使用 XCTest 生成快照。支持使用 PreviewProvider
或 #Preview
的 SwiftUI 和 UIKit 预览,并适用于所有 Apple 平台 (iOS/macOS/watchOS/tvOS/visionOS)。
PreviewGallery
,无需 Xcode。PreviewGallery
是一个构建在快照提取之上的交互式 UI。它将你的 Xcode 预览变成一个组件和功能图库,你可以从你的应用程序中访问,例如在内部设置屏幕中。无需 Xcode 即可查看预览。 你可以使用它来预览单个组件(按钮/行/图标等),甚至整个交互式功能。
PreviewGallery 的公共 API 是一个名为 PreviewGallery
的 SwiftUI View
。显示此视图可让你访问完整的图库。例如,你可以添加一个按钮来打开图库,如下所示:
import SwiftUI
import PreviewGallery
struct InternalSettingsView: View {
var body: some View {
NavigationStack {
Form {
Section("Previews") {
NavigationLink("Open Gallery") { PreviewGallery() }
}
}
}
.navigationTitle("Internal Settings")
}
}
在 XCTest 中,无需编写任何代码即可为每个 Xcode 预览生成 PNG。将你的 XCTest 目标链接到 SnapshottingTests
,并创建一个继承自 SnapshotTest
的测试,如下所示:
import SnapshottingTests
class DemoAppPreviewTest: SnapshotTest {
// Return the type names of previews like "MyApp.MyView._Previews" to selectively render only some previews
override class func snapshotPreviews() -> [String]? {
return nil
}
// Use this to exclude some previews from generating
override class func excludedSnapshotPreviews() -> [String]? {
return nil
}
}
请注意,没有测试函数;它们在运行时由 SnapshotTest
自动添加。你可以从 snapshotPreviews()
函数返回预览列表,基于你想要在本地验证的预览。快照将被添加为 Xcode 测试结果中的附件。
注意
当你使用 Preview 宏 (#Preview("Display Name")
) 时,快照的名称使用文件路径和名称,例如:"MyModule/MyFile.swift:Display Name"
EmergeTools 快照测试服务 在云端生成快照并进行差异比较,以控制不稳定因素的来源,将图像存储在 git 之外,并优化测试性能。SnapshotTest
用于在本地调试这些快照测试。你还可以使用 PreviewLayoutTest
来获取单元测试中所有预览的代码覆盖率,而无需生成 PNG。这将验证预览不会崩溃(例如缺少 @EnvironmentObject),但运行速度更快,因为它不会将视图渲染为图像。
Xcode 可访问性审核 也可以在本地对任何预览运行。它们在 UI 测试(而不是单元测试)中运行。要启用这些,请继承自 AccessibilityPreviewTest
。要自定义行为,你可以在你的测试中覆盖以下函数:
import SnapshottingTests
import Snapshotting
class DemoAppAccessibilityPreviewTest: AccessibilityPreviewTest {
override func auditType() -> XCUIAccessibilityAuditType {
return .all
}
override func handle(issue: XCUIAccessibilityAuditIssue) -> Bool {
return false
}
}
有关完整的示例,请参阅演示应用程序。
XCTest 通过使用 Objective-C 运行时创建函数并覆盖 XCTest 的 testInvocations
函数来动态插入测试函数。
通过解析 __swift5_proto
Mach-O 部分来发现二进制文件中的预览,以查看哪些类型符合 PreviewProvider
(以及由 #Preview 宏生成的类似协议)。有关这在 Swift 运行时中如何工作的详细信息,请参阅我们的博客文章。
使用此存储库的 URL (https://github.com/EmergeTools/SnapshotPreviews) 将包依赖项添加到你的 Xcode 项目。
将你的应用程序链接到 PreviewGallery
和(可选)SnapshotPreferences
,以自定义快照生成行为。将你的 XCTest 目标链接到 SnapshottingTests
。
强烈建议为每个预览使用显示名称,例如:
struct MyView_Previews: PreviewProvider {
var previews: some View {
MyView().previewDisplayName("My Display Name")
// Note if you had more than one view here they should all have different display names.
}
}
#Preview("My Display Name") {
MyView()
}
显示名称将显示在 XCTest 结果和 EmergeTools UI 中。显示名称在每个 PreviewProvider 中或在预览宏的文件中应该是唯一的。
建议在你的单元测试 scheme 中将环境变量 EMERGE_IS_RUNNING_FOR_SNAPSHOTS
设置为 1
。当从 EmergeTools 快照测试服务生成快照时,也会设置此变量。像这样将其与 Xcode 预览变量结合使用:
extension ProcessInfo {
var isRunningPreviews: Bool {
environment["EMERGE_IS_RUNNING_FOR_SNAPSHOTS"] == "1" || environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1"
}
}
检查 ProcessInfo.isRunningPeviews
以禁用你不希望在预览中出现的行为,例如发出日志数据。
提示
使用 PreviewVariants 可以大大简化快照测试,方法是确保一组一致的变体,并确保为每个视图提供一个名称。
使用同一视图的多个变体可以确保测试覆盖用户与你的 UI 交互的所有方式。 大部分由 SwiftUI 提供,例如:.dynamicTypeSize(.xxxLarge)
。 包中内置了一个:.emergeAccessibility(true)
。 此函数将旁白元素的 可视化添加到您的快照。 您可以使用示例应用程序中演示的PreviewVariants
视图自动添加变体。它添加了RTL、横向、辅助功能、深色模式和大文本变体。您可以这样使用它
struct MyView_Previews: PreviewProvider {
static var previews: some View {
PreviewVariants(layout: .sizeThatFits) {
MyView(mode: .loaded)
// PreviewVariants requires that every view has a name, so you can’t create one without a display name
.previewVariant(named: "My View - Loaded")
MyView(mode: .loading)
.previewVariant(named: "My View - Loading")
MyView(mode: .error)
.previewVariant(named: "My View - Error")
}
}
}