Import XCTest in to existing project - ios

I added a new target as a Cocoa Touch Unit Testing Bundle, named the directory "MyAppTests", and the actual framework is not active-- it is highlighted red
When I add the framework by the 'link binary with libraries' in the 'build phases' tab technique, a new Framework is added, instead of updating the one that was created with adding the target.
When I go to run the code, I then run in to all sorts of troubles, ranging from linking errors to other frameworks not being recognized.
How can I activate the XCTest.framework that was generated when I added target? Please help, thank you!

XCTest.framework is the bundle that Xcode uses to enable
#import <XCTest/XCTest.h>
To add test cases to an existing project select the target, right click > file > new > objective c test case class. Then in your build phases you can add the XCTest.Framework. Make sure you check the add to target boxes when creating the test case.

Related

Can't access swift files in Unit test target in Xcode

Adding swift files to test target will work, but it is not the best way to do. My problem is I can't able to access Swift file whereas Objective-C files are accessible.
I have checked product module name and set configuration file same as project file for test target. Even removed the test target and readded, but, still encountering "Use of undeclared type in SlideViewController".
Can anyone help me with solving this issue?
By default you won't be able to access internal classes from your unit test target.
The apple docs on writing tests with swift say that you need to take two steps to get around this:
Set the ENABLE_TESTABILITY build setting to YES.
Add #testable to the import statement for your module. #testable import MySwiftApp
If you follow both of those steps your SlideViewController (as long as it is not a private class) should be accessible from your unit test file as if it was declared as an open class.
Try to add this on top of your test file:
#testable import <YOUR_MODULE_NAME>
Sometimes you will need to add files to the build phases of your test target.
1.- Go to project navigator
2.- Select your project
3.- On the project and target list, select the target for your tests (Ex. "MyProjectTests")
4.- Select Build Phases tab
5.- Open "Compile Sources"
6.- Using the plus sign, add the files needed for the compilation

Xcode won't add "Embedded binary" after deleting "DerivedData"

Alternative titles to aid search:
Adding Embedded Binaries fails in Xcode
Xcode won't link framework from separate project
App crashes on device because of missing framework, works in simulator
Overview
After deleting the "DerivedData" folder (or performing a "Product > Clean") in xcode6, I cannot add CocoaTouch frameworks from another project to the "Embedded Binary" section (under General tab).
Or, Xcode hits a linker error because it cannot find a framework that if previously could.
Other symptoms
Clicking on the + under "Embedded Binaries" shows the Framework selector but selecting a framework in different project in the workspace does nothing.
When you add the framework to the Embedded Binaries, there will be a reference added to your project for it. If you select that reference after your steps above, you will probably find that it has an Absolute Path reference to the framework rather than a relative one, which we'd like. Change the location to Relative to Build Products and the reference should always be discoverable if do a "hard" clean or use another computer etc.
I have made a video which describes how best to add a built framework from one project to an app target in another sibling project.
This it the only way i have discovered to restore the embedded binaries, please leave comments if you find some steps are not required.
Prerequisites: Read Daniel Tull's answer.
Remove all framework projects from the workspace
Perform a "clean build" and/or remove the "DerivedData"
Add project back into the workspace
Build the project (possibly optional)
In the General tab of the app target click the + under "Linked Frameworks and Libraries", select the framework.
Build and run in the Simulator (there should be no issues building or running)
Build and run for device (this might cause a crash due to the framework not being correctly linked, ignore this crash)
Click the + under "Embedded Binaries", select the framework. This should add it to the project (possible duplicate under "Linked Frameworks and Libraries")
Repeat for all required frameworks
Once building and running (on device) is confirmed you can remove any duplicate (and/or red) frameworks in the Project Navigator or target General tab
Just to add to #Daniel's answer, if your Location dropdown is greyed out you may have selected the wrong file. Make sure to select the framework that's in your app project (not framework project).

Migration of OCUnit to XCTest leads to linker error

I've tried to migrate our OCUnit to XCTest. So I have 100% compilable project but I see next linker error:
Error:Undefined symbol '_OBJC_CLASS_$_XCTestCase' referenced from:...
My "Framework Search Paths" looks like this:
$(SDKROOT)/Developer/Library/Frameworks (non-recursive)
$(inherited) (non-recursive)
$(DEVELOPER_FRAMEWORKS_DIR) (non-recursive)
I'm not familiar what else to do to satisfy linker
I am seeing the exact same error messages in Xcode 6.1 after migrating with
Pull Down Menu → Edit → Refactor → Convert to XCTest.
I got 2 solutions:
Solution 1 (recreate test project)
Backup all source files in your test project.
In Project Navigator, select the project.
This shows the project settings.
In the project settings, click Show project and targets list.
Select the test target, and press delete to delete it.
In Project Navigator, select the test target, and press delete to delete it.
In Test Navigator, click the + button on the bottom left, and choose New Test Target.
Add your original source files back into the new test target.
Now test your project as usual.
Solution 2 (hackishly modify test project)
In Project Navigator, select the project.
This shows the project settings.
In the project settings, select the test target (not the main target), then select Build Phases.
In Link Binary With Libraries, click the + button.
This shows the list of frameworks, but there is no XCTest.
Choose a framework that you don't use at all, say, Twitter.framework, and click Add.
Open your project file (something.pbxproj) in a text editor, and replace all occurrences of Twitter.framework with XCTest.framework.
Note: the pbxproj file is inside the .xcodeproj folder. In Finder, you have to right click on the .xcodeproj and select Show Package Contents.
Go back to Link Binary With Libraries in Xcode, and check that XCTest.framework is added.
If not, try restarting Xcode.
If it is added but is red, just ignore it. Xcode can't find the framework, but the linker can.
Now test your project as usual.

