28

I've been following Apple's documentation on writing unit tests for the iPhone, and out of the box, the routine doesn't seem to work. I'm not sure I understand where the unit test is going to get the reference to the application delegate.

My Dependencies are like the following: My_Program_target -> UnitTesting_target -> UnitTests_bundle

The following code snippet is where the assert fails. I'm very familiar with CPPUNIT, but I'm having trouble understanding how this crosses over.

- (void) testAppDelegate {

    id yourApplicationDelegate = [[UIApplication sharedApplication] delegate];
    STAssertNotNil(yourApplicationDelegate, @"UIAppliation failed to find the AppDelegate");

}

Additionally:

I've decided in my approach to do a logic test. I'm trying to read in an XML file, but I'm not having luck resolving the bundle, which will provide me with the path by which I can access my file. I've tried pasting in the path output by allBundles, but that path doesn't seem to work either. Below is what I'm executing in my test (you can see the debug statement I'm using to output the paths of the bundles):

NSLog(@"BundlePaths: %@", [NSBundle allBundles]);
   NSString * path = [[NSBundle bundleWithPath:@"$(TARGET_BUILD_DIR)"] pathForResource:@"SimpleTestList" ofType:@"plist"];
   STAssertNotNil(path, @"Bundle Location couldn't find the file specified");

Essentially, the assert on path is not successful, but I'm not sure what to put for the path or directory to reference my unitTest bundle that I've told to copy the bundle resources. Calling [NSBundle mainBundle] does not work either.

Gary
  • 1,515
  • 1
  • 14
  • 22
  • Building off of Gary's solution, I came up with the following [Xcode: TEST vs DEBUG preprocessor macros](http://stackoverflow.com/questions/6748087/xcode-test-vs-debug-preprocessor-macros/6763597#6763597). – ma11hew28 Jul 20 '11 at 14:39

3 Answers3

72

Ok, so I've figured it out. In order to open a file in a unit test, you'll need to specify the file to open as:

NSString * filePath = [[NSBundle bundleForClass:[self class] ] pathForResource:@"SimpleTestList" ofType:@"plist"];

If you include this in a class that's compiled as part of your unit test bundle, that class will look inside the unit test bundle for the file SimpleTestList.plist.

For a unit test, just make sure you set up "Copy Bundle Resources" to include your plist in your unit test bundle.

Gary
  • 1,515
  • 1
  • 14
  • 22
  • That was exactly my problem too. Thanks for posting this! – kubi Aug 07 '09 at 10:45
  • No problem! Glad it helped! =) – Gary Aug 25 '09 at 05:03
  • Also, in case anyone's wondering, I also came across this link as well in regards to managedObjectModels. Similar situation. http://www.spacevatican.org/2009/9/10/unit-testing-core-data-iphone-apps – Gary Mar 08 '10 at 04:38
  • 1
    I had to tweak it like this: `NSURL *modelURL = [[NSBundle bundleForClass:NSClassFromString(@"NSManagedObjectModel_AdditionsTests")] URLForResource:@"Tests" withExtension:@"momd"]` – ma11hew28 Jul 20 '11 at 02:56
3

If you need the application delegate, you have to run the unit tests on the device itself and not the simulator. Also, you will see unit test output appear in the console, not in the build results.

The key thing to know is that there are two types of unit tests - logic tests that are run outside of the executable, and then integrated system kinds of tests that need the full running environment.

The logic tests MUST be run with the simulator selected as the target or they will not run.

The integrated system tests MUST be run as part of the executable, on the device - you'll want a new target to accomplish this.

Sorry this is all so complex, this aspect is still very much a work in progress compared to many other unit testing frameworks.

Kendall Helmstetter Gelner
  • 73,251
  • 26
  • 123
  • 148
  • Hmm, having the application delegate probably won't be necessary for what I'm doing then. What I'm trying to accomplish at the moment is test my model. Prior to OCUnit in the latest devkit release, I had my testing done in a derived class within my application. I would instantiate that derived class, and it would test itself in a separate thread prior to running and displaying the view the user sees. I'm trying to factor that out into a unit test where it belongs. My current problem now is I'm having issues getting the OCUnit test to see the plist file, even tho it is in the bundle. – Gary Jul 08 '09 at 19:07
  • ...actually by "in the bundle", I mean that I added it into that copy folder in the bundle. – Gary Jul 08 '09 at 19:08
0

The Swift 3 translation of Gary's answer above (using an URL instead of a string path) is:

let url = Bundle(for: type(of: self)).url(forResource: "SimpleTestList", withExtension: "plist")

Notice the critical and non-obvious part type(of: self) instead of [self class].

Frederick Squid
  • 493
  • 4
  • 13