AddPreviews

GitHub Workflow Status codecov

@AddPreviews 使基于预览的 快照测试 更容易。

当应用于预览提供程序时,它...

  1. 通过从结构体内的静态视图属性派生视图的内容,自动创建 preview
  2. 使其预览提供程序可以通过其视图属性进行迭代,从而方便对每个预览状态进行快照覆盖。

使用方法

在预览中使用

只需 import AddPreviews 并将 @AddPreviews 附加到您的预览结构体。

import AddPreviews

@AddPreviews
struct MyView_Previews: PreviewProvider {
    static var stateOne: some View { MyView(state: .one) }
    static var stateTwo: some View { MyView(state: .two) }
}

这将生成一个 previews 属性,其中包含您的每个视图状态,以及显示名称,以便轻松识别您在 Xcode 中查看的是哪个状态。

// (Generated)
static var previews: some View {
    stateOne.previewDisplayName("stateOne")
    stateTwo.previewDisplayName("stateTwo")
}

在快照测试中使用

真正的神奇之处在于消除了 快照测试 中的样板代码。

@AddPreviews 使带注释的预览提供程序可迭代其每个视图属性,从而将快照测试从以下形式简化为:

import SnapshotTesting
import XCTest

final class MyViewTests: XCTestCase {
    func testStateOne() {
        assertSnapshot(of: MyView_Previews.stateOne, as: .image(layout: .device(config: .yourDevice)))
    }
    
    func testStateTwo() {
        assertSnapshot(of: MyView_Previews.stateTwo, as: .image(layout: .device(config: .yourDevice)))
    }
}

简化成这种形式 - 代码可以轻松地随着新预览状态的添加而扩展。

import SnapshotTesting
import XCTest

final class MyViewTests: XCTestCase {
    func testPreviews() {
        for preview in MyView_Previews() {
            assertSnapshot(of: preview, as: .image(layout: .device(config: .yourDevice)), named: preview.name)
        }
    }
}

您所要做的就是在添加或更改时重新记录快照,或者在删除预览状态时删除未使用的参考图像。

动机

为什么要创建特定的视图属性? 为什么不直接将不同的状态内联到预览属性本身中?

这种模式使编写设备尺寸视图的 快照测试 变得轻而易举,如上面所示

也就是说,这种模式最适合应该拥有自己的参考图像的屏幕大小的视图。 对于较小的视图,这种方法有点过头了,一个包含堆栈中多个状态的预览可以直接简单地编写和快照,如下所示

预览

struct RowView_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            RowView(title: "Title")
            RowView(title: "Title", subtitle: "Subtitle")
            RowView(title: "Title", subtitle: "Subtitle") {
                Image(systemSymbol: .envelopeFill)
            }
        }
    }
}

快照

final class RowViewTests: XCTestCase {
    func testPreviews() {
        assertSnapshot(of: RowView_Previews.previews, as: .image(layout: .device(config: .yourDevice)))
    }
}

#Preview 宏怎么样?

#Preview 很棒、简洁,并且被定位为 Xcode 预览的未来,但它不支持 PreviewProvider 那样的方式进行快照测试,如上所示。

使用 #Preview 会生成一个带有乱码类型名称的结构体,如下所示: $s17<YourTarget>33_5594AE1E7369B73F633885FC4E970BA7Ll7PreviewfMf_15PreviewRegistryfMu_

虽然从技术上讲可以引用此类型名称(尽管不建议这样做),但仍然没有可以从中提取出来并插入到快照测试中的 View。 关于 Xcode 如何将这些预览转换为视图,DeveloperToolsSupport 目前是一个黑盒。

许可

该库在 MIT 许可证下发布。 有关详细信息,请参见 LICENSE