编写测试类与方法

    当你使用测试导航面板往项目中添加测试目标时,Xcode 会在测试导航面板里展示出测试类与方法。在测试目标里是包含测试方法的测试类。本章节讲述怎样创建测试类和编写测试方法。

    在学习创建测试类前,有必要看看测试导航面板。它对创建和运行测试工作极为重要。

    测试导航面板罗列了测试包里的所有组件内容,并在一个层次列表里展示出测试类和测试方法。下面是一个工程的测试导航面板视图,包含了多个测试目标,展示了测试包、测试类以及测试方法的嵌套层级。

    测试包可包含多个测试类。你可以使用测试类把测试分到相关的组群中,或者按照功能分,或者按照组织目的分。比如,对于本章中的计算器示例工程,你可以创建, AdvancedFunctionsTests以及 DisplayTests classes三个类,但他们都属于Mac_Calc_Tests测试包。

    编写测试类与方法 - 图1

    一些测试类型可能会共享某些类型的安装和卸载需求,把这些测试整合到类里面会更加合理,这样可以最小化每个测试方法所需编写的代码。

    创建测试类

    可以使用加号按钮(+)和测试导航面板中的 New Test Class 命令创建新测试类。

    基于你在配置页面键入的测试类名,你添加的每个类都会使得一个名为 TestClassName.m 的文件被添加到项目中。

    编写测试类与方法 - 图2

    尽管Xcode会默认的把测试类添加到为工程测试目标所创建的组中,你还是可以在项目中组织自己选择的文件。当你按下Next按钮,标准的 Xcode 添加文件页面如下所示:

    你可以用相同的方法在工程导航面板中添加文件。具体使用方法详见

    测试类包含如下的基本结构

    Xcode 执行测试可以明确这些方法的使用,这正是我们接下来的内容要讨论的。

    测试执行的流程

    在执行测试的过程中,XCTest 找到所有继承于XCTestCase的类(也就是说所有的测试类),并为每个类运行它的所有测试方法。

    对于每个类来说,测试开始于类的 setup 方法的运行。对于每个测试方法来说,一个新的类实例被创建,它的实例 setup 方法就会执行。在跑完了测试方法之后,实例卸载方法。类中这样连续重复执行所有测试方法。在运行的类卸载了最后的测试方法后,Xcode会执行类卸载方法,并开始下一个类。这种序列一直重复直到跑完所有测试类的所有测试方法。

    你通过编写测试方法把测试写到测试类中,一个测试方法是以 test 开头的测试类的实例方法,没有参数,返回void,比如testColorIsRed.测试方法调用工程中的代码,如果代码没有产生预期的结果,那么会用一系列的断言API报错。比如,一个函数返回值可能与预期值相比不同,或者你的测试方法使用了某个类里不适当的方法都将会抛出异常。“XCTest Assertions”描述了这些情况。

    为了使测试方法能够正常访问被测试代码,引入正确的头文件到测试类中很重要。

    当 Xcode 运行测试时,它调用的每个测试方法都是独立的。因此每个方法需要准备和清理辅助变量、结构以及与主题API进行交互的对象等。如果类中所有测试方法的代码是相同的,你可以直接把它添加到必需的setUptearDown的实例方法中,详见。

    下面是个测试方法的模型:

    1. - (void)testColorIsRed {
    2. ... // Test logic and values, assertions report pass/fail to testing framework.
    3. ... // Tear down. (Code could be shared in tearDown method.
    4. }

    这里有一个简单的测试方法例子,检查是否成功地为 SampleCalc 创建了CalcView实例,详见“Quick Start”章节:

    1. - (void) testCalcView {
    2. // setup
    3. app = [NSApplication sharedApplication];
    4. calcViewController = (CalcViewController*)[NSApplication sharedApplication] delegate];
    5. calcView = calcViewController.view;
    6. XCTAssertNotNil(calcView, @"Cannot find CalcView instance");
    7. // no teardown needed
    8. }

    更为深入一点的例子可以查看Testing Apps and Frameworkssample工程代码。

    XCTest断言

    你的测试方法使用 XCTest 框架提供的断言来呈现 Xcode 显示的测试结果。所有断言都有一个相似的形式:项目比较或逻辑表达式,一个失败结果字符串格式,和插入到字符串格式中的参数。

    比如,里方法中的断言:

    1. XCTAssertEqualObjects([calcViewController.displayField stringValue], @"10", @"Part 2 failed.");

    阅读这段简单明了的语句,是说:“Indicate a failure when a string created from the value of the controller’s display field is not the same as the reference string ‘8’” 。如果断言失败,那么 Xcode 在测试导航面板发出失败信号,然后 Xcode 会在 issues 导航面板、源码编辑器以及其他地方展示失败的描述。下面是源代码编辑器中典型的断言结果:

    编写测试类与方法 - 图3

    测试类可以包含多个断言,如果任何断言包含失败报告,那么 Xcode 都发出的测试失败信号。

    断言分为五种类型:无条件失败、等价测试、nil测试、Boolean测试以及异常测试。

    下面的区域列出了 XCTest 断言。你可以在 Xcode 中使用 Quick Help 查看XCTestAssertions.h来引用来获得更多关于 XCTest 断言的信息。

      XCTAssertEqualObjects。当expression1不等于expression2时报错(或者一个对象为空,另一个不为空)。

      1. XCTAssertEqualObjects(expression1, expression2, format...)

      XCTAssertNotEqualObjects。当expression1等于expression2时报错

      1. XCTAssertNotEqualObjects(expression1, expression2, format...)

      XCTAssertEqual。当expression1不等于expression2时报错,这个测试用于C语言的标量。

      XCTAssertNotEqual。当expression1等于expression2时报错,这个测试用于C语言的标量。

      1. XCTAssertNotEqual(expression1, expression2, format...)

      XCTAssertEqualWithAccuracy。当expression1expression2之间的差别高于 accuracy 时报错。这种测试适用于 floats 和 doubles 这些标量,两者之间的细微差异导致它们不完全相等,但是对所有的标量都有效。

      1. XCTAssertEqualWithAccuracy(expression1, expression2, accuracy, format...)

      XCTAssertNotEqualWithAccuracy。当expression1expression2之间的差别低于 accuracy 时报错。这种测试适用于 floats 和 doubles 这些标量,两者之间的细微差异导致它们不完全相等,但是对所有的标量都有效。

      1. XCTAssertNotEqualWithAccuracy(expression1, expression2, accuracy, format...)

      XCTAssertNil。当expression参数非nil时报错。

      1. XCTAssertNil(expression, format...)

      XCTAssertNotNil。当expression参数为nil时报错。

      1. XCTAssertNotNil(expression, format...)

      XCTAssertTrue。当expression计算结果为false时报错。

      1. XCTAssertTrue(expression, format...)

      XCTAssert。当expression计算结果为false时报错,与XCTAssertTrue同义。

      XCTAssertFalse。当expression计算结果为true时报错。

      1. XCTAssertFalse(expression, format...)

      XCTAssertThrows。当expression不抛出异常时报错误。

      1. XCTAssertThrows(expression, format...)

      XCTAssertThrowsSpecific。当expression针对指定类不抛出异常时报错。

      1. XCTAssertThrowsSpecific(expression, exception_class, format...)

      XCTAssertThrowsSpecificNamed。当expression针对特定类和特定名字不抛出异常时报错。对于AppKit框架或Foundation框架非常有用,抛出带有特定名字的NSException(NSInvalidArgumentException等等)。

      1. XCTAssertThrowsSpecificNamed(expression, exception_class, exception_name, format...)

      XCTAssertNoThrow。当expression抛出异常时报错。

      XCTAssertNoThrowSpecific。当expression针对指定类抛出异常时报错。任意其他异常都可以;也就是说它不会报错。

        XCTAssertNoThrowSpecificNamed。当expression针对特定类和特定名字抛出异常时报错。对于 AppKit 框架或 Foundation 框架非常有用,抛出带有特定名字的NSException(NSInvalidArgumentException等等)。