0%

iOS接口的单元测试

iOS接口的单元测试

近期把一个业务复杂,功能繁多的库进行了拆分,实现了功能的单一性。代码重构告一段落,功能验证并且提测了,在QA测试阶段,终于闲下来把单元测试的代码也进行拆分与补充了。

现在就来聊聊iOS代码的单元测试。

单元测试本质上就是对我们写的代码接口进行执行,传入特定的参数,返回执行结果,然后对比结果与期望的值是否一致,确定功能是否执行正确。

单元测试流程

不同于其他语言,Objective-C可以通过苹果官方的编辑器XCode提供的XCTest框架很方便的进行测试,可以不需要额外的第三方框架进行基础的单元测试。而JavaScript语言(jest)、C语言(CUnit)等需要专门的库才能作测试。

现在,我们公司iOS开发属于组件化开发,各个组件的代码都是在一个独立的库,工程通过cocoapods管理。这样有一个好处,就是每个库的功能单一,接口少,代码都是由特定的一个或者几个人员维护,开发人员对代码比较熟悉,单元测试都是可以对所有文件的接口进行覆盖测试,还可以通过Xcode直观的看到每个文件的测试覆盖率。在代码入库检视时,检视人把好单元测试的关,很容易推动他人对代码作单元测试,提高代码的质量。

下面讲一下我是如何作单元测试的

如何开始单元测试

每个组件库代码都是一个由cocoapods管理的workspace工程组织的,构建最终输出是一个个.a

  • 创建一个target, 类型为 iOS Unit Testing Bundle
  • 在target下创建一个文件,继承XCTTestCase, 编写单元测试代码
  • 工程选中对应的test target, 设置 Target Dependencies, Link Binart with Libraries 为库的target
  • 编译执行test target (快捷键 command + U)

每个测试用例的重复代码可以写在 setUp/tearDown方法里, 分别为公共前置代码编写、资源清理的处理。

异步接口测试

针对一些异步执行的接口, XCTest提供了XCTestExpectation来实现。

由于项目代码不便提供,这边请允许我偷个懒, 从SDWebImage库上摘录一些测试代码O(∩_∩)O哈哈~

在回调里面,根据传入的参数判断是否符合预期, 是则调用fullfil方法,否则调用报错。

添加文件测试

  • 添加文件到test target
  • 使用 bundleForClass:获取正确的bundle,再访问bundle路径下的具体文件。

使用OCMock进行代码mock

对于复杂的对象,可能会有许多成员。但是这些成员是不容易获得的, 我们可以通过OCMock模拟该成员,对部分函数进行打桩,达到期待的结果。

OCMock是一个库, 通过 podfile 引入该库, 然后根据文档进行操作。 具体文档可以访问链接

使用OHHTTPStubs 对网络接口进行mock

有些接口需要访问网络才能返回正常的结果,可以使用OHHTTPStubs这个库对网络请求进行打桩,根据请求的request确定是否要进行打桩。

查看代码覆盖率

  • 工程Edit Scheme -> Test -> Options -> Gather coverage for xxx
  • 跑一遍单元测试, 查看结果

更多

一般的接口功能的单元测试,掌握以上部分就可以了。 如果还有性能的测试、或者UI的测试可以看官网文档。

更多查看苹果文档

感想

为工程添加单元测试, 我们可能需要对已有代码进行重构, 使之可以是可被测试的。 通过单元测试代码的运行,可以很容易发现隐藏的问题, 不会引入新问题。 单元测试是代码质量的一个可靠的保障手段,好的团队应该对其代码进行单元测试。当然这里有巨大的工作量,但是是值得的。 以为本次代码重构的经历而言, 设计占2/5, 写代码4/15, 单元测试大概1/3. 比例大概为 6:4:5。 单元测试还是花了许多时间,但中间也发现了一些问题, 这些问题在前面功能自测的时候并没有发现,代码检视过程中也没有发现,单元测试的时候发现了,不枉我花了时间啊O(∩_∩)O哈哈~。 单元测试算是一个迭代的过程吧, 也有一点一劳永逸的感觉。

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。