What conditions enable the Xcode 4 "Product > Test" menu option? - xcode

It's not entirely clear what enables the "Test" option for a product in Xcode 4. It is enabled when you create a new project with an associated .octest target.
Is there a flag or an option to link a particular target as a test of another? The reference material only seems to talk about making tests when they are working, not getting them working in the first place.
What I'm trying to do is use a non-Objective-C test framework, in this case Catch, for testing a cross-platform C++ application. Objective-C, with the associated Foundation library, is not available on the target.

If you need to add third-party test frameworks to an Xcode project, you can do this by replacing the "Build Phase" associated with running what is, by default, otest.
Add a target that compiles your third-party test suite into an executable form. This is independent to the .octest target.
Add this target as a dependency of the main ".octest" target under "Build Phases", "Target Dependencies" to ensure the tests are compiled as required.
Replace the "Run Script" section with whatever is required to execute your tests. Typically it looks something like:
DYLD_LIBRARY_PATH=$TARGET_BUILD_DIR "${TARGET_BUILD_DIR}/myCustomTests"
This presumes there's an executable called myCustomTests produced by the custom test target and also configures the DYLD_LIBRARY_PATH to include the build directory so that any custom libraries are loaded properly.

Related

How do I add a framework dependency to a test target?

I have created a framework that contains code useful for testing (a bunch of convenience initializers, for example). Now I would like to import that framework in a test target but there doesn't seem to be a way to do this in Xcode. Just importing it with import Dependency gives me the "Module not found" error when building.
The General tab of the test target does not have any settings for that (or any settings):
The Build Phase tab has a Dependencies section, but the framework I want to add does not show up in the list when I press the + button:
There's also a Link Binary with Libraries section, but when I try to select the framework there Xcode says that file is already being linked (where?):
I can import and use the framework if I add it in the Frameworks, Libraries and Embedded Content section of the main target, but I don't want to do this since the framework is meant to be used only in the test code. I don't see the reason to pollute the namespace with all the extra initializers. I could probably try to check if no XCTest classes are available at runtime and crash, but that seems like a workaround rather than a solution.
Any advice?
P.S. I'm using the latest version of Xcode (11.3.1).
If you have a source code you are able to use Explicit dependency[About] with cross-project reference
drag and drop dependency project inside a test target
Build Phases -> Dependencies -> Plus(If you didn't include dependency into test target on previous step)
Import
[Mixing Objective-C and Swift]
Xcode 12
Drag and drop the framework into folder where tests are located.
Go to YourAppTests target settings: Build phases -> Link Binary With Libraries – here your framework should be listed, if not tap on + button -> Add other (on the bottom) and choose your framework from project's test folder
Done!
PS: most likely works for Xcode 11 as well

failed to emit precompiled header

Good Afternoon
I am trying to implement googles heatmaps into my map based project.
In this particular project, I get the following errors when trying to build.
failed to emit precompiled header '/Users/zachwilcox/Library/Developer/Xcode/DerivedData/OddJobs-gbnkfettubuccoheinzfovrqefub/Build/Intermediates.noindex/PrecompiledHeaders/OddJobs-Bridging-Header-swift_3WGH9SNI96Z2-clang_16JN3VASQHE4C.pch' for bridging header '/Users/zachwilcox/Desktop/OddJobs/OddJobs-Bridging-Header.h'
and a follow up that says
'Google-Maps-iOS-Utils/GMUHeatmapTileLayer.h' file not found
I'm not sure why this is happening because I created an entirely new project and did the same implementation and it worked perfectly. But when I run it on my existing project I get these two errors.
I have been researching this problem for a while now and I can't figure out what the problem is. I have the Bridging header set to the .h file.
I have tried most steps that individuals have tried to give with their answers but for some reason, it's not working for my project. Thank you in advance. When reading googles installation guide, it said that all I needed to add was one bridging header file which is the code you see in the image below. When researching it, I have seen that I needed to add a .m file as well however I still get the same error when I do. again, in my dummy project, I don't have the .m file just everything you see below and everything compiles.
There are chances you have 'Find Implicit Dependencies" turned off for the selected Scheme. If you have updated/installed pods and try to build the project, it will more likely fail if this option is unchecked for the selected Scheme.
From Apple's Document:
Parallelize Build – This option allows Xcode to speed up total build time by building targets that do not depend on each other at the same time. This is a time-saver on projects with many smaller dependencies that can easily be run in parallel.
Find Implicit Dependencies – This is a very powerful option that allows Xcode to resolve what targets need to be built for the primary target of the scheme to be built successfully. However, this does come with some sharp edges that you have to be aware of.
Situation: You link a library against your application target and create an implicit dependency to that library’s target.
Scenario 1: “Find Implicit Dependencies” is enabled.
Result: The library will get built prior to building the application target. The application target will then link against the library and build successfully.
Scenario 2: “Find Implicit Dependencies” is disabled.
Result: The library will not get built prior to building the application target. The application target fail to build.
Fix: To ensure that the second scenario does not happen, you must add the necessary targets into the targets list and order them correctly.
If your project includes pod then you've to set the pod configuration for the test project too..
Select Root Project in File inspector -> Project Name -> Info -> Configurations
Set configuration for your test project same like your main project

XCTest with multi targets project

I have a XCode(in Swift) project with multi targets. Each target has its own macro that program can know which target is being run.
For example,
FreeVersion target has a macro "FREE"
PaidVersion target has a macro "PAID"
I would like to make test code with XCTest but it seems like XCTest source cannot be related to a specific target.
What is the best practice for using XCTest in such a situation?
Actually, the test bundle is associated with a specific app target through the TEST_HOST build setting. So I think it should be possible to set up two test targets. Each can have its own prefix header (pch) to set the macro you need, and specify their TEST_HOST.
If you duplicate your current test target, be sure to check the new build settings carefully. I've found that Xcode likes to change some settings in the duplicate but not others.

Writing XCTestCase for Mac OS Command Line Tool

I am trying to unit test a command line tool written for Mac OS.
When I first create the project, XCode does not generate a tests group in the project navigator. When I try to add a new test target, it doesn't give me the option to specify my target as the "Target to be Tested".
My question is this: is it even possible to use XCTest for a Command Line Tool project? Or is it just considered trivial to do so by virtue of the fact that I could just run it from the command line? I could understand that reasoning, but there is internal functionality I'd really like to test.
I'm not sure what version of Xcode you are using, but I ran into a similar problem using the templates in Xcode Version 6.2 (6C131e). That said, I was able to get XCTests to work with a Command Line Tool project. The solution was to ignore the "Target to be Tested" field during creation and instead add the Test target to the main scheme after creating it:
Go to Manage Schemes. You should see your main Target’s scheme and a
newly created test scheme.
Select you main scheme and go to Edit.
Select the Test action and add your new Test target to the tests
list using the “+” in the Test action detail panel.
From there you should be able to run the tests using cmd-U.
In Xcode 8.2, I was only able to run unit tests in a command line app by adding a unit test target from the Test Navigator, then editing the testing scheme to include that new test target under the "tests" list, and manually adding testable source files to the test target from the "target membership" section of the File Inspector pane.
(Adding a unit test target from the project "add target" screen wouldn't link properly with XCTest framework, even after adding the framework to build phases.)
Following the Apple doc directions for adding a unit test target from the Test Navigator pane looks like this:
Note:
In the Unit Test Target setup, the "target to be tested" dropdown still won't select the command line tool. Leave this option as "None".
For adding unit test target (XCTest) for Mac OS Command Line project which has(main.swift and other swift files), to make this work,
1.Add UnitTests target to scheme by editing in manage schemes
2.Make your functions and classes has PUBLIC access
This solved my linking errors. Hope it helps for you guys as well

How to set up working logic unit tests target in Xcode 4.5 "Command Line Tool" project?

Having trouble getting unit tests set up for a specific scenario. Here's what I'm trying:
In Xcode 4.5, I created a simple OSX "Command Line Tool" application project (Foundation).
Note that Xcode does not provide the option to add unit tests to a "Command Line Tool" project automatically – so please don't suggest ticking the ticky-box; it ain't there :-/
In my project, I created a trivial example class that I'd like to test; e.g. "Shape".
I followed instructions in Apple's Xcode Unit Testing Guide for Setting Up Unit-Testing in a Project:
I added a unit test target to my project, and
I edited the "Test" scheme to run the tests in the new target.
In the test project's implementation (.m) file, I added an import for Shape.h and code in the setUp() method to instantiate a shape and assign it to an instance variable.
At that point, I decided to see if things would build and if the default test would run still. However, when I selected Product...Test from the menu, the build failed with the following error:
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_Shape", referenced from:
objc-class-ref in ExampleTests.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Interpreting this error is not the issue. I grok that the unit test target isn't being linked to the binary containing Shape's implementation. However, I don't (yet) grok Xcode unit testing & target configuration. So:
What do I need to do in order to get the test target linking against the command line tool's resulting output? Can I link to a command-line executable from the unit test target? Apple's documentation looks specific to regular OSX applications (*.app) and iOS applications, and this is neither.
I have business logic classes that I'd like to develop in a command-line tool setting (to begin with), so I'd like to understand what I need to do to get a unit test target running in a "Command Line Tool" type of project. Thank you!
(p.s. Note that I'm not interested in running my unit tests from the command line – Stack Overflow already suggested "similar" questions on how to do that – but rather running unit tests on a "Command Line Tool" type project, and still from within Xcode.)
I've determined a workaround I find suitable and which doesn't appear to have significant drawbacks, other than an added target.
In a nutshell: the solution involves adding a static library target to take advantage of Xcode's ability to create & run unit test code around such a target. The command line tool target then delegates to the static library, where an alternate main()-like function is defined and called by the real main() entry point. The command line tool is kept free of non-trivial code, so the unit test target can access everything worth testing.
Here are the steps:
From an empty Xcode, from the menu choose File...New Project.
In the resulting dialog, chose OS X...Application...Command Line Tool. For the purpose of this example, I'll assume it is named SampleCmd.
After the basic command line tool project has been created:
From the menu choose File...New...Target.
In the resulting dialog, choose OS X...Framework & Library...Cocoa Library. For the purpose of this example, I'll assume it is named SampleCmdLogic.
Choose type Static, so the command line tool will remain a stand-alone executable.
Make sure the Include Unit Tests box is checked.
After the static library project has been created:
Copy the main() function from main.m to SampleCmdLogic.m, replacing the #implementation block. (This file will hold the main entry point only. Other files can be added for Objective-C classes, etc.) Rename the function to libMain().
In SampleCmdLogic.h, add a declaration for the new libMain(), replacing the #interface block:
int libMain(int argc, const char * argv[]);
In the command line tool's main.m, add an #import "SampleCmdLogic.h" at top.
In the command line tool's main.m, change the entire contents of the real main() function to:
return libMain(argc, argv);
The code is now ready, but there are required linking steps:
In the project settings for SampleCmd, under Build Phases, expand Target Dependencies and add (+) SampleCmdLogic as a dependency.
In the project settings for SampleCmd, under Build Phases, expand Link Binary With Libraries and add (+) libSampleCmdLogic.a
Everything is now ready. When you change to the SampleCmd target and choose Product..Run from the menu, the build should succeed and output generated as expected. When you change to the SampleCmdLogic target and choose Product...Test from the menu, the build should succeed and the unit tests will run. The single issue reported will be the initial default failing unit test assertion inserted by Xcode, in SampleCmdLogicTests.m. This is expected.
From this point on, proceed to add all logic and corresponding tests to the SampleCmdLogic target. The SampleCmd target is to remain trivial and providing the command line tool entry point only.
There are normally a number of additional steps to add a test target to an app project -- in particular, the setting of Bundle Loader and Test Host as I describe in https://stackoverflow.com/a/12624873/246895.
But when I did them with a Command Line Tool and tried running tests, all it did was run the tool. For an app, it goes through a phase of launching the app, injecting the test bundle into the running app, then executing the tests. But these phases don't apply to Command Line Tools.
So instead of an injected test bundle, what you'll need is a second command-line tool that runs your tests. Then set the your classes so they target the test tool as well as your actual tool. gh-unit and google-toolbox-for-mac both follow this model, so I'd try them.
It seems like the most immediate problem is simply that Shape is not included in the new test target. Try adding Shape.m to the test target:
Click on Shape.m in Project Navigator
Open the Utilities view (View -> Utilities -> Show Utilities)
In the Target Membership section of the Utilities view, make sure that both your app and test targets are checked.
I don't know if that's the end of your issues with your setup, but it seems like a likely candidate for your most immediate problem.

Resources