您的位置:首页 > 移动开发 > IOS开发

iOS开发:XCTest单元测试(附上一个单例的测试代码)

2016-12-27 14:18 393 查看
测试驱动开发并不是一个很新鲜的概念了。在我最开始学习程序编写时,最喜欢干的事情就是编写一段代码,然后运行观察结果是否正确。我所学习第一门语言是c语言,用的最多的是在算法设计上,那时候最常做的事情就是编写了一段代码,如何编译运行,查看结果是否正确,很多时候,还得自己想很多特殊的(比如说零值,边界值)测试数据来检测所写代码、算法是否正确。那个时候,感觉还好,比较输出只是只是控制台的一个简单的数字或者字符。在学习iOS开发中,很多时候也是要测试的,这种输出是必须在点击一系列按钮之后才能在屏幕上显示出来的东西。测试的时候,往往是用模拟器一次一次的从头开始启动app,然后定位到自己所在模块的程序,做一系列的点击操作,然后查看结果是否符合自己预期。

这种行为无疑是对美好生命和绚丽青春的巨大浪费。于是有很多资深工程师们发现,我们是可以在代码中构造一个类似的场景,然后在代码中调用我们之前想要检查的代码,并将运行结果和设想结果在程序中进行比较,如果一致,则说明我们的代码没有问题。比如说下面的代码:

当测试足够全面、具有代表性的时候,我们就可以肯定这个代码是没有问题的,至少,问题不是出自这块代码。我们做出某些条件和假设,并以其为条件使用到被测试中的代码去,比较预期结果与运行结果是否相等,这就是软件测试中的基本方法。

首先什么是单元测试?维基百科中的解释是:

在计算机编程中,单元测试(又称为模块测试, Unit Testing)是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。

通常来说,程序员每修改一次程序就会进行最少一次单元测试,在编写程序的过程中前后很可能要进行多次单元测试,以证实程序达到软件规格书(en:Specification)要求的工作目标,没有程序错误;虽然单元测试不是什么必须的,但也不坏,这牵涉到项目管理的政策决定。

在XCode中使用XCTest

在XCode7中新建一个工程的时候,会默认带一个用于单元测试的target,其名字为工程名加Test后缀,并且文件名也以Test结尾。你会发现已经有了一个默认的测试用例





注意到画勾的地方,Include Unit Test就是包含单元测试的意思。打开工厂目录,你会发现有如下文件:





其中,ZYMusicPlayerTests文件夹目录下的文件就是我们的单元测试文件。

新建一个工程的时候,会默认带一个用于单元测试的target,其名字为工程名加Tests后缀,并且文件名也以Test结尾。你会发现已经有了一个默认的测试用例,其中有四个方法:

四个方法分别是:setUp, tearDown, testExample, testPerformanceExample。其中testExample方法左侧有一个播放按钮,点击它就会对这个方法进行测试,而在整个文件的@implemenation那行也有个同样的按钮,点击后会对当前测试用例的所有方法进行测试,也可通过Command+U快捷键来触发。这个测试用例类没有头文件,因为测试用例不需要给外部暴漏接口。按照苹果官方的文档,建立一个测试用例的过程应该是这样的:

建立一个
XCTestCase
的子类
实现测试方法
选择性的定义一些实例变量来存储fixture的状态
通过重写
setUp
方法选择性的实例化fixture
通过重写
tearDown
方法来在测试后清除

测试方法没有参数和返回值,用test作为前缀,比如:

- (void)testPlayingMusic

会自动被
XCTest
架构识别为测试用例,每个
XCTestCase
的子类中的
defaultTestSuite
都是一个
XCTestSuite
,它包含了这些测试用例。

测试方法的实现经常包含断言,必须通过验证才能通过测试,举个例子:





下面是使用时的所有断言测试:

参考自:http://yulingtianxia.com/blog/2014/04/28/iosdan-yuan-ce-shi-xctest/

有一部分已亲测。

在使用XCTest的时候,一般是所需要测试的那个类的类名+Tests,如ZYAudioManagerTests就是为了测试ZYAudioManager类。并且这个类要继承自XCTestCase类,或者它的子类,如:

@interface ZYAudioManagerTests : XCTestCase

下面是一个音乐播放的单例代码与它的测试代码:

测试代码(测试代码,只有.m文件,无.h文件):

Command + U运行测试。

我应该测试什么?

学习完上面的使用方法时,迷茫了,在具体开发中,如果写测试代码,那么我该测试什么?私有方法也需要测试么?

我们不需要去测试私有方法,除此之外要回答“我该测试什么?”这个问题,并没有这么简单,但我依旧希望测试代码可以按照我实际编码时候的想法去测试,那么就是测试就仅仅是调用了我的共有方法。

- (void)testDownloadData;

像这样的测试有一个根本的问题:它不会告诉你应该发生什么,也就是不会告诉你实际的预期是什么。它不清楚需求是什么。

应该测试什么?我不应该关注于测试,而应该关注行为,应该测试行为。

什么是行为?

让我们思考你设计的 app 中的一个对象。它有一个接口定义了其方法和依赖关系。这些方法和依赖,声明了你对象的约定。它们定义了如何与你应用的其他部分交互,以及它的功能是什么。它们定义了对象的行为。

有很多行为,或许是私有的。比如说,我想测试一个继承自UIViewController的ZYNewViewController里面的tableView的dataSource的三个必须实现的数据源方法是否实现?

以往写代码,根据封装的原则,tableView必然是私有的,那么难道为了方便测试,我们就应该将它写成public?

不,有一种可以解决的方案是,写一个公共的TestsProcotol,然后利用委托实现上面的测试。

朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