Xcode 6 Testing Target Troubles

2019-08-09 02:43发布

问题:

I've been going through many questions and answers here, and have ended up in a quandary.

Now that I'm happy with the state of my project code, I wanted to implement unit testing. So I added a testing target, can I get it to compile correctly? No.... I'm sure it's something simple, but I cannot work it out.

The project contains 2 3rd party private frameworks.

My test target bundle loader parameter is set to:

$(TEST_HOST)

My test target test host parameter is set to:

$(BUILT_PRODUCTS_DIR)/My App.app/Contents/MacOS/My App

When I try to compile, I get errors like this:

Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_MyArrayController", referenced from:
      objc-class-ref in SMyAppLogicTests.o

I look this up, and find answers like this on: XCTestCase: ld: symbol(s) not found for architecture x86_64

Basically saying I need to add my classes to my test target. This seems to kind of defeat the point building on top of the working app, but what the hey. So I add all .m files to the test target, and it compiles! Hooray, but, I have new problems:

Class MyClass is implemented in both /Users/georgebrown/Library/Developer/Xcode/DerivedData/My_App-akedavtbgqpujscilxqmhsvikcku/Build/Products/Debug/My App.app/Contents/MacOS/My App and /Users/georgebrown/Library/Developer/Xcode/DerivedData/My_App-akedavtbgqpujscilxqmhsvikcku/Build/Products/Debug/My App Tests.xctest/Contents/MacOS/My App Tests. One of the two will be used. Which one is undefined.

That makes sense, why do I have to put the m files in if they're already contained in my app. So I look it up, and get an answer that puts me back in the first position:

Class Foo is implemented in both MyApp and MyAppTestCase. One of the two will be used. Which one is undefined

What am I missing? I've been stuck for a week just trying to implement testing in Xcode (Not to mention what Xcode server did to my server, I still have to figure that out), when I planned a 3-4 days for writing the tests foolishly thinking it would be a quick setup.

EDIT: I deleted my test target and started again. First thing that didn't work is that it couldn't find my 3rd part private frameworks. So I added $(PROJECT_DIR) to the frameworks search paths.

Next, I started getting the Undefined Symbols for architecture error again for my classes. I noticed my Bundle Loader was unset, so I set that to be $(TEST_HOST), now the tests run! Hooray.

Now I can't build for the Run Action, but build for Test works..... Progress I guess. I get the Undefined symbols for architecture x86_64: error again.

I've managed to fix that by editing the scheme, and deselecting "Run" for the test target on the build. I'm not sure I entirely understand how the scheme is supposed to work, however, it did the trick.

回答1:

The XCTesting thingie works by injecting the test bundle into the app at runtime. When you add a new test target, Xcode takes care of setting up all that stuff for you: I'd suggest if you have a test target that is giving you grief, you create a new one in Xcode and transfer your test cases to that target. Then you only have to follow three rules:

  1. Add your class implementation files only to app targets, never to test any test targets. This will prevent the "Class Foo is implemented in both MyApp and MyAppTestCase. One of the two will be used. Which one is undefined" warning
  2. Add your XCTestCase files only to test targets.
  3. '#import' the header files of each custom class that you use in a test case.