框架选择

參考这篇选型文章,http://zixun.github.io/blog/2015/04/11/iosdan-yuan-ce-shi-xi-lie-dan-yuan-ce-shi-kuang-jia-xuan-xing/,尽管结论不一定全然适用,可是关于框架对照的地方还是值得阅读的。基于这篇文章,排除Kiwi框架之后,决定參考一些项目的源码,了解他们使用的測试方面的框架。


首先,參考https://github.com/artsy/eigen开源项目,其内部总体结构很完整,开发流程也很专业。至少比我知道的大多数国内团队都要专业:
eigen: Specta + OCMock + Expecta + OHHTTPStubs + FBSnapshotTestCase + "Expecta+Snapshots" + "XCTest+OHHTTPStubSuiteCleanUp”。

其次,參考公司内部别的项目使用情况。发现使用下面框架来做測试方面的事情: Specta + Expecta + OCMock + OHTTPStubs + KIF(UI Test)

so,我决定选择 Specta (BDD框架) + Expecta(断言框架) + OCMock(mock框架) + OHHTTPStubs(http stub框架) + KIF(UI Test) 做測试框架来学习。


XCTest简单介绍

因为我决定不直接使用XCTest作为測试框架。可是又因为Specta是基于XCTest进行封装的,所以对XCTest做一个基础的了解还是有必要的。
參考:


BDD框架 — Specta

1. 简单介绍

眼下主流的BDD框架,这些BDD框架在语法层面差点儿是同样的,基本的差别在于他们的可配置能力和绑定的组件。

以下三个OC BDD框架相对于官方框架XCTest都具有更好的可读性。另外如今已经有了比較流行的swift BDD框架:https://github.com/railsware/Sleipnir 和 https://github.com/Quick/Quick


关于specta与kiwi框架的对照,參考:http://appleprogramming.com/blog/2014/01/18/tdd-with-specta-and-expecta/,这篇文章的结论是specta相对于kiwi有更加优雅的语法,对于我这样的刚開始使用的新手,果断採用specta这样的各种完胜的框架。Specta框架具有一下特点:
  • An OC RSpec-like BDD DSL
  • Quick and easy set up
  • Build on top of XCTest
  • Excellent Xcode integration

2. Specta BDD DSL语法简单介绍

能够參考 https://github.com/specta/specta 官网和https://github.com/artsy/eigen项目中的test
case代码来学习语法
1) SpecBegin 声明了一个測试类。SpecEnd 结束了类声明
2) describe (context) 块声明了一组实例
3) it (example/specify) 是一个单一的样例
4) beforeAll 是一个执行于全部同级块之前的块,仅仅执行一次。afterAll 与beforeAll相反,是在全部同级块之后执行的块。仅仅执行一次。
5) beforeEach/afterEach,在每一个同级块执行的时候,都会执行一次,而beforeAll/afterAll仅仅会执行一次
6) it/waitUntil/done()。异步调用,注意完毕异步操作之后。必须调用done()函数。例如以下:
  • it(@"should do some stuff asynchronously", ^{

        waitUntil(^(DoneCallback done) {

          // Async example blocks need to invoke done() callback.

          done();

        });

      });

7) sharedExamplesFor 和 itShouldBehaveLike结合在一起。能够实如今不同的spec之间共享同一套test case,參考:http://artandlogic.com/2014/02/specta-shared-behavior/;sharedExamplesFor
设置多个spec之间共享的test case,第一个參数作为标识符。通过itShouldBehaveLike来执行spec中test case。第一个參数传入sharedExamplesFor设置时使用的标识符。注意。在describe局部使用sharedExamplesFor定义shared examples。能够在它作用域内覆盖全局的shared examples。

8) pending,仅仅打印一条log信息。不做測试。这个语句会给出一条警告,能够作为一開始集中书写行为描写叙述时还未实现的測试的提示。


断言框架 — Expecta


使用方法能够參考开源项目: https://github.com/artsy/eigen。从中找到相应的代码学习是最好的方式。假设须要找到很多其它更全面的使用方法,能够去项目官方站点:https://github.com/specta/expecta。截取一段eigen上面代码,基本上就能够了解Expecta框架的基本使用方法了,例如以下图中
expect(mapView.nextZoomScale).to.equal(mapView.annotationZoomScaleThreshold)





mock框架 —
OCMock


