ios - 单元测试 ViewController 的生命周期

标签 ios objective-c unit-testing uiviewcontroller

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

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

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

谢谢

最佳答案

有很多开发人员避免或不相信您可以测试 UIViewController。 Apples poor testing doco对此也无济于事。

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

首先,正如任何人都会告诉您的那样,尝试将业务逻辑置于 View Controller 之外。尽量让它只加载 View ,尽可能少地加载其他内容。从 MVC 架构更改为其他架构可能对此有所帮助。根据您正在构建的内容,您可能还需要考虑使用自定义 UIView 类来提供帮助。

纯单元/逻辑测试

我正在处理 Apple 所说的“逻辑测试”,即没有分配可执行文件的测试目标。你仍然可以测试很多。包含简单 View 处理代码的方法可以通过手动设置 View 或使用测试代码手动加载 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];

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

大多数情况下,我发现这对于测试与 View Controller 和自定义 View 相关的内容很有用,这些 View 与属于大屏幕布局的 View 相关。没有那么多顶级 View Controller 。

界面测试

最后是 Apple 提供的新 UI 测试框架。我使用了第 3 方 Ruby 框架,例如 Frank 和 Calabash在过去。事实证明,Apple 的 UI 测试实际上非常好,并且与这些工具相当。

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

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

到目前为止,我还没有探索混合这种测试形式和手动将 View 加载到窗口上的想法,但我不明白为什么这行不通。

关于ios - 单元测试 ViewController 的生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28751723/

相关文章:

ios - 在iOS上很长的NSString中进行大量NSRange调用的最快方法是什么?

iphone - 如何在 iOS 的地址簿中检查和检索更改/新添加的联系人详细信息?

objective-c - 当我使用 RegisterEventHotKey (Cocoa) 时,为什么在查找器中复制并粘贴不起作用?

unit-testing - 如何对具有关系映射的 grails 域类进行单元测试?

ios - 交易成功但下载内容时一直要求输入密码

iOS AVExportSession 失败,仅显示经过修剪的视频

ios - 当我从 unity 在 Xcode 上构建应用程序时,我在 Xcode 11 上收到 _ShowToast 错误

ios - 在 iOS 中显示按钮而不是固定在 map 上

python - 如何将 sqlalchemy.exc.IntegrityError 添加为模拟对象的副作用?

c# - Visual Studio 单元测试代码覆盖异常 "file path of .coverage file is invalid or corrupt"