在iOS应用中运行XCTest测试是否可行?

14

我们有一个使用XCTest编写的后端测试套件。该套件在Xcode中运行良好,但出于各种原因,如果我们也能在iOS应用程序中运行该套件,那将是很好的。这是否可能?我不介意为此编写一些粘合代码,但目前我甚至无法在非测试目标中导入XCTest框架:

SomeController.swift:2:8: Cannot load underlying module for 'XCTest'

你想要实现什么目标? - Jon Reid
这将是我们的工程师从我们的调试应用程序上随时运行后端测试套件的一种简单而方便的方式。 - zoul
这是一件相当不寻常的事情。我会在需要时使用Jenkins(或任何其他CI)来运行特定的测试,而不是直接运行应用程序本身。 - Michał Myśliwiec
澄清一下,测试不是被测试应用程序的一部分。它们测试服务器组件。我认为在CI服务器上运行它们是正确的解决方案,但在我们获得CI服务器之前,我希望有一种简单的方法来运行测试而不需要开发人员的机器。 - zoul
是的,不错。但是如果没有这个好用的Xcode支持,你如何在iOS应用程序中收集/可视化测试结果呢?嗯,也许你可以尝试模拟XCTest类和XCTAsserts方法。这样,您就可以在XCTest和iOS应用程序中使用相同的代码。我不知道XCTest的内部情况,但我猜它与macOS和Xcode紧密绑定,不能仅仅通过在iOS应用程序中导入它来解决问题。 - Michał Myśliwiec
显示剩余2条评论
1个回答

19

可以实现!关键是要获得XCTest框架链接的副本,然后使用公共的XCTest API运行您的测试。这将给您与在Xcode中运行测试时看到的相同的控制台输出。使用公共API连接自己的自定义报告器似乎是可行的,但如何执行这样的操作是一个好问题 - 不多人使用XCTest API,因为Xcode已经为我们完成了繁重的工作。

复制XCTest.framework

与其解开模块加载过程中的问题,不如从目标平台的平台框架中将XCTest.framework捆绑包复制到您的项目中:

mkdir Frameworks && mkdir Frameworks/iphonesimulator
PLATFORMS=/Applications/Xcode.app/Contents/Developer/Platforms
FRAMEWORKS=Developer/Library/Frameworks
cp -Rp \
    "$PLATFORMS/iPhoneSimulator.platform/$FRAMEWORKS/XCTest.framework" \
    Frameworks/iphonesimulator/

链接到你自己的 XCTest

接下来,打开你主应用程序目标的编辑器,将从Finder中复制的测试库文件拖放到“链接的框架和库”列表中。

将你的测试构建到主应用程序目标中

现在,进入你的测试文件,打开文件检查器,在这些文件旁边的主应用程序目标旁边勾选复选框。现在,你正在将测试文件作为主应用程序的一部分进行构建,这会将所有的XCTestCase子类放入二进制文件中。

运行这些测试

最后,将一个按钮连接到“运行测试”的操作上,像这样:

import UIKit
import XCTest

class ViewController: UIViewController {
    @IBAction func runTestsAction() {
        print("running tests!")
        let suite = XCTestSuite.default()
        for test in suite.tests {
            test.run()
        }
    }
}

当您点击按钮时,您将在控制台中看到以下内容:

running tests!
Test Suite 'RunTestsInApp.app' started at 2017-05-15 11:42:57.823
Test Suite 'RunTestsInAppTests' started at 2017-05-15 11:42:57.825
Test Case '-[RunTestsInApp.RunTestsInAppTests testExample]' started.
2017-05-15 11:42:57.825 RunTestsInApp[2956:8530580] testExample()
Test Case '-[RunTestsInApp.RunTestsInAppTests testExample]' passed (0.001 seconds).
Test Case '-[RunTestsInApp.RunTestsInAppTests testPerformanceExample]' started.
/Users/jeremy/Workpad/RunTestsInApp/RunTestsInAppTests/RunTestsInAppTests.swift:34: Test Case '-[RunTestsInApp.RunTestsInAppTests testPerformanceExample]' measured [Time, seconds] average: 0.000, relative standard deviation: 122.966%, values: [0.000002, 0.000001, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100
Test Case '-[RunTestsInApp.RunTestsInAppTests testPerformanceExample]' passed (0.255 seconds).
Test Suite 'RunTestsInAppTests' passed at 2017-05-15 11:42:58.081.
     Executed 2 tests, with 0 failures (0 unexpected) in 0.256 (0.257) seconds
Test Suite 'RunTestsInApp.app' passed at 2017-05-15 11:42:58.081.
     Executed 2 tests, with 0 failures (0 unexpected) in 0.256 (0.258) seconds

这看起来很不错,迫不及待想要测试一下。谢谢! - zoul
<未知>:0: 错误: -[MyProjectTests testExample] : 失败: 捕获到 "NSInternalInconsistencyException","没有通过测试配置指定目标应用程序路径: (null)" - laoyur
1
这对我有用,如果有人遇到问题,我在这里的答案中描述了一些调整:https://dev59.com/zrHma4cB1Zd3GeqPFg6B#54209379 - brthornbury
1
在Xcode 11.3.1上,我们还需要复制和链接“XCTAutomationSupport.framework”。我们可以添加到脚本中:cp -Rp \ "$PLATFORMS/iPhoneSimulator.platform/$FRAMEWORKS/../PrivateFrameworks/XCTAutomationSupport.framework" \ Frameworks/iphonesimulator/ 并且也可以拖放“XCTAutomationSupport.framework”。 - kanobius
在Xcode 11.5上,我们还需要复制并链接libXCTestSwiftSupport.dylib,该文件位于/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib文件夹中。 - Ivo Leko
在 Xcode 14 中似乎不再可能了。在遵循 @IvoLeko 的最后提示之后,我还必须添加 XCTestCore.framework,然后我会收到链接器警告:“您的二进制文件不是 XCTestCore 的允许客户端”。 :( - Kristof Van Landschoot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接