Add Test Target to existing project in Xcode 6.3 - ios

Note: this question is related, but the answer given there does not solve the issue for me: XC Testing Framework iOS(XCode 6.1) Test session exited(80) without checking in
I have existing iOS code, and I want to start writing XCTest cases using my Xcode 6.3. I create a Test Target by clicking on the + in the Test Navigator. A test target is created for me, including a file Tests with unit tests in them.
The test starts greyed out in the Test Navigator (I cannot click cmd+T).
Question 1: How can I enable the tests?
EDIT: The answer is described in this screenshot: https://www.evernote.com/shard/s4/sh/6a5ca990-d723-46ee-bf77-2cf0ff4e70b2/1a62c472fbbeeffa595fcecd4a9fbbf7, which I found here: Adding Unit Tests to an already existing project?
In my project settings, I have the following settings for my production target (legacy):
And the following settings for my test target (auto generated):
If I run my test anyway manually by clicking on the Play button in the Test Navigator, I receive the following extensive error messages.
Warning: Error creating LLDB target at path '/Users/erwin/Library/Developer/Xcode/DerivedData/NyonOrder-bzkqdvtkegbjpuccyzmrgprbjqgm/Build/Products/Debug-iphonesimulator/OrderWriter.app'- using an empty LLDB target which can cause slow memory reads from remote devices.
IDEBundleInjection.c: Error 3585 loading bundle '/Users/erwin/Library/Developer/Xcode/DerivedData/NyonOrder-bzkqdvtkegbjpuccyzmrgprbjqgm/Build/Products/Debug-iphonesimulator/NyonOrderTests.xctest': The bundle “NyonOrderTests” couldn’t be loaded because it doesn’t contain a version for the current architecture.
DevToolsBundleInjection environment:
XCInjectDiagnostics: (null)
XCInjectBundleInto: /Users/erwin/Library/Developer/Xcode/DerivedData/NyonOrder-bzkqdvtkegbjpuccyzmrgprbjqgm/Build/Products/Debug-iphonesimulator/OrderWriter.app/OrderWriter
XCInjectBundle: /Users/erwin/Library/Developer/Xcode/DerivedData/NyonOrder-bzkqdvtkegbjpuccyzmrgprbjqgm/Build/Products/Debug-iphonesimulator/NyonOrderTests.xctest
TestBundleLocation: /Users/erwin/Library/Developer/Xcode/DerivedData/NyonOrder-bzkqdvtkegbjpuccyzmrgprbjqgm/Build/Products/Debug-iphonesimulator/NyonOrderTests.xctest
TMPDIR: /Users/erwin/Library/Developer/CoreSimulator/Devices/7094B929-04BD-459E-8E83-BDF9CBFA397A/data/Containers/Data/Application/B02B9956-754B-4663-9BC2-7191B0C2BFFE/tmp
DYLD_LIBRARY_PATH: /Users/erwin/Library/Developer/Xcode/DerivedData/NyonOrder-bzkqdvtkegbjpuccyzmrgprbjqgm/Build/Products/Debug-iphonesimulator
DYLD_INSERT_LIBRARIES: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/IDEBundleInjection.framework/IDEBundleInjection
DYLD_FRAMEWORK_PATH: /Users/erwin/Library/Developer/Xcode/DerivedData/NyonOrder-bzkqdvtkegbjpuccyzmrgprbjqgm/Build/Products/Debug-iphonesimulator
DYLD_FALLBACK_LIBRARY_PATH: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/lib
DYLD_FALLBACK_FRAMEWORK_PATH: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks
*** Test session exited(80) without checking in. Executable does not provide an architecture compatible with the current process. If you believe this error represents a bug, please attach the log file at /var/folders/cn/sfcysstx0zxb13qzdj35rh040000gn/T/com.apple.dt.XCTest-status/Session-2015-04-10_13:58:25-8ifyOV.log
Question 2: Which settings do I additionally have to check/change to be able to run tests?
EDIT Adding arm64 to the production target valid architecture solved this particular error. Is this dangerous to add?

Related

Unit tests of xcframework

