6

I am trying to write an extension for the XCTest framework in Swift. In order to do so, I created a project with two targets: the main/production target and a test target.

As I am writing an extension for XCTest, I need to import XCTest within my main/production target as well. However, I am having trouble to do so. When in Xcode and I click on my project, then select the main target, go to Build Phases, Link Binary With Libraries and add XCTest there, I get a compile error:

ld: framework not found XCTest clang: error: linker command failed with exit code 1 (use -v to see invocation)

I also tried the solution provided here which unfortunately doesn't work either.

Cal
  • 422
  • 6
  • 20
ImJustACowLol
  • 826
  • 2
  • 9
  • 27
  • For your use-case computing test coverage, the official solution may also be appropriate: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/07-code_coverage.html – brthornbury Jan 16 '19 at 08:23

1 Answers1

4

Auxiliary information on XCTest itself is sparse and hard to find, I was also chasing down the same functionality and finally managed to get it working.

I am on XCode 10.1 and running on a real iPhone with iOS 11. I am certain the general technique will work for other versions, but probably will require a few tweaks.

The general steps are described in this stackoverflow answer, but required several additional steps and tweaks to work for me on a real iPhone:

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

Follow the steps in the above link. The below steps are deviations from those instructions that were required for me.

  1. Copy in the XCTest framework as described in the above link. NOTE: Use the framework for the iPhone.OS platform and not the simulator as it describes. You can find this framework file inside the actual XCode Application package on your mac. (Right click, "Show Package Contents", then look in ./Contents/Developer/Platforms/iPhoneOS.platform

  2. Disable bitcode in your app target. This solves a linker error. Here is an example of enabling it: how to ENABLE_BITCODE in xcode 7?

  3. When dragging the XCTest.framework file to the linked binaries in your target, ensure that you also drag it to the "Embedded Binaries" which is directly above the "Linked Frameworks and Libraries" option. If you don't do this you will get a runtime error.

add framework to embedded binaries

  1. The ViewController code to start the tests is slightly different in new Swift, here is what I am using:

import UIKit
import XCTest

class ViewController: UIViewController {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("running tests!")
        let suite = XCTestSuite.default;
        for test in suite.tests {
            test.run()
        }
    }

}

That should be it! When I run the above app, then touch the screen, all of the tests from my UITesting target run flawlessly and pass!

brthornbury
  • 3,518
  • 1
  • 22
  • 21
  • Cheers for the answer! – ImJustACowLol Jan 18 '19 at 08:17
  • Glad it helped! – brthornbury Jan 18 '19 at 23:03
  • When built with XCode 11.1, running gives the error "Library not loaded": `/private/var/containers/Bundle/Application/UUID_HERE/test2.app/Frameworks/XCTest.framework/XCTest Reason: image not found` any ideas? – tommed Nov 09 '19 at 10:36
  • Try opening up the .app archive on your local machine, is the framework present? – brthornbury Nov 11 '19 at 18:44
  • Complementing this answer: if you have problems, double check the framework search paths. It should point to the path to your copied XCTest.framework. – Carla Camargo Mar 25 '20 at 17:35
  • 1
    Unfortunately, It's still impossible to get running something like: `XCUIApplication(bundleIdentifier: "com.apple.springboard")`. It will just freeze app for 60 seconds and log error: Unable to update application state promptly for Application 'com.apple.springboard'. – Ivo Leko Jun 16 '20 at 14:45