原文地址:《Testing with Xcode》——QuickStart
本篇介绍了Xcode执行测试的方法,说明了Xcode工具如何新建、执行一个测试用例。
看完之后你能学习到:
如何使用Xcode来创建一个测试用例。
如何执行测试用例
如何观察Xcode的测试结果
文章翻译自Apple官方文档《Testing with Xcode》,不保证每个字都能翻译的精准,如有翻译错误,请留言指出,不胜感激。
这个快速开始是为了告诉你,你可以很容易的给你开发的软件做一些必须的测试。
当你开始测试工作的时候,你经常会使用Xcode的导航功能。
测试导航菜单是工作区的一部分,是让你便捷的创建,管理,运行和检视测试代码。你可以点击在issue导航和debug导航中间的的图标进入测试导航菜单。当你的项目有定义测试套件,你可以在这里看到类似的导航菜单。
测试导航菜单想一个项目一样以列表的形式分级的展示了包,类和方法。这个项目是一个类似计算器的app。计算器的工程项一套工程的结构,可以看到优先级最高的SampleCalcTests
测试包,是为了测试应用的代码。
**注意:**Xcode只想的测试包会在测试导航菜单中展示。
如果你测试时使用数据,图片和其他内容,他们可以被添加到测试包,在执行的时候使用NSBundle
APIs。使用+[NSBundle bundleForClass:]
和你的测试类时,你要确保你取回了正确的测试包和正确的数据。更多详情请看NSBundle Class Reference.
Xcode会计划和控制构建的内容。Schemes也会操作可执行的测试的方法进行测试。你可以在测试菜单中使用Control-clicking有选择的使用或者忽略测试包,类和方法。
在视图中活动的测试包是SampleCalcTests. SampleCalcTests
,它包含该了一个测试包,测试包中包括9个测试方法。当你把鼠标放在列表中任意一项上,运行按钮就会出现在列表名称的右侧。测试结束后会返回成功或失败的结果给Xcode。测试开始执行的时候,这些图标会更新,给你展示测试的结果。绿色表示通过,红色表示失败。这里测试导航菜单显示的测试结果,有两项被断言为失败。
点击列表中任意一个测试类或者测试方法,会在代码编辑器中打开对应的测试类。测试类和测试方法也会在编辑器中做上标记。测试失败会在代码编辑器中展示断言处和对应的方法。
在测试菜单的底部是增加按钮和过滤控制,你可以减少展示的内容,只显示活动的测试项或者只展示失败的测试,当然,你也可以按照名称来过滤。
更多测试导航菜单的详细操作,请看Test Navigator Help。
在Xcode5和以后的版本中你可以在新建app,框架和资源的时候添加一个测试的target。当你开始一个新的项目时打开测试导航菜单,你可以看到一个测试包,一个测试类和一个测试方法的模板。但是你不要使用没有测试target的Xcode版本来打开以前的项目。这里的工作流程假设一个之前的项目是没有纳入测试的。
点击测试导航菜单左下方的增加按钮来选择新建一个Unit Test Target
在下一个对话框中选择OS X或者IOSUnit Testing Bundle
,然后点击Next
。会出现一个新的对话框,编辑项目名称和其他你需要的参数。
点击Finish
来增加你的target,在测试导航菜单师徒中包含了一个测试类的模板和两个测试方法的模板
现在你可以为你的项目增加测试方法了。你想要开发一些有用的测试方法。但是首先,先把鼠标放到测试导航菜单的SampleCalcTests
上并点击运行按钮来执行所有的测试方法。测试结果会在函数名的旁边用绿色的标记标记出来,在代码编辑器中也一样。
模板中的单元测试和演示的测试方法都是空的。这就是为什么他们都会被标记为成功,没有失败的断言。注意34行灰色菱形measureBlock:
方法。点击菱形来展示演示结果的面板。
面板允许你设置一个预期的基线和最大STDDEV参数。这些方面稍后会讨论。
由于这个样本项目是一个计算器APP,你想要检查他能否想其他计算函数一样正确的执行加减乘除。由于测试是在app项目内部构建,你可以增加所有你愿意增加的测试环境。创建测试要做的事就是在执行单元测试的文件中增加一个函数。
例如。你给SampleCalcTests.m
文件增加一个#import
和声明变量。
#import
//
// Import the application specific header files
#import "CalcViewController.h"
#import "CalcAppDelegate.h"
@interface CalcTests : XCTestCase {
// add instance variables to the CalcTests class
@private
NSApplication *app;
CalcAppDelegate *appDelegate;
CalcViewController *calcViewController;
NSView *calcView;
}
@end
然后给测试方法一个描述的名称,就像testAddition
一样,然后为方法增加一个执行的代码。
- (void) testAddition
{
// obtain the app variables for test access
app = [NSApplication sharedApplication];
calcViewController = (CalcViewController*)[[NSApplication sharedApplication] delegate];
calcView = calcViewController.view;
// perform two addition tests
[calcViewController press:[calcView viewWithTag: 6]]; // 6
[calcViewController press:[calcView viewWithTag:13]]; // +
[calcViewController press:[calcView viewWithTag: 2]]; // 2
[calcViewController press:[calcView viewWithTag:12]]; // =
XCTAssertEqualObjects([calcViewController.displayField stringValue], @"8", @"Part 1 failed.");
[calcViewController press:[calcView viewWithTag:13]]; // +
[calcViewController press:[calcView viewWithTag: 2]]; // 2
[calcViewController press:[calcView viewWithTag:12]]; // =
XCTAssertEqualObjects([calcViewController.displayField stringValue], @"10", @"Part 2 failed.");
}
注意测试导航菜单中样例的测试方法,testExample
被替换成了testAddition
。
现在点击测试导航菜单中的运行按钮(或者代码编辑器中的指示)来运行testAddition
方法。
就像你看到的一样,一个断言失败了,在测试导航菜单和代码编辑器中都高亮显示了。看源代码。Part 1成功了,是Part 2有一个问题。在测试中,错误很明显:在76行,[calcView viewWithTag:11]
错了。应该是[calcView viewWithTag:12]
。收集错误信息修复问题后,测试成功。
Xcode为活动的测试包运行所有的测试方法一次。在这个小例子中只有一个方法执行了。它需要接受三个计算器app提供的变量对象。如果你写了四个或者五个测试方法在同样的类中。你会发现你需要为每一条测试案例输入重复的代码。XCTest框架提供你一个测试类的入口方法,setUp
和tearDown
,你可以用他们来放置每次执行测试方法的前置方法和结束方法。
使用setUp
和tearDown
方法很简单。从Mac_Calc_Tests.m
文件中的testAddition
代码中剪切4行// obtain the app variable for test access
然后粘贴他们到模板默认的setUp
入口方法中。
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
// obtain the app variables for test access
app = [NSApplication sharedApplication];
calcViewController = (CalcViewController*)[[NSApplication sharedApplication] delegate];
calcView = calcViewController.view;
}
现在使用最少重复代码增加更多的测试方法——testSubtraction
和其他方法。
你能看到的这个简短的快速开始,它非常简单的给项目增加测试。这里有一些需要注意的地方:
setUp
方法和tearDown
方法作为入口方法,能够让你把常用的代码统一的使用在方法中,保持代码的连贯性也更容易发现问题。