I made my xcframework but I can't run its unit-tests on iPhone because:
Logic Testing Unavailable Logic Testing on iOS devices is not
supported. You can run logic tests on the Simulator.
I found out it means I have to set host app for my xcframework. So I injected the framework into a host app project - just dragged it. And I got a nested structure with two test targets, one for the host app and the other for the framework. The first one is not needed at this point but the second one still doesn't want to run tests because host app isn't set. I managed to do it by setting these fields in Build Settings:
Test Host: $(BUILT_PRODUCTS_DIR)/HostApp.app/HostApp
Bundle Loader: $(TEST_HOST)
Please note: I did this in the second test target. After that, Xcode allowed the tests to run, but they hang every time they run. And a warning appeared:
/Users/xxxxxxxxxx/MegaApp/Framework/Framework.xcodeproj Unable to find
a target which creates the host product for value of $(TEST_HOST)
'/Users/xxxxxxxxxx/Library/Developer/Xcode/DerivedData/HostApp-xxxxxxxxxxxxxxxxxxxxxxxxxx/Build/Products/Debug-iphoneos/HostApp.app/HostApp'
This looks like Xcode expects framework's main target to produce the binary of the host app I specified in its test target. But framework's main target does the other work in accordance with its purpose. And I got stuck here.
Anyway, is it something that can be easily fixed or it's impossible to run tests for xcframework on device?

iOS UI Tests Linker Error

I'm trying to run some UI tests for my iOS app. I was successfully able to record my UI tests, but when running them, I get a linker error:
I have a UI Testing Target added to my project, and my UI Test file has been added to that target.
I've already been able to write and run several Unit Tests without a problem.
Anyone know where I should look to solve this, or have a guess what the problem may be?
EDIT: The full log output shows that the UI test file can't import an SDK that my target app relies on.
For some reason, when I created my UITest target, a linker flag was added in the target that shouldn't have been there (-lMySDK).
Removing that flag resolved the linker error.

XCode UI Testing: Unable to find test runner app containing test bundle path

I have written UI Tests in XCode 7.3.1 on a dedicated target. I can record a UI test but if I try to launch it (all tests or a single one), I got the following error :
Unable to find test runner app containing test bundle path /Users/dle/Library/Developer/Xcode/DerivedData/Keecoach-exynmciqyehgmxcfxhkpksrqifsb/Build/Products/Debug-iphonesimulator/DemoKeecoachUITests-Runner.app/PlugIns/DemoKeecoachUITests.app
I do not really understand the message except that it appears a runner app has to launch the tests and that runner app is not existing. This DemoKeecoachUITests-Runner.app does not actually exist on my disk.
I cannot find anybody else mentionning the problem anywhere... I get the same error if I launch the tests in command line with xctool. I have the same problem on other computers, but I do not have the problem on other project, so it is related to the project. Any clue ?
Found it!
Was due to the Wrapper Extension build setting. It was set to app for the project and so inherited for each target. I switched it to nothing for the projet, app for the application target and xctest for the test targets.
Now the generated binaries for tests are ABCTests.xctest and not ABCTests.app anymore. It was probably like this from a long time, but I don't know for what reason...

When do app sources need to be included in test targets?

