UnitTest
以下内容属于个人见解,如有不恰当欢迎指正!
什么叫单元测试
对于面向对象来说,最基本的单元是类,对类的测试或者是对类中的方法测试,认为是 单元测试 。类中的方法特指 public 方法或者类方法,私有方法不做测试。
tip:若私有方法需要测试,那么私有方法一定含有概念性错误。
XCTest框架
1 | - (void) setUP; //在测试前设置好要测试的方法 |
其中测试方法的编写时有讲究的:
- 测试方法名必须是以test开头
- 测试方法没有返回值(void)
- 测试方法的调用顺序就是方法名字典序 eg:testA,testB。testA调用先于testB
XCTest中的几种断言,加入断言机制是为了使测试更加明确,我们预计程序错误或崩溃的条件,防止程序在运行到该位置时崩溃。
- XCTFail(format…) 生成一个失败的测试;
- XCTAssertNil(a1, format…)为空判断,a1为空时通过,反之不通过;
- XCTAssert(expression, format…)当expression求值为TRUE时通过;
…
expression 是在测试的时候确定的一个布尔表达式
测试demo
- 异步操作测试
具体通过XCTestExpection类和waitForExpectationsWithTimeout:handler:方法来实现对异步操作的测试
1 | -(void)testWebPageDownload |
其中框架会预计XCTestExpection在之后的某一时刻被实现。最终的程序完成代码块中的测试代码会调用XCTestExpection类中的fulfill方法来实现期望
若是请求时间超过时限,则会调用其error中的代码块,以至于无限制的等待一个无效的请求
辅助测试的第三方框架 OCMock
从名字的来看 OCMock 是仿制,伪造的意思,他的功能的确是伪造一个类,来解决测试过程中一些类难以实例化的问题,直接可以通过 mock 来伪造生成,降低系统业务和测试之间耦合
1 |
|
现在看Mock的源码比较吃力,大概的意思就是 动态创建一个类用它的元类(meta-class)作为mockedClass的元类,同时并创建改类的初始化方法。
OCMock中几个主要方法
- 任意类型的 mock
1 | id mockA = [OCMock mockForClass [A class]]; |
这种方式创建的mock对象,如果调用未stub的方法,会抛出一个异常。
这需要保证在mock的生命周期中每一个独立调用的方法都是被存根的。
- Nice Mock
1 | id niceMockA = [OCMock niceMockForClass[A class]]; |
如果你不想自己对很多的方法进行存根,那么使用nice mock。Nice mock是比较友好的,当一个没有存根的方法被调用时他不会引起一个异常
- Partial Mock
1 | id aMock = [OCMockObject partialMockForObject: [UIApplicationsharedApplication]]; |
当调用一个没有被存根的方法时,会调用实际对象的该方法。当不能很好的存根一个类的方法时,该技术是非常有用的。另外,对于单例类的mock也需要使用partialMock。
- Stub与Expect的使用
场景:假如我们的待测代码中有一个Car类,Car类中有一个方法为goFaster:units: ,我们的待测函数A需要传入一个Car对象,而A内部一些条件依赖于goFaster:units:的返回值。
stubbed methods(存根方法)
1 | id mockCar = [OCMockmockForClass[Car class]]; |
OCHamcrest
OCHamcrest 用于各种匹配,文本匹配,逻辑等等。他的github说的很清楚啦。
总结
测试其实很重要,老外对这种要求应该比较高,记得看过一篇blog中间一个项目的单元测试代码量比项目代码量还多,在很多人看来这是得不偿失的。作为一个小白,只能现在慢慢重视起来,特别在越大的项目中,单元测试或者时说测试就越重要,不做测试的结果就是项目做到后期bug堆积起来容易失控,这是很可怕的。就bb到这吧,欢迎到我的github上一起交流技术.