有很多开发人员要么避免要么不相信你可以测试 UIViewControllers。 Apples poor testing doco 对此也无济于事。
UIViewController 可以通过多种方法进行测试。
首先,正如任何人都会告诉你的那样,尝试将业务逻辑排除在视图控制器之外。试着让它只是加载视图,尽可能少地加载。从 MVC 架构更改为其他架构可能对此有所帮助。根据您正在构建的内容,您可能还需要考虑使用自定义 UIView 类来提供帮助。
纯单元/逻辑测试
您正在处理 Apple 所谓的“逻辑测试”,即没有分配可执行文件的测试目标。您仍然可以进行很多测试。包含简单视图处理代码的方法可以通过手动设置视图或使用测试代码手动加载 xib 文件等方式进行测试。OCMock 等模拟框架也非常有用。
通常,在这些类型的测试中,您最终需要手动执行各种生命周期方法来执行您想要测试的代码。例如,如果您想测试 viewDidLoad 方法:
id mockView = OCMClassMock([UIView class]);
// Setup mock expectations.
myViewController.view = mockView;
[myViewController viewDidLoad];
应用测试
如果您正在使用设置应用程序的测试目标,那么您实际上可以通过单元测试进行一些测试,而无需尝试导航应用程序。这有点作弊,但我发现它有时非常有用。
UIView *myView = // ... load the view manually or simply [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)]
myViewController.view = myView;
[[UIApplication sharedApplication].keyWindow addSubview:myView];
如果您采用这种方法,请务必删除拆解中的视图。这样做的好处是,围绕在屏幕上获取视图的所有生命周期方法都会自动为您调用。
大多数情况下,我发现这对于测试与视图控制器和自定义视图相关的东西很有用,这些视图与属于大屏幕布局的一部分的视图相关。没有那么多顶级视图控制器。
界面测试
最后是 Apple 提供的新 UI 测试框架。我过去使用过诸如 Frank 和 Calabash 之类的第 3 方 Ruby 框架。事实证明,Apple 的 UI 测试实际上非常好,并且与这些工具相当。
它的诀窍是使用它来构建一个有意义的方法库,并帮助描述(使用 DSL)应用程序的各个方面。
这种方法的缺点是您不能只加载要测试的视图。您必须实际运行该应用程序并导航到它。另一个主要缺点是它非常基于应用程序的基于外部可访问性的视图。进入内部几乎是不可能的,因此测试是基于应用在屏幕上的行为而不是内部类。
到目前为止,我还没有探索过混合这种测试形式并手动将视图加载到窗口上的想法,但我不明白为什么这不起作用。