In a new project I have this simple test
#import <XCTest/XCTest.h>
#import "ViewController.h"
@interface ViewControllerTests : XCTestCase
@end
@implementation ViewControllerTests
- (void)testExample
{
// Using a class that is not in the test target.
ViewController * viewController = [[ViewController alloc] init];
XCTAssertNotNil(viewController, @"");
}
@end
ViewController.h is not part of the test target yet this compiles and runs the tests with no issues.
I think this is because the application is built first (as a dependancy) then the tests. The linker then figures it out what the ViewController class is.
However, on an older project, with exactly the same test and ViewController file, the build fails at the linker phase:
Undefined symbols for architecture i386: "_OBJC_CLASS_$_ViewController", referenced from: objc-class-ref in ViewControllerTests.o
This linker error occurs even if when a fresh XCTest unit testing target is created.
To get around this instead, it is possible to include the sources in both the app and the test targets (tick both boxes in the image above). This causes build warnings for duplicate symbols, in the simulator's system log (open the simulator and press cmd-/ to see this):
Class ViewController is implemented in both [...]/iPhone Simulator/ [...] /MyApp.app/MyApp and [...]/Debug-iphonesimulator/LogicTests.octest/LogicTests. One of the two will be used. Which one is undefined.
These warnings occasionally cause issues illustrated by the following example:
[viewController isKindOfClass:[ViewController class]]; // = NO
// Memory address of the `Class` objects are different.
NSString * instanceClassString = NSStringFromClass([viewController class]);
NSString * classString = NSStringFromClass([ViewController class]);
[instanceClassString isEqualToString:classString]; // = YES
// The actual class names are identical
So the question is what setting(s) in the older project are requiring application source files to be included in the test target?
Summary of comments
Between the working and the non-working project:
- There is no difference in the linker output (the command starting with
Ld
). - There is no difference in the target dependancies (there is 1 dependancy to the test target,which is the app)
- There is no difference in the linker settings.
-framework XCTest
in one andObjC
in the other. I corrected this difference and it still failed to compile :( Can you think of anything else? – Tootsielink
step. Check differences between arguments passed to the linker. – HaemophilicLd
). The first was these 2 additional flags:-fprofile-arcs
-ftest-coverage
. I deleted these 2 options and added it made no difference. The other was-F/Applications/Xcode.app/Contents/Developer/Library/Frameworks
was repeated 4 times in a row in the non working project, but only 2 times in a row on the working project. However I don't think that will be it (its is probably included once per framework linked). – Tootsie