XCTest

1.第一个单元测试

XCTest是Xcode 5中自带的测试框架

下面从一个Demo开始。首先用Xcode新建一个工程UnitTestDemo,工程目录结构如下:

可以看到工程下面多了一个叫UnitTestDemoTests的部分,Targets也多了一个UnitTestDemoTests,根据图标初步认为该Target跑的是一个框架。

这两个多出来的东西(相比Xcode 4没有Include Unit Tests的工程)就是用来做单元测试的,其特点是文件名或Target名都以Tests结尾。

再来看下UnitTestDemoTests.m中的代码:

  1. #import <XCTest/XCTest.h>
  2.  
  3. @interface UnitTestDemoTests : XCTestCase
  4.  
  5. @end
  6.  
  7. @implementation UnitTestDemoTests
  8.  
  9. - (void)setUp
  10. {
  11. [super setUp];
  12. // Put setup code here. This method is called before the invocation of each test method in the class.
  13. }
  14.  
  15. - (void)tearDown
  16. {
  17. // Put teardown code here. This method is called after the invocation of each test method in the class.
  18. [super tearDown];
  19. }
  20.  
  21. - (void)testExample
  22. {
  23. XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
  24. }
  25.  
  26. @end

  该类继承自XCTestCase类,其中包含 三个方法:setUp,tearDown和testExample。

setUp方法用于在测试前设置好要测试的方法,tearDown则是在测试后将设置好的要测试的方法拆卸掉。

testExample顾名思义就是一个示例。

按快捷键Command + U进行单元测试,结果如下:

可以看到没有通过测试,在Issue Navigator和控制台都输出了错误信息:本类中的testExample方法没有实现。

实际上,这个错误是我们主动抛出来的。XCTFail是一个宏,其作用就是让测试失败,后面的No implementation for \"%s\"", __PRETTY_FUNCTION__就是要报告的错误信息,由我们自定。

报错总是让人不爽,好吧,我们将其注释掉,另外写一个测试方法,尝点甜头。为了规范,建议每个测试方法都写成“ - (void)testXXX ”形式,XXX表示要测试的方法名,并且无返回类型。

  1. //- (void)testExample
  2. //{
  3. // XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
  4. //}
  5.  
  6. - (void)testTrue {
  7. XCTAssert(1, @"Can not be zero");
  8. }

  Command + U ,搞定:

注意左边的 Test Navigator, 绿色的标志表示 测试全部通过。

2.测试的顺序

如果在同一测试类文件中多写几个方法,例如:

  1. - (void)testTrue2 {
  2. NSLog(@"2222222222222222222222");
  3. XCTAssert(1, @"Can not be zero");
  4. }
  5.  
  6. - (void)testTrue1 {
  7. NSLog(@"1111111111111111111111");
  8. XCTAssert(1, @"Can not be zero");
  9. }
  10.  
  11. - (void)testTrue3 {
  12. NSLog(@"3333333333333333333333");
  13. XCTAssert(1, @"Can not be zero");
  14. }
  15.  
  16. - (void)testAtrue {
  17. NSLog(@"0000000000000000000000");
  18. XCTAssert(1, @"Can not be zero");
  19. }

控制台部分输出:

  1. Test Case '-[UnitTestDemoTests testAtrue]' started.
  2. 2014-03-19 21:19:38.182 UnitTestDemo[7401:60b] 0000000000000000000000
  3. Test Case '-[UnitTestDemoTests testAtrue]' passed (0.001 seconds).
  4. Test Case '-[UnitTestDemoTests testTrue1]' started.
  5. 2014-03-19 21:19:38.183 UnitTestDemo[7401:60b] 1111111111111111111111
  6. Test Case '-[UnitTestDemoTests testTrue1]' passed (0.000 seconds).
  7. Test Case '-[UnitTestDemoTests testTrue2]' started.
  8. 2014-03-19 21:19:38.184 UnitTestDemo[7401:60b] 2222222222222222222222
  9. Test Case '-[UnitTestDemoTests testTrue2]' passed (0.013 seconds).
  10. Test Case '-[UnitTestDemoTests testTrue3]' started.
  11. 2014-03-19 21:19:38.196 UnitTestDemo[7401:60b] 3333333333333333333333
  12. Test Case '-[UnitTestDemoTests testTrue3]' passed (0.001 seconds).
  13.  
  14. 可以看到无论我们怎样调换test方法的书写顺序,其测试顺序都是不变的。

