Reputation: 12132
I've successfully added a normal Unit Testing Bundle to my project, following these instructions. I can build and run my test target and the one sample test works fine.
Things start to go downhill when I try to test a specific class.
In my App, many of my .h files are included in the .pch file. Also, MyModel interacts with other classes. Because of this, when I import MyModel.h and use it in my test, I get a bunch of errors pertaining to the fact that other files couldn't be loaded. My workaround to this is to simply add the same files in my test target's .pch file and also add those files to the test target's "compile sources" list.
So I add those classes to the test target and to the .pch, try to run, and I just end up in an endless loop, always needing to require more files. When I finally add every .m to my project, running the tests still fails spectacularly.
Any idea how I need to set up my project correctly so that I can just simply #import "MyModel.h"
into my test file and write/run my tests? Is it possible that my project is configured in a way that will make testing impossible?
Update 1 Followed Carl's suggestions but can't get past step 2. I get:
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_MyModel", referenced from:
objc-class-ref in BaseUnitTests.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
It's at this point where I would then add MyModel.m to "Build Phases/Compile Sources" and go down the endless path of adding every other .m file to the test target's "Compile Sources".
Upvotes: 3
Views: 1323
Reputation: 35131
I got the same problem, and solved by just adding xxx-Prefix.pch file path to GCC_PREFIX_HEADER for my Tests Target like what I do for the main App Target:
Upvotes: 1
Reputation: 18363
Code can definitely be written in ways that make testing difficult, especially when it wasn't written with testing in mind. But it's not impossible. Right now you just need to clean up your imports. I think the approach I'd take is
1) Remove all your non-test-case class implementations (.m) from the tests target - they don't need to be there. Do this by removing them from the "compile sources" pane in the test target's build phases.
2) Copy all your PCH imports into your test case (temporarily). Import "MyModel.h"
. Try to just get an instance of MyModel
and test it isn't nil
and has the right class. Just keep adding imports if you need to but don't add .m's.
3) This and the next step are optional but I highly recommend them, as they might reveal trouble areas in your code that will prevent you from writing fine-grained tests. Once you get that simple test passing, it's time to start cleaning up your imports. Switch back to your main project. First things first, I'd start removing any of your own classes from the pch (not counting library / framework type imports). Remove headers from the pch one at a time, and import them in the files that truly need them.
3a) As you're going through this process make sure you import as few files from other header files as possible. You should only have a #import in your .h in a few situations, generally: 1) Subclassing a class declared in the imported file 2) Implementing a protocol declared in the imported file 3) referring to any C type defined in the imported file. For protocols and classes, forward-declare them with @protocol and @class in the header and only import them where you actually message them or access their properties (usually in your .m)
So, at this point, you should have a single passing unit test and a cleaner pch. Make sure to clean up the imports in your unit test now. Switch back to your testing target, and start writing more tests. As you make your interfaces more focused and testable, the need to import files will decrease. Hope this helps!
Upvotes: 1