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

是否可以在iOS应用程序中运行XCTest测试?,ios,testing,xctest,Ios,Testing,Xctest,我们有一个用XCTest编写的后端测试套件。该套件在Xcode中运行得很好,但出于各种原因,如果我们也能在iOS应用程序中运行该套件,那将是一件好事。可能吗?我不介意为它编写一些粘合代码,但事实上,我甚至无法在非测试目标中导入XCTest框架: SomeController.swift:2:8: Cannot load underlying module for 'XCTest' 这是可能的!关键是获取XCTest框架链接的副本,然后使用公共XCTest API运行测试。这将提供与通过Xcod

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

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

这是可能的!关键是获取XCTest框架链接的副本,然后使用公共XCTest API运行测试。这将提供与通过Xcode运行测试时相同的控制台输出。(使用公共API连接您自己的定制reporter看起来是可行的,但询问如何这样做本身就是一个很好的问题——没有多少人使用XceTest 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/
链接到您自己的测试 然后,弹出主应用程序目标的目标编辑器,将您的副本从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

你想实现什么?这将是我们的工程师从调试应用程序中按需运行后端测试套件的一种简单方便的方式。这是非常不寻常的事情。我会在Jenkins(或任何其他CI)上运行这个特定的按需测试,而不是应用程序本身。他们测试服务器组件。我还认为在CI服务器上运行它们是正确的解决方案,但在我们获得CI服务器之前,我希望有一种简单的方法,在没有开发人员机器的情况下运行测试。好的,那么它不应该是XCTest测试,而应该是一些自定义代码和自定义UI来显示结果。这看起来很棒,迫不及待地要测试它。谢谢您!:0:错误:-[MyProjectTests testExample]:失败:捕获到“NSInternalInconsistencyException”,“通过测试配置未指定目标应用程序路径:(null)”这对我来说很有效,如果有人遇到问题,我在这里的回答中描述了一些调整:在Xcode 11.3.1上,我们还需要复制和链接
XCTAutomationSupport.framework
。我们可以在脚本中添加:
cp-Rp\“$PLATFORMS/iPhoneSimulator.platform/$FRAMEWORKS/./privateframes/XCTAutomationSupport.framework”\FRAMEWORKS/iPhoneSimulator/
和拖放
XCTAutomationSupport.framework
。在Xcode 11.5上,我们还需要复制和链接libXCTestSwiftSupport.dylib,可在/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib文件夹中找到。