目前初步的结论:测试方法执行的顺序与方法名中test后面的字符大小有关,小者优先,例如testA,testB1,testB2三个方法相继执行。

3.断言测试

下面一共18个断言(SDK中也是18个,其含义转自 ios UnitTest 学习笔记

XCTFail(format…) 生成一个失败的测试;

XCTAssertNil(a1, format...)为空判断,a1为空时通过,反之不通过;

XCTAssertNotNil(a1, format…)不为空判断,a1不为空时通过,反之不通过;

XCTAssert(expression, format...)当expression求值为TRUE时通过;

XCTAssertTrue(expression, format...)当expression求值为TRUE时通过;

XCTAssertFalse(expression, format...)当expression求值为False时通过;

XCTAssertEqualObjects(a1, a2, format...)判断相等,[a1 isEqual:a2]值为TRUE时通过,其中一个不为空时,不通过 ;

XCTAssertNotEqualObjects(a1, a2, format...)判断不等,[a1 isEqual:a2]值为False时通过;

XCTAssertEqual(a1, a2, format...)判断相等(当a1和a2是 C语言标量、结构体或联合体时使用,实际测试发现NSString也可以);

XCTAssertNotEqual(a1, a2, format...)判断不等(当a1和a2是 C语言标量、结构体或联合体时使用);

XCTAssertEqualWithAccuracy(a1, a2, accuracy, format...)判断相等,(double或float类型)提供一个误差范围,当在误差范围(+/-accuracy)以内相等时通过测试;

XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format...) 判断不等,(double或float类型)提供一个误差范围,当在误差范围以内不等时通过测试;

XCTAssertThrows(expression, format...)异常测试,当expression发生异常时通过;反之不通过;(很变态)

XCTAssertThrowsSpecific(expression, specificException, format...) 异常测试,当expression发生specificException异常时通过;反之发生其他异常或不发生异常均不通过;

XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression发生具体异常、具体异常名称的异常时通过测试,反之不通过;

XCTAssertNoThrow(expression, format…)异常测试,当expression没有发生异常时通过测试;

