初识单元测试

上一篇文章讲到了行为,行为具有职责单一性,所以易于测试。那到底有多易于测试呢?我较了一次真想写写看,也是第一次写单元测试,所以记录一些自己的感受~

网上有很多文章介绍单元测试,但是大部分都是讲如setUp()tearDown()等是什么时候调用的,怎样写一个测试用例,然后举个很简单的例子说明一下。还有一部分文章会讲到用单元测试去测试API接口部分,但发现照葫芦画瓢的,也就只会用它来测试这部分。我以为已经了解了,然后开始想在自己的项目里去用,竟发现居然无从下手!到底要测试什么呢?似乎有些逻辑肯定是对的,不需要测,那要测试一些复杂流程的输入和输出是否正确吗?我不甘心呀,继续用搜索引擎变换着关键词去找😤,后来再一些文章中看到说测试行为,不要测试细节。有比较大的启发,我想我们在写单元测试的时候就要变换自己的角色了,站在tester或者user的角度去想,他们关注什么呢。下面就说一说我给在上一篇文章中讲到的Behavior写的单元测试,Demo地址:https://github.com/shinancao/BehaviorDemo

  • CheckCodeBehaviorTests

对于CheckCodeBehavior的测试相对还好入手一点,从整个功能上的表现我需要验证这些情况是正确的:

  1. 输入错误的手机号码时,发送验证码按钮不可用。
  2. 输入正确的手机号码时,发送验证码按钮变为可用。
  3. 点击发送验证码按钮后,按钮变为不可用,并且title显示正在倒计时。
  4. 倒计时结束后,按钮的title会变为发送验证码

接着再测试一下如果别人正确配置了CheckCodeBehavior,那它的表现是否会如预期一样:

  1. 设置cornerRadius时,按钮的圆角是否变为相应值。
  2. 设置borderWidth时,按钮的边框是否变为相应值。
  3. 设置normalTitleColordisableTitleColor时,按钮在正常状态下和不可用状态下的titleColor是否正确。
  4. 设置initialState为1时,按钮的样式是否为可用的样式。
  5. 设置initialState为0时,按钮的样式是否为不可用的样式。

想好要测试什么,写的过程就不是事儿啦😄。

  • ImagePickerBehaviorTests

运用同样的想法来写ImagePickerBehavior的测试用例,于是我想到的是用例是:

  1. 点击按钮时弹出了UIAlertController
  2. 弹出的UIAlertController的标题分别是相册相机取消
  3. 点击相册时,相册打开了。
  4. 点击相机时,相机打开了。
  5. 点击取消时,UIAlertController消失了。

1、2还是轻松实现了,3、4、5就犯难了,UIAlertController并没有将按钮被点击了的消息放出来,也没有啥hack的方法能够监听到那个按钮被点击了。通过迂回的办法还是可以做的,我找到了一篇介绍:传送门。但是这要改变我主程序的代码呀!UIAlertController在我原来的程序中只是一个临时变量,也确实没必要把它写成一个全局变量,但是为了写测试用例必须要把它弄成一个全局变量。这就有一点为了测试而测试了,有点教条主义了。再来看一下是否真的有必要写测试用来呢,对于这5点,只要运行一下程序,点下按钮就看的一目了然了。还有BackgroundGradientBehaviorNavBarGradientBehavior,直接运行起来看效果更直观一些。也许对于这种偏界面的、有动画交互的效果,确实不适合写测试用例,所以这2个我就都没写。(哈哈,理由找的还不错吧😆)但是UI方面的东西还是一样可以用XCTest来测试的,我们也应尽量来测试,如这篇文章所讲的,自己权衡吧。

王垠的这篇文章:测试的道理讲的还是非常好的,如果你打算开始写测试用例了,强烈建议你看一看。对于测试,不能太教条。

  • GoodsDetailBehaviorTests

GoodsDetailBehavior的测试就相对简单一些了,就是看能否正常接收通知,各个控件是否被正常的赋值。

  • MultipleProxyBehaviorTests

MultipleProxyBehavior的测试也相对简单,就是看是否正常的实现了多路代理。

这样的测试看似简单,但是还是值得写,便于我们开始时调试逻辑,免得改一点东西就要编译运行一下程序,然后再创造出各种条件,才能验证。

以上的所有这些测试用例,看起来都测试的是一个小功能点的各种情况,也能比较分析出来要测试什么,这都是因为一个Behavior的职责单一性。你可以回头去看看你的ViewController,要对其写测试用例,是不是都觉得无从下手,很难清晰的列出来要测哪些,测了之后就能保证逻辑没问题了。

初步经验总结

  • 测试行为,不要测试细节。功能的实现细节变的可能性非常大,一定实现变了,那测试又要跟着变,没有多大必要写。真正要关注的是,我们究竟要要得到什么效果。
  • 从开发的角度转换到测试或者用户的角度去思考。如此,我们就能从我们自己写的代码中跳出来了,别管你咋实现的,就问你实现了没有。
  • 功能模块保持职责单一。开发时就要尽量做到这一点,这样才能有明确的输入和输出,便于我们分析测试用例。
  • 测试用例保持简单。单元测试来测试我们开发的功能代码了,那单元测试的代码谁来测试呢?所以尽量的保持每个用例的实现简单,才能让用例代码本身出错的几率变小。

其路漫漫

在这个摸索的过程中,我还了解到了测试中的MockStub这些术语,Objective-C有比较成熟的Mock框架,像OCMock,但是Swift目前好像还没有。以后随着使用的加深再一点点总结经验~

转载请注明出处:

作者:意林

原文链接:http://shinancao.github.io/2017/01/12/iOS-Tester-1/

–End–