In a new project I have this simple test
#import <XCTest/XCTest.h>
#import "ViewController.h"
#interface ViewControllerTests : XCTestCase
#end
#implementation ViewControllerTests
- (void)testExample
{
// Using a class that is not in the test target.
ViewController * viewController = [[ViewController alloc] init];
XCTAssertNotNil(viewController, #"");
}
#end
ViewController.h is not part of the test target yet this compiles and runs the tests with no issues.
I think this is because the application is built first (as a dependancy) then the tests. The linker then figures it out what the ViewController class is.
However, on an older project, with exactly the same test and ViewController file, the build fails at the linker phase:
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_ViewController", referenced from:
objc-class-ref in ViewControllerTests.o
This linker error occurs even if when a fresh XCTest unit testing target is created.
To get around this instead, it is possible to include the sources in both the app and the test targets (tick both boxes in the image above). This causes build warnings for duplicate symbols, in the simulator's system log (open the simulator and press cmd-/ to see this):
Class ViewController is implemented in both
[...]/iPhone Simulator/ [...] /MyApp.app/MyApp and
[...]/Debug-iphonesimulator/LogicTests.octest/LogicTests.
One of the two will be used. Which one is undefined.
These warnings occasionally cause issues illustrated by the following example:
[viewController isKindOfClass:[ViewController class]]; // = NO
// Memory address of the `Class` objects are different.
NSString * instanceClassString = NSStringFromClass([viewController class]);
NSString * classString = NSStringFromClass([ViewController class]);
[instanceClassString isEqualToString:classString]; // = YES
// The actual class names are identical
So the question is what setting(s) in the older project are requiring application source files to be included in the test target?
Summary of comments
Between the working and the non-working project:
There is no difference in the linker output (the command starting with Ld).
There is no difference in the target dependancies (there is 1 dependancy to the test target,which is the app)
There is no difference in the linker settings.
I spent some time figuring this out.
If you read this documentation you find that Xcode has two modes for running tests. Logic Tests and Application Tests. The difference is Logic tests build their own target with your Classes and symbols built right in. The resulting executable can be run in the simulator and reports test output back to Xcode. Application tests on the other hand build a dynamic library linking to your code which is injected into the app at runtime. This allows you to run tests in iPhone environment and test Xib loading and other things.
Because the symbols are missing from your test target when you unlink the source files it appears your older project seems to have a test target configured for logic tests, not Application (unit) tests.
As these days Xcode seems to be trying not to distinguish between the two and defaults to creating an Application Tests target lets walk through all the things you might have to change to turn your Logic Test Target into a unit test one.
I'm also going to assume that you have an Application Target and not a static library target as the directions will be a little different.
In the build settings for your test target delete "Bundle Loader" and "Test Host" build settings. We will get Xcode to add these back later
You need to remove all the .m files from your application from the test target. You can either do this by selecting all the .m files and removing the test target in the Xcode File inspector or you can use the compile sources build phase of the test target.
Change the "Framework search paths" for your test target. For Xcode 5 they should be
$(SDKROOT)/Developer/Library/Frameworks
$(inherited)
$(DEVELOPER_FRAMEWORKS_DIR)
in that order and with no extra quotes or backslashes
Go to the General pane of your test target's build settings and select your target from the drop down menu. If the menu already specifies your application target you should toggle it off and on again. This will make Xcode reconfigure the Bundle loader and Test Host settings with the correct value.
Finally double check your application's scheme. In the scheme drop down select edit scheme. Then click the test action. Make sure you test target is in the list on the info pane and make sure all the tests are selected.
This information more or less comes from the above linked documentation, but I updated the steps for Xcode 5.
EDIT:
Hmm 100% note what eph515 is saying about debug symbols being visible but you might also want to check that someone didn't set your scheme's test action to build in the Release or other configuration. Click the scheme selector an choose edit scheme. Click the test action and then make sure the Build Configuration is Debug
If you have a Static Library Target
So if you have a static library target you have two options:
1. Logic Tests
2. Application tests in a host app
For 1. you have to make sure that Bundle Loader and Test Host are empty for your static library target. Your sources then have to be compiled into the test target as they would have no other way to be run.
For 2. You need to make a new app Project in Xcode and add your static Library project as a subproject. You then need to manually copy the Bundle Loader and Test Host build settings from your New App's test target to your Static Lib test target. Then you open the scheme for your new Test App and add your test target to the tests action for the new app.
To run the tests on your lib you run the test action for your host app.
On Xcode 6, I was able to fix this problem by checking "Allow testing Host Application APIs" in the test target > General > Testing.
I ran into this as well and followed jackslash's recommendation but with one more addition: Select your main target and looks for Symbols Hidden by Default (under Apple LVM 5.0 - Code Generation), if the value is Yes, change it to No. This seems to 'un hide' all the symbols of the compiled sources that the unit test target is looking for. Works for me. Please make sure that you include all the steps that jackslash outlined as well.
The answer was a combination of jackslash's and eph515's answers.
As in eph515's answer symbols hidden by default should be No for debug.
Also deployment postprocessing should be No for debug.
Also all libraries that are included in the test target should be removed from the unit test. All that should be left are the 3 in the screen shot plus anything that is specific to unit testing.
Also if there is a run build script build phase at the end of the list, then it should be removed (since it is an artefact of unit testing).
Then do everything in jackslash's answer.
In my case in Xcode 6.2 was error in different architectures in project target and tests target.
Project target has only armv7 and armv7s architectures (because of some older library)
Project Tests target has armv7, armv7s and arm64 architectures.
Removing arm64 architecture solve this issue for my case.
Project Editor -> Project Tests target -> Build Settings -> Valid Architectures = armv7 armv7s
(perhaps it is needed also to set "Architectures" instead of $(ARCHS_STANDARD) to $(ARCHS_STANDARD_32_BIT))
For me it was just a case of having no test targets added for the Scheme.
For the app target go to Edit Scheme, then click Test on the right hand side then add a test target with the + button at the bottom:
When you create a Unit Testing Bundle(Unit Testing target) for testing application you have two options
Enable Allow testing Host Application APIs
General -> Host Application <app_name> -> >check< Allow testing Host Application APIs
slow build
Add every app's tested file into Target Membership[About]
you should take care of classes dependencies which are used into testable class(they should be added too)
When you write a test and no one option was not enabled you can get
Undefined symbol: nominal type descriptor for <class_name>
Undefined symbol: type metadata accessor for <class_name>

xcode 4 fails to initiate unit tests (with linker error) after I created a new scheme

My unit tests worked fine in xcode4 until I had to create a new schema to compile a package to run on my device for testing.
All I did was creating a new Target and a new Scheme, now I try to run the unit tests and get the following error:
The test bundle at [...]Tests.octest could not be loaded because a link error occurred. It is likely that dyld cannot locate a framework framework or library that the the test bundle was linked against, possibly because the framework or library had an incorrect install path at link time.
What did I break?
Like #Haoest and #Peter DeWeese above's comments to Answer 1 - I had exactly the same problem when I changed the product name.
To fix this for the case where you've renamed the product, you need to go to the Build Settings tab of the test target, and change the Linking section - the Debug and Release bundle loader settings. If you have renamed the product - the directory and name of the application may both be incorrect.
Thanks to both of them for pointing this out - but I thought this alternative fix for this situation deserved a higher profile than a comment.
I've also run across problems with Xcode 4 after adding a target to an existing project. I eventually figured out that the Xcode DerivedData for the project was damaged. By deleting that data, I caused Xcode to rebuild the data and the project returned to normal. I found the data in my home Library folder (~/Library/Developer/Xcode/DerivedData/).
I tried everything (including the other answers and those noted here http://twobitlabs.com/2011/06/adding-ocunit-to-an-existing-ios-project-with-xcode-4/), but finally found a different solution:
Set Deployment Postprocessing (in the Deployment section of Build Settings) to NO for the Debug target.
Before I did this, the executable was being stripped, and the link would fail with
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_SomeClassUnderTest", referenced from:
objc-class-ref in SomeTest.o
No matter that Strip Linked Product and Strip Debug Symbols During Copy were set to NO, it made no difference - only changing the Deployment Postprocessing setting finally made sure that the symbols were not stripped.
Same error message, in my case I wasn't linking one of the classes that were needed during the tests.
I discovered my problem was that I had 'Link time optimisation' enabled on my debug build. Setting it to no resolved the problem.
We were using nodejs-mobile which would build with the app but fail building with the tests.
Undefined symbols for architecture x86_64:
_start_node
In addition to all of the previous answers (build settings, search paths, making a brand new Unit Test, deleting DerivedData), what finally resolved it was creating a brand new new UI test instead of a Unit Test in Xcode.
It built successfully. Then you can copy your test definitions from your current test to the one one.
If you do not need the UI part, you can uncomment XCUIApplication().launch() in setUp of the generated tests, which makes it run as fast as before.

Resources