Last Updated: February 25, 2016
·
989
· lukestringer90

Determining test/production target programatically

Thanks to the great guys at objc.io for their post on view controller testing for this hint.

When running unit tests within Xcode you want your app to launch in the simulator or on a device, but you don't need anything more than the bundle to be loaded. You don't need the root view controller of your app to be initiated and added to the window for example. This behaviour could contaminate your tests if say managed objects are saved into core data and you tests depend on seeding core data in a controller way in your setUp calls.

So the solution is to augment your app delegate like so:

// Helper function to see if we are running the production target or the test target
static BOOL isRunningTests(void) __attribute__((const));
static BOOL isRunningTests(void) {
    NSDictionary* environment = [[NSProcessInfo processInfo] environment];
    NSString* injectBundle = environment[@"XCInjectBundle"];
    return [[injectBundle pathExtension] isEqualToString:@"octest"];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    if (isRunningTests()) {
        return YES;
    }

    // Normal logic here
}