I'm running into a strange problem that I haven't run into before.
When you do cmd+U to run your Unit Tests (OCUnit for example) does it actually call the main.m, new up the appDelegate and run the app as if your had pressed cmd+R?
I only ask because I'm using CoreData behind this DataLayer. I'm mocking out the DataLayer successfully in my tests, but once I implemented a getAll method that is actually calling CoreData, the app/xcode is throwing an exception about the managed object model can't be nil. Which I understand, but I'm not meaning to actually new up the DataLayer class, and I've put a break point in my mainviewcontroller loadView method where it is calling the DataLayer getAll method. It shouldn't matter with tests because this is a mock object, but it's apparently calling the real instance.
So back to my question, when pressing cmd+U does it also run the app first then run the tests?
⌘U will build and run all your test cases. It is the most commonly used shortcut when creating unit test cases. It is equivalent to ⌘R (build & run) while doing app development. You can use this shortcut to build your test target and run all the test cases in your test target.
Unit tests are awesome. They not only improve the overall quality of your code, they also make it easier for you to test individual pieces of your app without having to manually run your app. Given Apple's extensive support for unit tests in Xcode and Swift, it's surprising that so few iOS developers write unit tests.
The really short version is that unit tests have access to the code in your app (or whatever kind of module you are building) and UI tests do not have access to the code. A unit test only tests one single class per test.
Unit tests can be performed manually or automated. Those employing a manual method may have an instinctual document made detailing each step in the process; however, automated testing is the more common method to unit tests. Automated approaches commonly use a testing framework to develop test cases.
The application is actually run but there is a trick you can use to prevent it from running.
int main(int argc, char* argv[]) { int returnValue; @autoreleasepool { BOOL inTests = (NSClassFromString(@"SenTestCase") != nil || NSClassFromString(@"XCTest") != nil); if (inTests) { //use a special empty delegate when we are inside the tests returnValue = UIApplicationMain(argc, argv, nil, @"TestsAppDelegate"); } else { //use the normal delegate returnValue = UIApplicationMain(argc, argv, nil, @"AppDelegate"); } } return returnValue; }
Here's a variation of Sulthan's answer that uses XCTest, which is the default for test classes generated by XCode 5.
int main(int argc, char * argv[]) { @autoreleasepool { BOOL runningTests = NSClassFromString(@"XCTestCase") != nil; if(!runningTests) { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } else { return UIApplicationMain(argc, argv, nil, @"TestAppDelegate"); } } }
This goes into main.m, which should be under Supporting Files in a standard project layout.
Then in your tests directory add:
TestAppDelegate.h
#import <Foundation/Foundation.h> @interface TestAppDelegate : NSObject<UIApplicationDelegate> @end
TestAppDelegate.m
#import "TestAppDelegate.h" @implementation TestAppDelegate @end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With