Quick / Quick

The Swift (and Objective-C) testing framework.
http://quick.github.io/Quick/
Apache License 2.0
9.79k stars 914 forks source link

Undefined symbols for architecture x86_64: #415

Closed esetnik closed 8 years ago

esetnik commented 8 years ago

Using XCode 7.1 with a brand new swift-based project. I am trying to create a test for UIViewController subclass referenced in a storyboard.

Installed Quick 0.8.0 with first Cocoapds and then Carthage following the installation instructions.

I receive the following error when trying to run my project tests:

  "type metadata accessor for ExampleApp.LoginViewController", referenced from:
      ExampleAppUITests.LoginViewControllerSpec.(spec (ExampleAppUITests.LoginViewControllerSpec) -> () -> ()).(closure #1) in LoginViewControllerSpec.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

LoginViewControllerSpec.swift in ExampleAppUITests Module

import Nimble
@testable import ExampleApp

class LoginViewControllerSpec: QuickSpec {
    override func spec() {
        var viewController: LoginViewController!
        beforeEach {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            viewController = storyboard.instantiateViewControllerWithIdentifier(
                    "LoginViewControllerID") as! LoginViewController
        }

        describe(".viewDidLoad()") {
            beforeEach {
                // Method #1: Access the view to trigger BananaViewController.viewDidLoad().
                let _ =  viewController.view
            }
        }
    }
}

LoginViewController.swift in ExampleApp Module


class LoginViewController: UIViewController {
    @IBOutlet weak var logoLabel: UILabel!

override func viewDidLoad() { super.viewDidLoad()

// Do any additional setup after loading the view.

}



}```

Anyone have any suggestions?
esetnik commented 8 years ago

Anyone have any suggestions about how I can help debug this? it looks like Quick is just not working for new projects created in Xcode 7.1 / Swift 2

modocache commented 8 years ago

I have a theory: can you try importing UIKit at the top of your test file?

// LoginViewControllerSpec.swift

import Quick
import Nimble
+import UIKit
@testable import ExampleApp

// ...

This reminds me of other issues that have been reported, and those users were able to resolve their problems by importing UIKit.

esetnik commented 8 years ago

Unfortunately I get the same error even when I import UIKit. It's important to note that the test passes without any build errors if I use a UIViewController whereas fail with the error above if I use my custom UIViewController subclass.

Compiles and Passes:

import Quick
import Nimble
@testable import SumuApp

class LoginViewControllerSpec: QuickSpec {
    override func spec() {
        var viewController: UIViewController!
        beforeEach {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            viewController = storyboard.instantiateViewControllerWithIdentifier(
                    "LoginViewControllerID")
        }

        describe(".viewDidLoad()") {
            beforeEach {
                // Method #1: Access the view to trigger LoginViewController.viewDidLoad().
                let _ =  viewController.view
            }
        }
    }
}

Compilation Failure With Aformentioned Error

import Quick
import Nimble
@testable import SumuApp

class LoginViewControllerSpec: QuickSpec {
    override func spec() {
        var viewController: LoginViewController!
        beforeEach {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            viewController = storyboard.instantiateViewControllerWithIdentifier(
                    "LoginViewControllerID") as! LoginViewController
        }

        describe(".viewDidLoad()") {
            beforeEach {
                // Method #1: Access the view to trigger LoginViewController.viewDidLoad().
                let _ =  viewController.view
            }
        }
    }
}

My custom UIViewController subclass is nothing special as far as I can tell

import UIKit

class LoginViewController: UIViewController {
    @IBOutlet weak var logoLabel: UILabel!

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.setNavigationBarHidden(true, animated: false)
    }

    override func viewWillDisappear(animated: Bool) {
        navigationController?.setNavigationBarHidden(false, animated: animated)
        super.viewWillDisappear(animated)
    }
}
ikesyo commented 8 years ago

I think that the “Enable Testability” build setting for you app target is not set to Yes, since the internal LoginViewController is not exposed even if you are using @testable import; that would not be a Quick's issue.

ikesyo commented 8 years ago

And also you should check that if this happens with plain XCTestCase to separate the root cause.

esetnik commented 8 years ago

I have Enable Testability enabled in my app target. screen shot 2015-11-02 at 7 59 41 am

I also confirmed that I can reproduce this with a plain XCTestCase so I guess this is not a Quick issue rather an Xcode 7.1 bug.

esetnik commented 8 years ago

I received a response from Apple regarding this issue.

Apple Developer Relations04-Nov-2015 04:13 PM

This issue behaves as intended based on the following:

UI tests run outside your app in a separate process. You can’t access app code from inside a UI test - that’s intentionally part of the design. Use unit testing for tests that need to access the app code and UI tests to automate user interaction testing.

We are now closing this bug report.
esetnik commented 8 years ago

So the solution is to move your view controller tests from theUITests target to the Tests target.

jeffh commented 8 years ago

Thanks for the closing the loop @esetnik! :+1: