测试苹果MVC

苹果公司针对iOS应用程序的官方主要设计模式是模型视图控制器。 该模式包含一个模型(包含我们的数据),一个视图(显示数据)和一个控制器(将所有内容粘合在一起)。 从他们的角度来看,一切都可以归为这三个组成部分之一。 因此,让我们看看如何测试每个组件。

模型

该模型包含工作所需的数据。 不过要小心; 它不包含仅与视图相关的任何数据,例如按钮显示的文本。 相反,它可能是核心数据存储或游戏系统。

这意味着我们已经知道如何测试模型。 模型公开了一个api(方法,属性等),并且不需要任何额外的工作来设置测试。

视图

对于视图,我们必须假设Apple负责将物理交互转换为数据并将其传输到屏幕/视图的正确位置。 有了这个假设,我们可以创建我们要测试的两种视图数据:

  • 静态的
  • 更换零件

我们可以通过创建屏幕快照来测试静态部件,然后将当前屏幕快照与此进行比较,但老实说,这对于UX来说是有用的。 作为开发人员,我认为只要专注于视图的不断变化的部分和交互作用就可以了。 有趣的是,这导致我们必须测试控制器,因为它正在传达交互作用。

控制者

让我们开始研究应用程序的功能。 在iOS中,它称为ViewController。 该控制器接受事件,控制逻辑并使我们的应用程序正常工作。 所有这些功能都留下了“难以测试”的印象。 至少它对我有用。 如果您认为iOS具有两种不同类型的InterfaceBuilder创建视图,它将变得更加强大。 那么为什么它似乎很难测试?

  • 它做的很多,这意味着要进行大量的测试和进行交互的各个部分。
  • 如何测试视图生命周期的方法?
  • 特定于视图的方法,例如tableView(tableView:didSelectRowAt 🙂
  • 如何测试IBAction?
  • 如何测试IBOutlets?

让我们解决所有这些问题。

它做很多

听起来很糟糕,确实如此。 在大多数情况下,您需要考虑重构代码。 如果您无法减少代码中的功能量,它仍然不会阻止您进行测试。 一开始只是令人恐惧,您可能想在此过程中进行重构。

如何测试视图生命周期的方法?

有两种意见。 一种是您以与其他所有操作相同的方式来称呼它们。 只要您没有引用IBOutlets的代码,您甚至都可以自己经历整个生命周期。
另一个选择是从这些函数中提取所有代码,然后调用它们。 这样,您始终可以确保小型逻辑代码片段能够按预期的方式运行。 因此,这与我们在其他地方所做的相同。

特定于视图的方法

听起来很奇怪,但最终它们只是功能。 在这种情况下,它们是公共的,因此您不必创建类别并添加它们。

IB动作和IBOutlets

IBActions只是方法。 给他们打电话!
另一方面,IBOutlets需要ViewController来扩大视图并设置所有Outlets。 一旦完成,就可以使用与属性相同的方式进行测试。 所以问题是:如何为视图充气? 无需再费周折…

在单元测试中加载ViewController

苹果很好。 它们为我们提供了两种在InterfaceBuilder中创建视图的方式。 但这也带来了能够测试两种视图的必要性。 Xib是Apple创建视图的旧方法。 您有一个视图并通过以下方式加载它:

 testViewController = TestViewController (nibName:"OfferDetailViewController", bundle: nil) 
  _ = testViewController.view 

小属性“视图”将启动整个“视图-生命周期”,从而还设置了IBOutlets。

好的,有些人可能会说Xib是旧的方式(我知道有些程序员对此表示反对)情节提要如何? 这有点棘手。 您必须加载情节提要,然后加载视图。 更棘手的是,您必须为ViewController输入一个Storyboard ID。 否则,您将无法在情节提要中找到它。

那么,代码看起来像什么来使故事板视图膨胀呢?

 let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil) 
let testVC = storyboard.instantiateViewController(withIdentifier: "TestViewController")
  _ = testVC.view //从iOS 8开始,这对于情节提要也是必要的 

结论

我们可能没有在应用程序中使用MVC作为体系结构,但是开始考虑不同组件的可测试性仍然是一个不错的选择。 它们趋于相似,并且与MVC中一样,UI也会出现相同的问题。

下一页:关于网络

Previous:Swift中的单元测试