XCTAssertNoThrowSpecific(expression, specificException, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过;

XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过

特别注意下 XCTAssertEqualObjects和 XCTAssertEqual 。

XCTAssertEqualObjects(a1, a2, format...)的判断条件是[a1 isEqual:a2]是否返回一个YES。

XCTAssertEqual(a1, a2, format...)的判断条件是a1 == a2是否返回一个YES。

对于后者,如果a1和a2都是基本数据类型变量,那么只有a1 == a2才会返回YES。例如下面代码中只有第二行可以通过测试:

  1. // 1.比较基本数据类型变量
  2. XCTAssertEqual(1, 2, @"a1 = a2 shoud be true"); // 无法通过测试
  3. XCTAssertEqual(1, 1, @"a1 = a2 shoud be true"); // 通过测试

  但是,如果a1和a2都是指针,那么只有a1和a2指向同一个对象才会返回YES。例如下面的代码中:

  1. // 3.比较NSArray对象
  2. NSArray *array1 = @[@1];
  3. NSArray *array2 = @[@1];
  4. NSArray *array3 = array1;
  5. XCTAssertEqual(array1, array2, @"a1 and a2 should point to the same object"); // 无法通过测试
  6. XCTAssertEqual(array1, array3, @"a1 and a2 should point to the same object"); // 通过测试

  array1和array2指向不同对象,无法通过测试。

这里比较奇怪的是, NSString另当别论:

  1. // 2.比较NSString对象
  2. NSString *str1 = @"1";
  3. NSString *str2 = @"1";
  4. NSString *str3 = str1;
  5. XCTAssertEqual(str1, str2, @"a1 and a2 should point to the same object"); // 通过测试
  6. XCTAssertEqual(str1, str3, @"a1 and a2 should point to the same object"); // 通过测试

  尽管str1和str2指向不同的对象,但是二者的指针比较却能通过测试。在这里使用NSString要小心就是了。掌握了各个断言的含义,用起来就没什么大问题了。

如何通过Xcode 5中集成的XCTest框架进行简单的单元测试的更多相关文章

  1. 在前后端分离的SpringBoot项目中集成Shiro权限框架

    参考[1].在前后端分离的SpringBoot项目中集成Shiro权限框架 参考[2]. Springboot + Vue + shiro 实现前后端分离.权限控制   以及跨域的问题也有涉及

  2. 【IDEA】单元测试:项目中引入JUnit测试框架+Mock简单了解

    一.Junit 使用和说明: 参考:单元测试第三弹--使用JUnit进行单元测试-HollisChuang's Blog http://www.hollischuang.com/archives/17 ...

  3. Android中android-async-http开源网络框架的简单使用

    android-async-http开源网络框架是专门针对Android在Apache的基础上构建的异步且基于回调的http client.所有的请求全在UI线程之外发生,而callback发生在创建 ...

  4. Spring Boot集成Reactor事件处理框架的简单示例

    1. Reactor简介 Reactor 是 Spring 社区发布的基于事件驱动的异步框架,不仅解耦了程序之间的强调用关系,而且有效提升了系统的多线程并发处理能力. 2. Spring Boot集成 ...

  5. 在 Xcode 6 中使用矢量图( iPhone 6 置配 UI)

    在 Xcode 6 中使用矢量图( iPhone 6 置配 UI) (本文转载:http://iosdeveloper.diandian.com/post/2014-09-25/40063062789 ...

  6. Bing Maps进阶系列八:在Bing Maps中集成OpenStreetMap地图

    Bing Maps进阶系列八:在Bing Maps中集成OpenStreetMap地图 OSM(OpenStreetMap-开放街道地图)服务就是一种发布自己地图数据图片为服务的一种实现类型,开放街道 ...

  7. iOS原生项目中集成React Native

    1.本文的前提条件是,电脑上已经安装了CocoaPods,React Native相关环境. 2.使用Xcode新建一个工程.EmbedRNMeituan [图1] 3.使用CocoaPods安装Re ...

  8. Unity3d 游戏中集成Firebase 统计和Admob广告最新中文教程

    之前写过俩相关的教程,最近发现插件官方更新了不少内容,所以也更新一篇Firebase Admob Unity3d插件的教程,希望能帮到大家. Firebase Admob Unity3d插件是一个Un ...

  9. 使用Xcode过程中遇到的问题

    前言:记录一下使用Xcode过程中遇到的问题 1.关于开发者的Team的问题,是选用自己的个人Team还是选用公司的付费的Team(本机环境:Xcode9 + iPad :iOS11.0.3) 问题: ...

随机推荐

  1. 2014年将会受欢迎的IT技能--你有多少哪?

    据国外媒体报道,据Global Knowledge等十几家研究机构发布的2014年IT技能和薪金调查报告显示,2014年最受欢迎的十大IT技能如下: 1.编程与应用开发 据美国劳工统计局称,开发者和程 ...

  2. http://blog.sina.com.cn/s/blog_6145ed810102vr8k.html

    http://blog.sina.com.cn/s/blog_6145ed810102vr8k.html

  3. TypeScript完全解读(26课时)_6.TypeScript完全解读-泛型

    6.TypeScript完全解读-泛型 创建实例ts文件generics.ts 在index.ts内引入 fill是填充数组,创建的数组的元素数是times,填充的值就是接收的value的值 这里传入 ...

  4. 爬虫代码实现四:采用Hbase存储爬虫数据(2)

    导入hbase的jar包,在maven仓库找:进入http://mavenrepository.com/,输入hbase client,选择apache hbase client, 点击进入,选择 点 ...

  5. Eclipse如何查看接口实现类快捷键

    1.找到要打开的接口类 2.双击接口名选中 3.按Ctrl+T打开接口实现类 以List接口为例,如下所示

  6. Makefile研究 (一)—— 必备语法

    摘自:http://blog.csdn.net/jundic/article/details/17535445 参考文档:http://blog.csdn.net/wrx1721267632/arti ...

  7. HTML学习笔记(五)框架

    框架 通过使用框架,可以在同一个浏览器窗口中显示多个页面. eg: <frameset rows="50%,50%"> <frame src="/exa ...

  8. Android之打包签名

    一.什么的是打包? 打包就是根据签名和其他标识生成安装包. 二.什么是签名? 1.在android应用文件(apk)中保存的一个特别字符串 2.用来标识不同的应用开发者:开发者A,开发者B 3.一个应 ...

  9. MFC——ComBox用法大全

    Combo Box (组合框)控件很简单,可以节省空间.从用户角度来看,这个控件是由一个文本输入控件和一个下拉菜单组成的.用户可以从一个预先定义的列表里选择一个选项,同时也可以直接在文本框里面输入文本 ...

  10. ES6之Promise对象学习——8个例子学会Promise

    目录 Promise 立即执行 Promise 三种状态 Promise 不可逆性 链式调用 Promise.then()回调异步性 Promise中的异常 Promise.resolve() res ...