了解OCMock 2.x中的具体features。能够參考: http://ocmock.org/features/;了解OCMock 3.x的具体API。能够參考:http://ocmock.org/reference/


In a modern Object Oriented system, the component under test will likely have several object dependencies. Instead of instantiating dependencies as concrete classes, we use mocks. Mocks are ‘fake’ objects with pre-defined behavior to stand-in for concrete objects during testing. The component under test does not know the difference! With mocks, a component can be tested with confidence that it behaves as designed within a larger system. 

OCMock框架的使用方法也比較简单,因为我个人时间比較紧张,仅仅能抽出一两天的时间学习測试部分的知识,就不多说了,以下几篇文章都说的比較清楚,能够參考:http://zixun.github.io/blog/2015/04/16/iosdan-yuan-ce-shi-xi-lie-yi-ocmockchang-jian-shi-yong-fang-shi/ ,学习2.x和3.x的API的基本使用。

另外能够參考开源项目 https://github.com/artsy/eigen,学习当中的OCMock
API的使用,框架使用比較简单,看看就懂了,不须要多说。


eigen的一个test case,注意在运行完成的时候,须要调用stopMocking。OCMockObject是基于runtime方法转发实现的。mock一个对象,就是对这个对象的方法进行转发的过程,运行完成须要调用stopMocking,否则会影响其它test case的运行。

以下能够看出一个OCMock基本过程:获得OCMockObject -> stub方法 -> 设置expect ->
verify校验运行结果 -> 调用stopMocking


watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">


以下有一个mock一个alert view show的过程



參考:

OHHTTPStubs

官方:https://github.com/AliSoftware/OHHTTPStubs。这个框架是基于NSURLProtocol实现的。之前正好看过这部分的仅仅是,整理来说。这个框架的源码并不复杂,但实现还是比較巧妙的。具体的介绍和使用,在github上面介绍的很清楚,框架本身使用也比較简单:
[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {

  return [request.URL.host isEqualToString:@"mywebservice.com"];

} withStubResponse:^OHHTTPStubsResponse*(NSURLRequest *request) {

  // Stub it with our "wsresponse.json" stub file (which is in same bundle as self)

  NSString* fixture = OHPathForFile(@"wsresponse.json", self.class);

  return [OHHTTPStubsResponse responseWithFileAtPath:fixture

             headers:@{@"Content-Type":@"application/json"}];

}];
这个框架的主要用法就是上面这个演示样例,用法非常明显易用。结合unit test使用的时候。须要使用网络请求的时候。能够在it或者beforeAll或者beforeEach的时候进行stub request。即上面这段代码的行为。可是不要忘记的是。须要在tear down的时候,即specta的afterAll的时候,记得调用 [OHHTTPStubs removeAllStubs] 。
注意,这里仅仅是使用NSURLProtocol来stub request。不会影响被測试的请求接口的測试。请求是异步的话,能够使用Specta的it/waitUntil/done()流程对请求进行測试,假设使用XCTest的话,OHTTPStubs给出了一个wiki解决。使用XCTestExpectation来搞定。我认为挺有意思:
- (void)testFoo

{

  NSURLRequest* request = ...

  XCTestExpectation* responseArrived = [self expectationWithDescription:@"response of async request has arrived"];

  __block NSData* receivedData = nil;

  [NSURLConnection sendAsynchronousRequest:request

                                     queue:[NSOperationQueue mainQueue]

                         completionHandler:^(NSURLResponse* response, NSData* data, NSError* error)

   {

     receivedData = data;

     [responseArrived fulfill];

   }

  ];



  [self waitForExpectationsWithTimeout:timeout handler:^{

    // By the time we reach this code, the while loop has exited

    // so the response has arrived or the test has timed out

    XCTAssertNotNil(receivedData, @"Received data should not be nil");

  }];

}

因为NSURLProtocol的局限性。OHHTTPStubs没法用来測试background sessions和模拟数据上传。


F.I.R.S.T 原则

  • Fast — 測试应该可以被常常执行
  • Isolated — 測试本身不能依赖于外部因素或其它測试的结果
  • Repeatable — 每次执行測试都应该产生同样的结果
  • Self-verifying — 測试应该依赖于断言,不须要人为干预
  • Timely — 測试应该和生产代码一同书写
怎样将測试结果收益最大化:不要将測试和实现细节耦合在一起。
  • 不要測试私有方法
  • 不要Stub私有方法
  • 不要Stub外部库
  • 正确地Stub依赖
  • 不要測试构造函数

