且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-02-05 18:04:31

这是可能的!关键是获取 XCTest 框架链接的副本,然后使用公共 XCTest API 运行您的测试.这将为您提供与通过 Xcode 运行测试时看到的相同的控制台输出.(使用公共 API 连接您自己的自定义报告器看起来可行,但询问如何这样做本身就是一个很好的问题 - 没有多少人使用 XCTest API,因为 Xcode 为我们做了肮脏的工作.)

It is possible! The key is to get a copy of the XCTest framework linking and then use the public XCTest APIs to run your tests. This will give you the same console output you see when running the tests via Xcode. (Wiring up your own, custom reporter looks doable using the public APIs, but asking how to do so would make a good question in itself - not many people use the XCTest APIs, because Xcode does the dirty work for us.)

您可以将 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 拖放到链接的框架和库"列表中.

Link Against Your Own XCTest

Then, pop open the target editor for your main app target, and drag and drop your copy from Finder to the list of "Linked Frameworks and Libraries".

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

Now, go to your test files, pop open the File Inspector, and tick the box next to your main app target for those files. Now you're building the test files as part of your main app, which puts all your XCTestCase subclasses into the binary.

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

Lastly, wire up a button to "Run Tests" to an action like this:

import UIKit
import XCTest

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

当您点击按钮时,您会在控制台中看到:

When you tap the button, you'll see this in the console:

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