如何从SenTestingKit/OCUnit迁移到XCTest?

her*_*ube 35 ocunit xcode5 xctest

我正在将我的项目从Xcode 4.6.3迁移到Xcode 5.0.2.该项目的单元测试是使用SenTestingKit/OCUnit开发的.现在当我在Xcode 5中运行测试时,我从RunUnitTests脚本中得到一个错误告诉我

RunUnitTests已过时.

可能相关的是Xcode 5发行说明中的​​这个注释:

SenTestingKit和OCUnit已弃用.使用迁移器移动到XCTest.

不幸的是,我还没有找到更多关于这个神秘的"迁移者"的信息.可能我的google-fu缺乏[再次],所以我的主要问题是:如何将单元测试从SenTestingKit/OCUnit迁移到新的XCTest(有或没有"迁移器")?

第二个问题,如果迁移是一项复杂的业务:是否有可能让Xcode 5运行仍基于SenTestingKit/OCUnit的单元测试?在所有这些仅仅被弃用之后,它们应该仍然存在并且功能性.

her*_*ube 59

感谢Shaggy Frog的回答,我们知道Xcode发行说明中提到的神秘"迁移器"是通过选择"编辑>重构>转换为XCTest"启动的向导.我将分两部分介绍我对这个向导的体验.第一部分是对主要问题的不完整答案,第二部分回答了次要问题.


第1部分:如何从OCUnit迁移到XCTest

您需要意识到的第一件事是,要使向导工作,您需要选择单元测试目标.如果选择了主目标,则向导不会列出要转换的任何目标.

一旦我发现了这一点,我就能够通过向导,但在我的情况下,最终的结果仍然是一个惊人的失败!该向导声称不需要进行任何源更改,只需要更新构建设置以迁移到XCTest.最后,精灵甚至没有设法正确地做到这一点:它没有删除提及的SenTestingKit框架,但它并没有投入到XCTest框架的引用.

无论如何,接下来是我必须手动进行的更改列表,因为向导无法为我创建它们.如果向导更适合您,您可能不需要执行所有这些操作.

  1. 从单元测试目标中删除"运行脚本"构建阶段
  2. 将所有测试用例类的基类更改SenTestCaseXCTestCase
  3. 将导入的标题更改<SenTestingKit/SenTestingKit.h><XCTest/XCTest.h>
  4. 在测试目标的Build Settings中,将Wrapper Extension从更改octestxctest.
  5. 将所有断言宏重命名ST*XCT*(例如STAssertTrue变为XCTAssertTrue)
  6. 以上例外:STAssertEquals需要重命名为XCTAssertEqual(注意末尾缺少"s").如果您收到此编译器警告,您将知道您已经忘记了这一点:warning: implicit declaration of function 'XCTAssertEquals' is invalid in C99
  7. 新的XCTest断言宏不允许nil作为失败描述传递.例如,XCTAssertNotNil(anObject, nil)不可能,必须更改为XCTAssertNotNil(anObject).当您收到此编译器错误时,您将知道存在此问题:error: called object type 'NSString *' is not a function or function pointer.
  8. 如果确实需要传递失败描述,则新的XCTest断言宏需要格式说明符的常量表达式,就像NSString类方法stringWithFormat:一样.当您收到此编译器错误时,您将知道存在此问题:error: expected ')'.一些例子:
NSString* formatSpecifier = @"%@";
NSString* failureDescription = @"foo";
// These are OK
XCTAssertNotNil(anObject, @"foo")
XCTAssertNotNil(anObject, @"%@", failureDescription)
// These are not OK
XCTAssertNotNil(anObject, failureDescription);
XCTAssertNotNil(anObject, formatSpecifier, failureDescription);
Run Code Online (Sandbox Code Playgroud)

最后但并非最不重要的是,如前所述,需要将对XCTest框架的引用添加到单元测试目标中.如果你遇到链接器错误,你就会知道你已经忘记了这一点Undefined symbols for architecture i386: "_OBJC_CLASS_$_XCTestCase", referenced from: foo.

Xcode 6更新:Xcode 6中不再需要与XCTest链接(实际上XCTest甚至不再列为可用框架).而是将构建设置CLANG_ENABLE_MODULES设置为YES(在UI中显示为"启用模块(C和Objective-C)").这将导致clang在看到#import <XCTest/XCTest.h>语句时自动链接到XCTest .有关详细信息,请参见clang文档"模块"部分.


第2部分:如何在Xcode 5中运行OCUnit测试

此时我收到一个链接器错误,让我意识到我迁移到XCTest的任务失败了.原因是:XCTest不是SDK 6.1的一部分,但我仍然使用基础SDK iOS 6.1构建我的项目(这个答案解释了如何将SDK 6.1集成到Xcode 5中).

由于我无法继续迁移,因此我目前的解决方案是基于SenTestingKit/OCUnit保持我的单元测试,直到我找到时间将我的应用程序升级到iOS 7.这是我必须按顺序执行的操作让单元测试运行:

  1. 从单元测试目标中删除"运行脚本"构建阶段.这是所有需要让Xcode中通过"测试"动作(执行单元测试+ U)而选择了单元测试目标.
  2. 但这并不理想,因为我不想仅仅为了执行单元测试而切换目标.相反,我想在选择主目标时执行单元测试.因此,第二步是修改主目标的Xcode方案,以便在运行"Test"操作时,执行单元测试目标的测试.

最终解决方案不如Xcode 4.x那样好,每当我运行主目标的"运行"或"构建"操作时,单元测试就会自动执行.不幸的是,似乎没有"运行脚本"构建阶段我无法使用它.


Sha*_*rog 14

编辑 - >重构 - >转换为XCTest

OCUnit测试仍然有效,但您也可以迁移.这些变化最终变得非常小.

  • xCode 6现在位于菜单`Edit - > Convert - > To XCTest ...`下 (2认同)