How to use a static library (e.g. cocoapods library) on a XCTest?

I'm working with Core Data and, as I the model gets more complex, I need to make sure that the new changes I introduce don't break my model unexpectedly in other parts.
I can create unit tests and run them every time I change something on my model. If something breaks, there might be something wrong with my model or at least I know I have to modify some queries in the main code/tests.
I'm using MagicalRecord to have access to some convenience methods.
I also use cocoapods for the same reason, convenience.
The problem is that cocoapods creates a static library and links it against my target, but in Xcode, new test targets are not automatically configured to link against the same libraries/frameworks the target in question links against to.
How can I have a XCTest link against a static library?
This is not only helpful with MagicalRecord/Core Data, but when you're using an external library it's a good idea to have tests to make sure that updates on the library don't break your App.
If you're using cocoapods, you can simply use link_with to include your test target, but if you're using a static library not created by cocoapods you can do the following:
(I will still use a cocoapods library for the instructions, as that's what I'm working with, but the idea is the same if you're not using a cocoapods library)
Once you have created a new Test Target, click on the project root node in the project navigator and select your test target.
Go to Build Settings and search for Header Search Paths. Double click on the Header Search Paths item and enter
${SRCROOT}/Pods/Headers and select recursive if you want to import all of your cocoapods libraries headers or enter them individually:
${SRCROOT}/Pods/Headers/MagicalRecord leaving non-recursive selected (although in this case it doesn't really matter).
Now search for Linking and in Other Linker Flags add -ObjC
Now with your Test Target still selected, go to Build Phases and in Link Binary With Libraries click on the + and add libPods.a or the other libraries individually (libPods-MagicalRecord.a)
You should be able to run a XCTest using the static library.
Optional: I like to import the headers I know I'm going to use in the -Prefix.pch file. You can go to your target test group in the Project Navigator. Go to the Supporting Files group and open the -Prefix.pch file. For MagicalRecord I like to add:
#define MR_SHORTHAND
#import "CoreData+MagicalRecord.h"
For more information:
Unit Testing with Core Data
Creating a Static Library in iOS
Tutorial
After a lot of fighting, these steps worked for me:
1) Project> Info
On configurations, set the Test Target to share the same Configuration File as your main project (generated by Cocoapods).
Now, you should start to get some errors because XCUnit framework is missing, but now your external libraries imported with CocoaPod are visible on your test project.
2) On the Test Target>Build Settings look for Header Search Paths, once there add:
$(DEVELOPER_DIR)/Platforms/iPhoneOS.platform/Developer/Library/Frameworks
$(DEVELOPER_DIR)/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks
The Unit Test framework is inside your Xcode App, this headers will make them public to be added later.
3) On the Test Target> Build Phases add the SenTestingKit.framework
And it should look like this
From there, everything seems to work for me. Good Luck.

Unit Testing in With A Static Library

I have an XCode workspace with a user interface project (UI) and a core logic project (Core). I want OCUnit unit tests in the UI project, so I have added a new target for testing, as is commonly done.
I am able to run tests just fine until I put in import statements for classes in the main UI target which in turn reference the Core project.
The error I get is "Lexical or Preprocessor Issue 'xxx.h' file not found". I do not get this message when I build the main UI target directly.
It's as if the main UI target knows about Core when it is built, but when it is referenced from the test target it seems to know nothing about Core.
I took the step of adding a reference to the core project using the "Link Binaries with Libraries" The item in the list remains red. A clue? Maybe, but the red reference in the Link list doesn't keep the UI target from building and using core classes. I also made the main target a dependency of the test target.
Make sure you check out the Apple sample code "Unit Tests":
https://developer.apple.com/library/ios/#samplecode/UnitTests/Introduction/Intro.html#//apple_ref/doc/uid/DTS40011742
Make sure your library project is set as a Dependancy in your OCUnit test target's build phases, AND it's linked as a library.
Open up your project in Xcode. In the File menu, go to Project Settings... (or Workspace Settings... if you are using a workspace). Click Advanced... and make sure Unique is checked. Clean and rebuild.
Check your BUILD_PRODUCTS_DIR to see if the headers for your library show up in there. If they don't, first check the build phases in your library target to make sure the headers you need are in the Public section (the Project section may work as well, but try Public and see if that solves your issue).
That covers the most common problems people seem to run into in your situation. When in doubt, check the target settings in the UnitTests sample against yours. Good luck!
In addition to Jon Reid's answer, I had to do the following as well:
In your test target, go to Build Settings. Set "Always Search User Paths" to YES
In your test target, go to Build Settings. Add the path to your static library headers to Header Search Paths.

Resources