XCode中的单元测试:编写测试类和方法(内容意译自苹果官方文档)
当你在工程中通过测试导航栏添加了一个测试target之后, xcode会在测试导航栏中显示该target所属的测试类和方法。
这一章演示了怎么创建测试类,以及如何编写测试方法。
测试targets, 测试bundles, 以及测试导航栏
在开始创建测试类之前,测试导航栏值得多看上一眼。对于创建测试和完善测试工作来说,如何使用好它是很关键的。
将一个测试target加到工程会创建一个测试bundle.测试导航栏会展开测试bundles里面所有的源代码组成部分(在一个层级列表中展示了测试类和测试方法)。下面是一个工程的测试导航页面,该工程中有两个测试targets,该图展示了测试bundles、测试类、测试方法之间的嵌套层次关系。
测试bundles可以包含多个测试类。你可以使用测试类来将相关的测试分组,分组的方式可以通过功能或者其他的组织目的。例如,对于计算器例子工程,你可能会创建BasicFunctionsTests类、AdvancedFunctionsTests类、DisplayTests类,都包含在Mac_Calc_Tests测试bundle里(如下图)。
有些类型的测试可能会共享一些类型的setup或是teardown的需求,将它们合理的聚集在一起可以复用setup和teardown方法;如此一来会大大减少你的工作量,不失为一个机智的策略。
创建一个测试类
你可以使用测试导航栏中的+按钮来创建新的测试类。
你可以选择添加一个单元测试类或是一个UI测试类。选完以后,xcode会显示一个包含了一些文件模板项的选择页。该页面此时会默认选中一个Unit test case class。按下一步继续。
(此处截图省略)
所有的测试类都应该是XCTestCase的子类(由xctest框架提供)。
尽管xcode默认会将测试类的文件加到你的测试target的group中,你仍然可以自由的组织你的测试类文件(比如同时添加到多个targets中)。
测试类的结构
这里是OC编写的,想用swift来写也可以。
注意:setup 和 teardown不是必须的。如果一个类里的所有测试方法都需要相同的初始化和销毁代码,那么可以在setup 和 teardown中实现它们。这两个方法分别会在测试方法调用前和调用后被执行。你也可以实现同名的类方法(setup和teardown),它们会在所有测试方法执行前和执行后被调用(也就是说只执行一次,对象方法会根据测试方法的多少被执行多次)。
测试执行的流程
XCTest会找到所有的测试类并且运行每个类中所包含的所有测试方法。
注意:你也可以选择指定运行哪些XCTest测试。你可以使用test navigator禁用测试或者通过edit scheme来达到类似的目的。你也可以通过测试导航栏或代码编辑器的运行按钮来只运行一个测试或测试的子集。
对于每个类,测试开始时会先运行setup方法。对于每个测试方法,类的一个新对象被分配;其对象setup方法会被执行。在那之后它运行测试方法, 然后运行对象的teardown方法。当最后一个测试方法的teardown被调用以后,xcode会调用类的teardown方法,然后移动到下一个类。 这些步骤就这样机械化的被xcode来重复执行,直到所有类的所有测试方法都执行完毕。
编写测试方法
我们通过在测试类中编写测试方法来添加测试。测试方法是一个对象方法,其前缀是test,没有参数也没有返回值。我们通过测试方法来检查你的项目中得代码,观察其执行结果是否符合预期。如果代码不能产生预期的结果,我们通过一组断言api来报告故障。
要测试相应的项目代码,请先将对应的头文件加到你的测试类中。
当xcode运行测试时,它会独立调用每个测试方法。因此,每个方法必须准备和清理任何需要与主题API进行交互所需要的辅助变量,结构,和对象。如果这段代码是类中的所有测试方法都需要的,那你可以将其添加到setUp和tearDown对象方法中。
为异步操作编写测试
因为每个测试都是一个接一个独立的执行,所以测试方法都是同步执行的。但是越来越多的代码需要异步执行。为了应对异步方法和函数的测试需求,xctest在xcode6被大大增强了——在测试方法中支持序列化执行异步方法,具体实现是通过等待异步操作执行完毕或超时来达到这个目的。
示例代码如下图:
要了解更多关于编写异步测试的内容,请重点查看XCTest.framework中的XCTestCase+AsynchronousTesting.h头文件。
编写性能测试
性能测试通过重复运行一个你需要评估执行时间的代码block十次并收集的平均执行时间和标准差来完成。最后得到的平均值可以用来和一个参考基准来对比,以此得出成功或是失败的结论。
代码非常简单:
- (void)testPerformanceExample {
// This is an example of a performance test case.
[self measureBlock:^{
// Put the code you want to measure the time of here.
}];
}
一个实际应用的例子:
- (void) testAdditionPerformance {
[self measureBlock:^{
// set the initial state
[calcViewController press:[calcView viewWithTag: 6]]; // 6
// iterate for 100000 cycles of adding 2
for (int i=0; i<100000; i++) {
[calcViewController press:[calcView viewWithTag:13]]; // +
[calcViewController press:[calcView viewWithTag: 2]]; // 2
[calcViewController press:[calcView viewWithTag:12]]; // =
}
}];
}
性能测试运行时,可以展开代码编辑器中得选项来查看具体每次运行的结果。其中的基准线也是可以设置的。同时,性能测试还可以针对不同的设备来设置不同的基准线(根据设备的性能不同来制定)。该设定是非常合理也非常实用。
今天先写这么多,关键在实践。单元测试作为一个非常有用的工具,实在不应该将其束之高阁。大家可以对底层的基础代码多多编写单元测试来保证代码的可靠性和健壮性;同时单元测试也是重构过程中的一个得力武器,有了它的保证,代码的重构之路才能走的更加坦荡。
让我们拥抱变化。
To be continued… (未完待续)
待翻译的续篇:(执行测试,查看结果)
Running Tests and Viewing Results
XCode中的单元测试:编写测试类和方法(内容意译自苹果官方文档)的更多相关文章
- 编写测试类,了解ArrayList的方法
这篇文章主要介绍了C#中动态数组用法,实例分析了C#中ArrayList实现动态数组的技巧,非常具有实用价值,需要的朋友可以参考下 本文实例讲述了C#中动态数组用法.分享给大家供大家参考.具体分析如下 ...
- 在C++中使用C#编写的类2
在那篇<在C#中使用C++编写的类>中我介绍了如何在C#中使用C++编写的类.可是由于C#在用户界面设计.数据库存储和XML文件读取等方面的优势,有时候也会出现要在C++中使用C#编写的类 ...
- Javacard 解释器怎样在API类库中找到源文件调用的类、方法或者静态域?
申明:本篇非本人原创,是在阅读各种论文文献之后,对论文文献的一种梳理. 主要参考文献为: ------------------------------------------------------- ...
- Randoop测试类和方法(用例自动生成)
详细使用方法见randoop官网: https://randoop.github.io/randoop/manual/index.html 测试程序之前,先检测下你的Randoop是否配置好: 打开c ...
- Hutool中那些常用的工具类和方法
Hutool中那些常用的工具类和方法 Hutool是一个Java工具包,它帮助我们简化每一行代码,避免重复造轮子.如果你有需要用到某些工具方法的时候,不妨在Hutool里面找找,可能就有.本文将对Hu ...
- 006-基于hyperledger fabric1.4( 官方文档)编写第一个应用【外部nodejs调用】
一.概述 官方原文地址 Writing Your First Application如果对fabric网络的基本运行机制不熟悉的话,请看这里. 注意:本教程是对fabric应用以及如何使用智能合约的简 ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(中)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- java中的方法引用(method reference)官方文档总结
2017/7/5 转载写明出处:http://www.cnblogs.com/daren-lin/p/java-method-reference.html 今天要说的是java中的一项新特性,方法引用 ...
- 【采坑小计】thanos receiver的官方文档中,并未说明tsdb落盘的配置方式
官方文档的地址在:https://thanos.io/tip/components/receive.md/ 一开始以为落盘的时间间隔是:--tsdb.retention=15d 实际测试中发现,tha ...
随机推荐
- A. Robot Sequence
A. Robot Sequence time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...
- Ajax 学习之创建XMLHttpRequest对象------Ajax的核心
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...
- js:数据结构笔记14--高级算法
动态规划: 递归是从顶部开始将问题分解,通过解决所有分解出小问题来解决整体问题: 动态规划从底部开始解决问题,将所有小问题解决,然后合并掉一个整体解决方案: function dynFib(n) { ...
- 用indexOf判断设备是否是PC端?
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 游戏 标签gui.label
using UnityEngine; using System.Collections; public class Gui : MonoBehaviour { public string str; p ...
- iis浏览网页时提示无法显示 XML 页
无法显示 XML 页. 使用 样式表无法查看 XML 输入.请更正错误然后单击 刷新按钮,或以后重试. 处理资源 'http://localhost/ 时出错.第 1 ...
- 新浪微博iOS客户端架构与优化之路
新浪微博iOS客户端架构与优化之路 随着Facebook.Twitter.微博的崛起,向UGC.PGC.OGC,自媒体提供平台的内 容消费型App逐渐形成了独特的客户端架构模式.与电商和通讯工具类 ...
- mysql多种方法修改密码----5.6的坑
创建用户并授权和改密码: grant all privileges on *.* to root@'%' identified by '123456' with grant option; * ...
- 又一种Mysql报错注入
from:https://rdot.org/forum/showthread.php?t=3167 原文是俄文,所以只能大概的翻译一下 这个报错注入主要基于Mysql的数据类型溢出(不适用于老版本的M ...
- [转].net自定义验证控件CustomValidator的使用
本文转自:http://tech.cncms.com/web/aspnet/96310.html CustomValidator验证控件,可以自定义验证函数,实现其它几个验证控件不能实现的验证规则,最 ...