【问题标题】:How do I migrate from SenTestingKit/OCUnit to XCTest?如何从 SenTestingKit/OCUnit 迁移到 XCTest?
【发布时间】:2013-11-30 02:40:19
【问题描述】:

我正在将我的项目从 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 的单元测试?毕竟这些只是被弃用了,所以它们应该仍然存在并且可以使用。

【问题讨论】:

  • 如果你足够疯狂(像我一样)想要为 iOS7 运行 XCTest 和为 iOS6 运行 OCUnit,请查看我的 blog post

标签: xcode5 ocunit xctest


【解决方案1】:

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

OCUnit 测试仍然有效,但您不妨迁移一下。变化最终非常小。

【讨论】:

  • 啊哈,隐藏在重构之下......好吧,它可能会更糟。无论如何,第二个向导屏幕应该让我选择要转换的目标。在我的情况下,列表是空的。任何想法为什么?
  • 我现在确信它一定与我的单元测试目标当前设置的方式有关。我尝试添加一个新的空单元测试目标(使用文件 > 新建 > 目标),并且该目标在向导中显示得非常好。找到解决方案后,我将继续调查并发布结果。
  • xCode 6 现在在菜单下Edit -> Convert -> To XCTest...
【解决方案2】:

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


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

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

一旦我发现了这一点,我就能够逐步完成向导,但就我而言,最终结果仍然是一个惊人的失败!该向导声称不需要更改源代码,只需更新构建设置即可迁移到 XCTest。最后,向导甚至没有正确地做到这一点:它确实删除了对 SenTestingKit 框架的引用,但它确实没有添加了对 XCTest 的引用框架。

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

  1. 从单元测试目标中删除“运行脚本”构建阶段
  2. 将所有测试用例类的基类从SenTestCase更改为XCTestCase
  3. 将导入的标头从<SenTestingKit/SenTestingKit.h>更改为<XCTest/XCTest.h>
  4. 在测试目标的 Build Settings 中,将 Wrapper Extension 从 octest 更改为 xctest
  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);

最后但同样重要的是,正如前面已经提到的,对 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。详情请见"Modules" section of the clang documentation


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

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

由于我无法继续迁移,因此我目前的解决方案是保留基于 SenTestingKit/OCUnit 的单元测试,直到我有时间将我的应用程序升级到 iOS 7。这就是我必须要做的为了让单元测试运行:

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

最终的解决方案不如 Xcode 4.x 中的好,在 Xcode 4.x 中,每次我运行主要目标的“运行”或“构建”操作时都会自动执行单元测试。不幸的是,如果没有“运行脚本”构建阶段,我似乎无法让它工作。

【讨论】:

  • 在我的项目中,所有似乎都转换为 XCTest 并且工作正常,但我仍然有 OCUnit 警告。在我再次执行自动转换后(不需要更改代码) - 警告消失了,但下次我打开 XCode 时它仍然存在。有什么帮助吗?
  • @IlyaK。你应该问一个新问题。这为您提供了更多空间来描述您的问题。此外,我目前没有从事任何 Xcode 项目,因此无法为您提供帮助。
  • 这是一个小问题,我想也许这个线程中的某个人遇到了这个问题。但也许你是对的,我应该打开单独的线程。
  • 我刚刚添加了一个步骤,将构建设置中的 Wrapper Extension 更改为 xctest。向导通常会这样做。
  • Xcode 中偶尔也会出现一个错误(至少影响 5.1),即使在迁移测试之后,“OCUnit 已弃用”警告仍然存在,并且尝试使用迁移工具无法运行(因为它没有检测到要迁移的测试套件)。我发现发生这种情况时,为相关 project.pbxproj 中的相关目标手动进行以下更改有助于消除警告:其中显示以下内容:productType = "com.apple.product-type.bundle.ocunit -测试”;改为:productType = "com.apple.product-type.bundle.unit-test";
猜你喜欢
  • 2014-02-14
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 2013-09-22
  • 1970-01-01
  • 2015-12-18
  • 2018-06-23
  • 2021-07-18
相关资源
最近更新 更多