22

I have looked at a lot of blogs and tried many things to get my Swift unit tests to work in Xcode 6.0.1 (or 6.1 for that matter). I'm trying to access classes in my app's target so I wrote this line:

var vc: LoginViewController!

Of course, I get the "Use of undeclared type 'LoginViewController'" error.

I then try to add LoginViewController to my test target, but then I get "use of unresolved identifier" errors on other classes in my project. So I try to add those classes to my test target, but I end up with a seemingly endless source of errors like the screenshot below:

xcode swift errors

Declaring all my classes as public, causes other errors and seems like bad practice. Is there anyway to include unit tests in a Swift project that relies on many frameworks and classes? I simply want to start with something almost exactly like the code in this article.

tfrank377
  • 1,858
  • 2
  • 22
  • 34
  • 1
    Double check target membership. If it is already done, try cleaning the project, remove derived data and restarting XCode. – Anthony Kong Oct 31 '14 at 21:46
  • That has not worked so far, the main issue I have with unit tests now is using a third-party static framework. Adding classes to the test target then calling a function in that framework causes the "use of unresolved identifier 'className'" – tfrank377 Nov 03 '14 at 17:56
  • Check to make sure your Bridging Header class/directory is listed in both the App target, and the App test target. – khanh.tran.vinh Nov 05 '14 at 18:56

3 Answers3

39

After much headache and putting this on the back burner, I found that the main problem was when adding files to the test target membership, the Objective-C classes would still complain. I figured it was an old compatibility issue with the new way Swift does unit tests, but the solution was my test target didn't know there was a bridging header. Thus, I added a reference to it in my test target's build settings, like so:

test target bridging header

It seems simple and obvious now, but the errors were unhelpful. No other solutions I saw for Swift unit tests suggested this could be an issue, but now I know.

Tl;dr

For unit tests to work in Swift, the test target must know everything the app target knows, so add a reference to your bridging header in your test target too (if applicable).

tfrank377
  • 1,858
  • 2
  • 22
  • 34
  • I've spent too many hours trying to understand why my tests weren't working. Thank you! – diogocarmo Mar 10 '15 at 16:38
  • 1
    You may have to change the filter from "Basic" to "All" under your test target Build Settings to get this to show up. – Andrew May 04 '15 at 15:27
14

If you're using Xcode 7, there's now a much better way of dealing with this using @testable import {ModuleName}.

Just make sure that the module you want to test has the build setting Enable Testability set to YES.

hwaxxer
  • 3,363
  • 1
  • 22
  • 39
13

I am using Xcode 6.1

You need to add your swift file to the target membership of the test target

enter image description here

idmean
  • 14,540
  • 9
  • 54
  • 83
Anthony Kong
  • 37,791
  • 46
  • 172
  • 304
  • I really need it to work on Xcode 6.0 for automated build reasons, but I tried this in Xcode 6.1 and it gives me "Use of unresolved identifier 'className'" errors. – tfrank377 Oct 31 '14 at 21:54
  • 8
    There has to be a better way to do this. Adding code to the test target slows down the testing a lot. In Objective-C you did not need to do add your sources to the testing target – Julio Bailon Feb 12 '15 at 19:42
  • This also causes problems with symbol resolution. Since the class is included in the binary twice, code that uses `as` can resolve incorrectly. – Greg Jun 29 '20 at 20:14