My colleague and I have been struggling with unit tests now for weeks. We have tried to get SenTest, GTM, and other frameworks set up, but we can never get past a gnarly ball of linking errors.
Here's where I am now with GTM. I would appreciate any guidance.
Beyond helping out on SO, if you have experience with this, I'd happily pay a consultant. Please email me at andrew#gaiagps.com if you think you can help me with this.
I followed the instructions here:
http://code.google.com/p/google-toolbox-for-mac/wiki/iPhoneUnitTesting. I found I also needed to add the file "GTMObjC2Runtime.h" to the project. Then, I was able to get to the point where I got the expected console output after installing the framework: "Executed 0 tests, with 0 failures (0 unexpected) in 0.030 (0.030) seconds"
Next, I went to write a test case for one of my classes. I created WebAPITest.h. I created a simple test, which worked fine. I just verified 1 == 1.
Next, I decided to write a test for my AppDelegate.h. So, I added #import "AppDelegate.h" to WebAPITest.h, and I got 8 linking errors. My project uses FBConnect, and the compiler complain that it can't find the FBConnect files. To address this, I added the the FBConnect header search path to the Test target's build config, and the linking errors went away.
Now is where I am stumped. When I try and reference AppDelegate in the implementation, I get these linking errors:
Building target “fooTest” of project “foo” with configuration “Debug” — (2 errors)
Undefined symbols:
".objc_class_name_AppDelegate", referenced from:
literal-pointer#__OBJC#__cls_refs#AppDelegate in WebAPITest.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
So, I tried adding AppDelegate to the Test target, but then it
started wanting all the dependencies for AppDelegate too, and I'm
guessing I'm not supposed to add dozens of files to the unit test
target.
Any idea what I need to do next?
Your test bundle does need access to the compiled class you are trying to test. It's your decision to accomplish that by either adding it directly to the target (and yes, with all its dependencies), by linking to a library that implements the class, or by setting up your test bundle so that it is loaded by a host application that has an implementation of the class.
This reference might be useful to you:
http://developer.apple.com/iphone/library/documentation/Xcode/Conceptual/iphone_development/135-Unit_Testing_Applications/unit_testing_applications.html#//apple_ref/doc/uid/TP40007959-CH20-SW3
And also from the main unit testing documentation at Apple:
http://developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/Conceptual/UnitTesting/1-Articles/CreatingTests.html#//apple_ref/doc/uid/TP40002171
Look for terms like "Test Host" and "Bundle Loader."
This stuff is not very straightforward to understand but the documentation eventually clarifies everything if you hunker down and plow through it.
Related
My app work well, in the last days I update a language and everything it's ok, today i put the 3th with the same process and my app give me this error "Cannot load underlying module for XCTest" I have just try a lot of solutions but without win...
This is a shot in the dark, as it's not entirely clear what the question here is. If I'm understanding right, though, you added another localization (the 3rd language supported by your app), and this now led to you seeing the Cannot load underlying module for XCTest error. If that's the case, I'd check that your new localization file is set to the right target: it should be set to the main target, not your testing target.
This question and it's answers also seem relevant here, if it's not your localization file it sounds like a file has the wrong target membership.
After reading many SO posts about the same error, I cant seem to resolve the problem with AdMob.
Im trying to implement it into my existing app and I copied the SDK and followed the tutorial.
All compiles fine but the app crashes with:
[GADObjectPrivate changeState:]: unrecognized selector sent to instance 0xa5cc610'
They say I need to add -ObjC or -all_load to Other Linker Flags.
When I do that, I get many, many duplicate symbol errors.
Since Im upgrading a project from a different developer, I dont know
the exact structure of the code.
Any other suggestions?
When you using the Abmob API, they add 2 API for you. 1 for Debug and 1 for real.
2 API have same functions and many things.
(Try to see what happen in your debug screen, they will give you the location of duplicated folder - It in Google Library 3.0/GoogleAnalysis/Library/lib - ...debug.lib)
The simple solution is remove the Debug API and you will be fine.
Addition: Adding ObjC is right for your program, it is other problem.
I am using XCode 3.2.2 to unit test some custom data types. The tests run properly without those data types, but when I use said data types, I get this error:
"_OBJC_CLASS_$_classname", referenced from:
(where "classname" is the, well, class name...)
I have seen hints online that it could be linker related. The strange thing is, I originally followed these instructions http://www.mobileorchard.com/ocunit-integrated-unit-testing-in-xcode/ and they worked for me the first time I tried them. Now, after following the same instructions, I'm getting the same error. Any help would be greatly appreciated.
Thanks!
-Matt
Unfortunately your question is pretty ambiguous.
First, is the example working given in the mentioned tutorial?
Second, I'd double check your code:
Right click the class (.m) you're trying to use with OCUnit and click get info. Make sure the target in the class file is pointing to OCUnit! This is key for the linking.
Are you importing your .h for the associated class in the test case?
Check the spelling of the class names?
I just wanna create a MS plugin to hook SpringBoard. I'm following "gojohnnyboi" tutorial from here "http://www.ipodtouchfans.com/forums/showthread.php?t=103558".
To create a dylib on XCode, I'm following "SkylarEC" tutorial. I mix these two great tutorials and finally got succeed by getting a dylib. But when I placed the dylib in the /Library/MobileSubstrate/DynamicLibraries/ nothing is happened (no alert was shown).
By evaluating, I found that, this dylib doesn't have any starting point when it was loaded into the memory. So I mentioned a starting point by declaring a constructor in the .mm file like,
__ attribute__((constructor)) static void init()
{
Class _$SBAppIcon = objc_getClass("SBApplicationIcon");
MSHookMessage(_$SBAppIcon, #selector(launch), (IMP) &__$ExampleHook_AppIcon_Launch, "__OriginalMethodPrefix_");
}
But when I'm trying to compile this, I'm getting an error like,
**Undefined symbols:
"_MSHookMessage", referenced from:
init() in ExampleHook.o
ld: symbol(s) not found
collect2: ld returned 1 exit status.**
Does anyone has idea how to solve this? It would be great and more helpful if anyone share the detailed tutorial/instructions to create a dylib on XCode.
P.S I placed all the libsubstrate.dylib and substrate.h files in the corresponding location. And the locations are,
libsubstrate.dylib : /Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/
substrate.h : /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr/include
and my base SDK is 3.0.
You should probably check out iOSOpenDev
(These are very old tutorials. Some modern MS code can be found in http://iphonedevwiki.net/index.php/MobileSubstrate. Eventually someone needs to write an updated tutorial...)
Make sure you have added libsubstrate.dylib in your Xcode project (Add → Existing files...). The compiler will not automatically find which dylib to link unless you tell it so.
Try http://unlimapps.com/?p=15 it will be much easier to compile plugins using the methods in that post
You have to copy CydiaSubstrate.framework to /Library/Frameworks in your mac and link to CydiaSubstrate
#include <CydiaSubstrate/CydiaSubstrate.h>
Starting with an app already in development, I have carried out the instructions in the iPhone Development Guide – Unit Testing Applications
I can successfully include and use my App's classes in Application-style tests that run on the device, and output their results to the console.
If I add the following line of code:
STAssertTrue([viewController isKindOfClass:[LoginViewController class]], #"Top view controller is not LoginViewController");
The following build error is generated:
Undefined symbols:
"_OBJC_CLASS_$_LoginViewController", referenced from:
__objc_classrefs__DATA#0 in LoginViewTest.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
I can provide more configuration information for the project and the Testing target, but the setup works file without the [LoginViewController class] line in the test source.
Without that line, I can reference the class, use it's properties and send it messages successfully.
Is there a linking build setting, or bundle loading option that is required when attempting to use an App class in this fashion? Or should I find another type of test to confirm that the class of an object is the expected one?
I have found an answer, but I think there must be a "better" way?
In the build configuration for the Unit Tests bundle, you can specify the Bundle Loader (BUNDLE_LOADER) setting that points to your "host" App.
${TARGET_BUILD_DIR}/AppName.app/AppName
The Unit Tests bundle is being built as a dependency of your App's unit testing target (say, AppName Testing), and as a result I haven't been able to resolve the App executable any better than the above.
The net result is a working unit test injected into the Testing target without any linker errors. The tests run and access the classes as expected.
EDIT: Bundle Loader – Target Configuration
It's important to configure the target that is "hosting" the testing bundle to not hide it's symbols.
GCC_SYMBOLS_PRIVATE_EXTERN = NO
a.k.a. "Symbols hidden by default". From the documentation:
When enabled, all symbols are declared
'private extern' unless explicitly
marked to be exported using
'__attribute__((visibility("default")))' in code. If not enabled, all symbols
are exported unless explicitly marked
as 'private extern'.
For more information, see
http://developer.apple.com/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/SymbolVisibility.html.
I just answered this over here:
iPhone unit testing: Symbols not found when calling custom code
I suppose one of these should be closed as a duplicate? I'm not reputable enough to do so...
I also followed Apple's iPhone Unit Testing Applications document and saw a linking error similar to the one described in the question when trying to unit test one of my classes.
Looks like any class referenced in your unit test class and so being run from your test target also needs to be added to that test target. To do this, you would right click your RootViewController class and click 'Get Info' (Cmd-i shortcut). On the targets pane, make sure your unit test target (e.g. 'LogicTests', if you've followed the naming in that document) is checked.
Now that class will be compiled with your tests and should be available to your unit test. To double check, expand the 'Targets/LogicTests/Compile Resources' node in the 'Groups & Files' browser on the left. This lists all the class files available when building the target and should now include your unit test class together with your class under test.
(Note that you'll need to similarly select all appropriate targets when you create a new application or test class - on the same page of the 'New File...' window when you name the file).
(I'm using XCode 3.2.3 & OS 4.0, by the way).