单元测试ViewController的生命周期

时间:2015-02-26 20:04:06

标签: ios objective-c unit-testing uiviewcontroller

我正在为ViewControllers编写单元测试。 viewDidAppear:,viewWillAppear:等方法的最佳实践是什么

我正在使用调用viewDidLoad的[vc view]。但除了viewDidLoad之外,我应该如何对其他生命周期方法进行单元测试。对它们进行单元测试是否常见?直接调用它们是否有意义?像:

[vc viewWillAppear:NO];
[vc viewDidAppear:NO];

由于

2 个答案:

答案 0 :(得分:4)

有很多开发人员要么避免也不相信你可以测试UIViewControllers。 Apples poor testing doco对此也没有帮助。

UIViewControllers可以通过多种方法进行测试。

首先,正如任何人都会告诉你的那样,尝试将业务逻辑保留在视图控制器之外。尝试使它只是加载视图,尽可能少。从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];

如果采用这种方法,请务必删除拆解中的视图。这样做的好处是可以自动为您调用在屏幕上获取视图的所有生命周期方法。

大多数情况下,我发现这对于与视图控制器和自定义视图相关的测试内容非常有用,这些视图与作为较大屏幕布局的一部分的视图相关。与顶级视图控制器不同。

UI测试

最后,Apple提供了新的UI测试框架。我过去曾使用过像Frank和Calabash这样的第三方Ruby框架。事实证明,Apples UI Testing实际上相当不错,而且与这些工具相当。

使用它的技巧是使用它来构建一个有意义的方法库,并帮助描述(使用DSL)应用程序的各个方面。

这种方法的缺点是您不能只加载要测试的视图。您必须实际运行该应用程序并导航到它。另一个主要缺点是它非常基于您的应用程序的基于外部可访问性的视图。几乎不可能进入内部,因此测试是基于屏幕行为的应用程序而不是内部类。

到目前为止,我还没有探讨过混合这种形式的测试和手动将视图加载到窗口的想法,但我不明白为什么这样做不起作用。

答案 1 :(得分:3)

您只感受到iOS ViewControllers的一大亮点:他们对可测试性感到厌恶

  

MVC的另一个大问题是它阻碍了开发人员   写单元测试。由于视图控制器混合视图操作逻辑   使用业务逻辑,为了这个组件而分离出这些组件   单元测试成为一项艰巨的任务。许多人忽视的任务   赞成......只是没有测试任何东西。

source

不要测试UIKit!你应该测试自己的逻辑。将逻辑放入VC中会使测试变得非常困难。尝试把它放在其他地方并单独测试它。答案是:你应该通过调用UIKit方法来避免测试 - 特别是这些方法不能直接调用!

如果你从ViewController中获得了所有的逻辑,那么它真的会变成一个视图:一个在屏幕上显示某些东西的哑类。那里应该没什么可测试的。

也许您应该考虑使用MVVM / MVP / VIPER。请阅读提供的链接,它将解释所有。

相关问题