Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
444 views
in Technique[技术] by (71.8m points)

testing - Is it possible to run XCTest tests in an iOS app?

We have a backend test suite written with XCTest. The suite runs great in Xcode, but for various reasons it would be nice for us if we could also run the suite in an iOS app. Is that possible? I don’t mind writing some glue code for it, but as it is I can’t even import the XCTest framework in a non-testing target:

SomeController.swift:2:8: Cannot load underlying module for 'XCTest'
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.)

Copy In XCTest.framework

Rather than unravel whatever is breaking the module loading, you can copy the XCTest.framework bundle into your project from the platform frameworks for your target platform:

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/

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".

Build Your Tests Into the Main App Target

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.

Run Those Tests

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...