iOS UI 使用模拟和屏幕截图进行测试

iOS UI Testing with Mocks and Screenshots

我想用 iOS 设置一个 UI 测试系统,它允许我只测试一个 ViewController 或 UIView 这样

a) 我可以为它提供模拟数据 b) 我可以将它的视图呈现给模拟器 c) 我可以截取它的屏幕截图,将其保存到磁盘并聚合快照(如快照)

为什么? 1) QA 团队想要快速验证 UI 的外观是否仍然符合他们应有的样子 2) 我们希望能够快速迭代位于深处的复杂编程视图的外观,而 Interface Builder 无法以任何有意义的方式支持它。

Xcode 7 UI 测试不适合此目的,因为您实际上无法编译任何原始代码。

Logic XCTest 框架似乎更合适,但可以理解的是,它不愿意在屏幕上呈现任何内容。我不在乎:我想要在屏幕上呈现一些东西。

请不要再对一个真正的 TDD 和 UI 与逻辑测试进行教条式的哲学谩骂。使用 Android Studio 完全可以做到这一点,我已经成功地使用了它。

在此先感谢您的帮助。

例子

Model * model = [[MockModel init] alloc]
model.value = @(10)

UIViewController * importantViewController= [[ImportantViewController alloc] initWithModel:model];

TestAppDelegate *appDelegate = (TestAppDelegate *)[UIApplication sharedApplication].delegate;

UINavigationController *navController = (UINavigationController*)appDelegate.window.rootViewController;

[navController pushViewController:importantViewController animated:NO];

TakeSnapshot("Important01")

Facebook 创建了一个优秀的库 iOS-Snapshot-Test-Case 来对 UIViews 和 CALayers 进行快照测试。使用它您可以创建单元测试,生成您的视图的 .png 文件并将它们与之前生成的(已知良好的)示例进行比较。

所有渲染都在屏幕外完成,速度非常快。但它没有对测试 UIViewController 的内置支持。因此,您可能需要做一些按摩才能使其正常工作,这不会比确保已实例化根视图并使用合理的(设备大小)框架进行布局更复杂。

有一点要注意。无论出于何种原因,Facebook 认为没有必要允许您在编写测试时定义设备分辨率(1x、2x、3x)。因此,您需要注意记录的设备和 运行 您的测试。

正如您在问题和评论中所述,您想要:

  1. 测试一个UI视图或UIViewController
  2. 为其提供“模拟”数据
  3. 将视图呈现为可写入磁盘的图像。

您有三组不同的选项:

应用测试

应用程序测试启动应用程序并将测试包注入其中。这样可以在测试中最大程度的控制。大多数应用程序会在应用程序生命周期的早期执行一些设置步骤,这会“弄脏”测试环境。您可以按照 this answer 中的指导或创建最小的应用程序目标进行测试。

在您的测试中,您可以根据自己的喜好创建“模拟”模型对象,并将它们传递给视图或视图控制器。在应用程序测试中,您可以通过在根视图控制器中添加或删除视图、提供您自己的根视图控制器或以模态方式呈现视图控制器来自由更改测试中的视图层次结构。如 Technical QA 1817: View Snapshots on iOS 7.

所述,截图非常简单

UI 测试

UI 测试的过程类似于应用程序测试。您与视图层次结构的大部分交互是通过 UI 测试代理对象,这可以限制测试的可行性或不可行性。 UI 测试允许您记录、回放和编辑与用户界面的交互——这是它的主要好处。根据您的问题,这可能对您没有多大用处。就像应用程序测试一样,对于 UI 测试,您需要能够为测试创建一个“干净”的环境。

UI 自动化

UI 自动化是 UI 测试的前身(UI 测试基于 UI 自动化)。就像 UI 测试 UI 自动化允许播放、记录和编辑与应用程序用户界面的交互。 UI 自动化,不像 UI 测试,运行s 在 Xcode in Instruments 之外 - 这给你模拟对象等的自由度要小得多,尽管这仍然可以通过启动参数和其他将参数传递给被测应用程序的方法。 UI 自动化使截图变得相当容易。

The Xcode 7 UI Testing does not suit this purpose since you cannot actually compile any of the original code.

当构建 UI 测试或应用程序测试时,它们依赖于应用程序目标。当测试 运行 时,它们将被注入到作为依赖项构建的应用程序中。所以被测应用程序和测试本身的原始代码实际上是编译过的 运行.