參考资料

iOS单元測试:Specta + Expecta + OCMock + OHHTTPStubs + KIF的更多相关文章

  1. iOS 单元測试之XCTest具体解释(一)

    原创blog,转载请注明出处 blog.csdn.net/hello_hwc 欢迎关注我的iOS-SDK具体解释专栏 http://blog.csdn.net/column/details/huang ...

  2. ios单元測试之GHUnit

    1.相同创建一个測试的project, 2.通过cocoaPod来下载GHUnit框架,或者到github上下载.由于这个框架是开源的第三方框架. 同一时候加入QuartCore.framework( ...

  3. [iOS翻译]《iOS7 by Tutorials》在Xcode 5里使用单元測试(上)

    简单介绍: 单元測试是软件开发的一个重要方面.毕竟,单元測试能够帮你找到bug和崩溃原因,而程序崩溃是Apple在审查时拒绝app上架的首要原因. 单元測试不是万能的,但Apple把它作为开发工具包的 ...

  4. 利用Continuous Testing实现Eclipse环境自己主动单元測试

    当你Eclipse环境中改动项目中的某个方法时,你可能因为各种原因没有执行单元測试,结果代码提交,悲剧就可能随之而来. 所幸infinitest(http://infinitest.github.io ...

  5. 在Eclipse中使用JUnit4进行单元測试(0基础篇)

    本文绝大部分内容引自这篇文章: http://www.devx.com/Java/Article/31983/0/page/1 我们在编写大型程序的时候,须要写成千上万个方法或函数,这些函数的功能可能 ...

  6. C语言单元測试

    C语言单元測试 对于敏捷开发来说,单元測试不可缺少,对于Java开发来说,JUnit非常好,对于C++开发,也有CPPUnit可供使用,而对于传统的C语言开发,就没有非常好的工具可供使用,能够找到的有 ...

  7. OpenStack中给wsgi程序写单元測试的方法

    在 OpenStack 中, 针对web应用, 有三种方法来写单元測试 1) 使用webob生成模拟的request from __future__ import print_function imp ...

  8. Android单元測试之JUnit

    随着近期几年測试方面的工作慢慢火热起来.常常看见有招聘測试project师的招聘信息.在Java中有单元測试这么一个JUnit 方式,Android眼下主要编写的语言是Java,所以在Android开 ...

  9. 让你提前认识软件开发(19):C语言中的协议及单元測试演示样例

    第1部分 又一次认识C语言 C语言中的协议及单元測试演示样例 [文章摘要] 在实际的软件开发项目中.常常要实现多个模块之间的通信.这就须要大家约定好相互之间的通信协议,各自依照协议来收发和解析消息. ...

随机推荐

  1. 2017-2018-1 JAVA实验站 第八周作业

    2017-2018-1 JAVA实验站 第八周作业 详情请见团队博客

  2. oracle复杂查询是sql

    一.over()分析函数 分组查前几条:select * from test t where (select count(*) from test a where t.type=a.type and ...

  3. UVA 11947 Cancer or Scorpio 水题

    Cancer or Scorpio Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://uva.onlinejudge.org/index.php? ...

  4. php模块组成

    php总共有三个模块:内核.ZEND引擎.扩展. 内核是用来处理请求.文件流.错误处理等操作的: ZEND引擎是将源文件转换成机器语言,然后在虚拟机上运行: 扩展层是一组函数.类库和流,php使用它们 ...

  5. Lucene——索引的创建、删除、修改

    package cn.tz.lucene; import java.io.File; import java.util.ArrayList; import java.util.List; import ...

  6. Running CMD.EXE as Local System(转)

    Many times in the past I had to run an interactive command-line shell under the Local SYSTEM account ...

  7. HDU 4716 A Computer Graphics Problem (水题)

    A Computer Graphics Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (J ...

  8. MVC实现多选下拉框

    借助Chosen Plugin可以实现多选下拉框. 选择多项: 设置选项数量,比如设置最多允许2个选项: 考虑到多选下拉<select multiple="multiple" ...

  9. jsondataobjects

    jsondataobjects GITHUB: https://github.com/ahausladen/jsondataobjects.git 跨平台JSON库 Json Data Objects ...

  10. 正则表达式校验15/18位生份证-JAVA版

    public static boolean isIDNumber(String iDNumber) { if (iDNumber == null || "".equals(iDNu ...