Xcode : One test target for multiple app targets - ios

I am wondering if you can link one Unit Testing bundle to multiple targets. So one can test all the application targets with one Testing bundle.
I have some shared code between all app targets but also some specific calculations based upon which app target is running.
Currently I have to set the Bundle Loader option in the Build Settings to the used application target's .app file if I want to test a different application target.
My question to you all is : can this be done without creating multiple test bundle targets for every app target, and without always changing the Bundle Loader option?

You need to:
Select the target you want to test
Go to Test navigation tab
Right-click on test target you want to enable
Click on Enable [name_of_your_target]

No, at this point you can't. It's like the extensions, you have to create a new one for each project's targets you have.
It's not pretty usefull but if the code differes from one to another target, the tests can fail because of missing code, not failing code.
It's why it's not allowed.
Sorry for the negative answer.

Related

What targets should I be adding my files to in my xcode project

I'm working on an xcode app using swift and xcode 8.1.
I keep adding files such as pictures and .plist files to my main folder with my storyboard, but each time it asks what targets I want to add it to. Should I be adding it to my test targets as well? If so, why? Whats the rule to know what targets to add it to.
No, you shouldn't add your files to the test target. Unit test target has access to your application files anyway.
According to the Apple documentation, target is a single build artifact. Because of that, you should only add the files which are building blocks of a specific target.
A target specifies a product to build and contains the instructions for building the product from a set of files in a project or workspace. A target defines a single product; it organizes the inputs into the build system—the source files and instructions for processing those source files—required to build that product. Projects can contain one or more targets, each of which produces one product.
For the most basic scenario with one application target and two test targets the general rule is as follows
Add application classes to the application target.
Add unit test case classes to the unit tests target.
Add UI test classes to the ui tests target.
In more complex scenarios you can have more targets in your application. You can have iMessage extension, share extension etc. You can also have multiple targets for building variants of the same applications but the general rule stays the same.

Cannot load underlying module for 'XCTest'

Every time I start to run my app, or I'm just starting Xcode I get this error:
I think the problem is that I don't know where my .xctest files are. I think I maybe deleted them.
Would be very nice if someone of you could help me! Maybe tell me how to recover these files, make some new one or something else.
You accidentally added one of your Xcode Unit Test files to your main app target.
Remove it:
Select test file
Open right side panel
Select Identity and Type tab
Unselect your app Target (not the unit test lego icon)
Tip:
Next time you add a new unit test, only add it to your unit test target. If you accidentally include any of your app targets, they will not have the XCTest framework available.
See also Apple Technical Q&A QA1954 'Cannot load underlying module for XCTest' which covers several variants of the issue
https://developer.apple.com/library/archive/qa/qa1954/_index.html
The main project does not link with the XCUnit framework. You should create a separate testing target for your project, if one does not already exist, and add your test source files to that target.
Select your project in the Project Navigator. This will open the project's settings in the editor.
Click the "+" button at the bottom of the column listing your Targets.
If you are working on an iOS project template, select iOS > Test > iOS Unit Testing Bundle.
If you are working on an OS X project template, select OS X > Test > OS X Unit Testing Bundle.

Adding test target to an existing project is not working

I need to add test cases to an existing project, so I tried adding a new test target via
File -> New -> Target -> Cocoa Touch Testing Bundle
From the test navigator filter bar.
Even after adding, the target is not getting listed in the test filter bar.
May be because of this issue, Product -> Test option is diabled in my project.
Also I could see some differnce between the build setting in my project and another sample project I started in Xcode 6.1 in which Product -> Test option is enabled and everything working fine for Test cases.
Please find the build settings screen shots.
Any help is appreciated.
I had this exact problem. It turns out my existing project was creating my Cocoa Touch Testing Bundle with the .app extension when it should've been a .xctest extension.
You can fix this by going to your test target you created. Build Settings > Wrapper Extension and changing it from app to xctest.
You may have to restart Xcode after this change to select your test target.
UPDATE: I found out the reason the Testing Bundle was becoming a .app extension in the first place. I had to go to the main project Wrapper Extension and make sure it was blank instead of .app. Apparently that was forcing all targets to become .app extension as well.

How to unit test an app extension on Xcode 6

Does anyone know how to perform unit testing on app extension target, especially keyboard extension target?
What have I tried (in the unit test target):
In the "General" tap, set it's target to the extension target instead of the container app.
Set the "Bundle Loader" to the path of the binary of the extension target, which looks like $(BUILT_PRODUCTS_DIR)/com.mycompany.keyboard.appex/com.mycompany.keyboard
Set the "Test Host" to $(BUNDLE_LOADER).
In the "Build Phases" tap, set the "Target Dependencies" to both the container app and the extension.
After these things done, I can build it successfully but always get "Test Failed" with an log Test target SogouInputTests encountered an error (Test session exited(1). without checking in. If you believe this error represents a bug, please attach the log file at /tmp/TestStatus-UXfvxw.log).
I'm using Xcode 6 beta 3.
I have reported the bug to Apple. And sadly, the answer is that the keyboard extension is not support unit test now. The answer comes from Apple:
It's not currently supported to run unit tests inside an app extension
Instead, factor the code you want to test into a framework and test the code there
Link the framework into your extension
Just ran into similar issues trying to unit test an extension. Independently did exactly the same thing the author tried with Bundle Loader pointing to .appx path with no success of course.
I really did not like the idea of creating a separate framework just for testing so I ended up of adding testable source into the extension test target. It is really simple if you don't have too many source files in your extension:
Select you extension test target in Project settings
Go to Build Phases
Expand Compile Sources
Click +
Add source files with your testable code.
Build for Testing
Why it works:
Once you add extension sources into your extension test target, XCode is going to double reference each of them and compile in both the normal extension build and the test build thus eliminating linking issues.
Are there any drawbacks?
You will have to manually synchronize the source file list in the extension test target. Whenever you add/remove files in the extension target, you may need to do the same in its test target.
What I did which was easier than the other suggestions (no framework creation, no weird settings on build settings, phases, etc) was adding the file that I wanted to test (from the extension target) into the Target Membership of the test target:
The only "drawback" would be that your test target will also include files from your extension (rather than using #testable import like with the main app), but since you are not shipping your test target I would say there is no drawback :)
Tested on Xcode 10.
Note: Only works with Swift code, with ObjC due the BridgingHeader is not possible to follow this approach.

Xcode: What is a target and scheme in plain language?

Yeah the title says it :-) What do they mean in plain English language? I really don't understand the explanation on Apple's website and I need to rename my target and I'm afraid that nothing works after that..
I've added in Workspace and Project too!
Workspace - Contains one or more projects. These projects usually relate to one another
Project - Contains code and resources, etc. (You'll be used to these!)
Target - Each project has one or more targets.
Each target defines a list of build settings for that project
Each target also defines a list of classes, resources, custom scripts etc to include/ use when building.
Targets are usually used for different distributions of the same project.
For example, my project has two targets, a "normal" build and an "office" build that has extra testing features and may contain several background music tracks and a button to change the track (as it currently does).
You'll be used to adding classes and resources to your default target as you add them.
You can pick and choose which classes / resources are added to which target.
In my example, I have a "DebugHandler" class that is added to my office build
If you add tests, this also adds a new target.
Scheme - A scheme defines what happens when you press "Build", "Test", "Profile", etc.
Usually, each target has at least one scheme
You can autocreate schemes for your targets by going to Scheme > Manage Schemes and pressing "Autocreate Schemes Now"
A target is an end product created by running "build" in Xcode. It might be an app, or a framework, or static library, or a unit test bundle. Whatever it is, it generally corresponds to a single item in the "built products" folder.
A scheme represents a collection of targets that you work with together. It defines which targets are used when you choose various actions in Xcode (Run, Test, Profile, etc.) Often, you will have just one scheme, which uses the main app target for the Run, Archive, and Profile actions, and a unit test target for the Test action. If you were building two related apps, you might have two schemes that used the same unit test bundle but different app targets.
The main benefit of schemes (introduced in Xcode 4) is that they allow you to switch between running your app and your unit tests without needing to toggle the selected target.
I am a visual person, hence to explain the concept I will be using a diagram.
When you have multiple targets they can be one-to-one matched with Xcode's Run,Test,Profile actions, this concept defines a scheme
A target is a version of your Project,i.e targets differ slightly in classes & resources to use during built time. A project can have multiple built time setting for separate distribution requirements.
Xcode structure
Workspace
-> Project
-> Target
-> Dependency
-> Scheme
-> Action
-> Build Configuration
-> Build Configuration File(.xcconfig)
Workspace (.xcworkspace) - is a container of multiple projects. It was created as a next step of cross-project references[About]
Workspace contains all schemes from included projects
Workspace handles all implicit dependencies[About]
Observations:
It is safe to work with different projects inside the same workspace and do not catch
//if you try to open two projects on two Xcode instances
Couldn't load Project.xcodeproj because it is already opened from another project or workspace
Cocoapods[About] working with workspace where creates Pods project
Project (.xcodeproj) - It is a container for targets and scheme. It defines code files, resources...
Also Projects manages Build Configuration(changed by scheme) and Build Configuration File[About]
You can convert existing Project into Workspace
File -> Save As Workspace...
[Workspace vs Project]
Target - PBXNativeTarget section. Defines a specific set of build settings that generate:
Application target
Library and framework targets
Test
Aggregate[About]. E.g. it is used to create a Universal framework or Umbrella framework
Scheme
Contains action(run, test, profile, analyze, archive) + configuration(additional arguments, [Build Configuration], diagnostic)
Scheme can be shared which helps you in CI, Carthage[Example]... and located:
<project_path>/<project_name>.xcodeproj/xcshareddata/xcschemes
Dependency - Targets can have dependencies. Dependency is a source link against. These dependencies can be linked statically or dynamically[About] There are two types of them:
Explicit Dependency[About] - Source code of the dependency that is located in the same project or nested project
Implicit Dependency[About] - Source/closed code of the dependency that is located in the project that is a part of the same workspace.
[Vocabulary]
tldr; Targets contain instructions to build a module/framework/library or an App/end Product e.g. instructions to build a watchOS app and an iOS App. Schemes know how to respond to certain actions e.g. a build action or test action or archive action.
Make sure you See WWDC16 video — Introduction to Xcode [45:13]. If you wanted to gain deeper knowledge then watch the entirety of the video. The video is simple to follow yet very foundational. My answer is mostly off of that.
Scheme
A scheme is how you specify what you want to run and it also contains
information about how you want to run it.
For example, I could have a project with an iOS app and a Watch app,
and in that case, I would have one scheme to run my iOS app and one
scheme to run my Watch app
Run will run my app in the debugger.
Test will run my tests.
Profile will run my app in instruments so I can measure its
performance.
Analyze will run Xcode's static analyzer and help catch problems I
might otherwise have missed.
And finally, the Archive action will build my app for release and put
it in the archive that I can then use to distribute to my testers or
to the App Store or to save for future crash log de-symbolication, or
symbolication.
Project
A project is a document that you use to organize your code an
resources in Xcode.
You have references to source code files and resource files on disc,
targets which actually build those files into products like your app,
Build settings which configure how your targets build their products,
and schemes which configure how you perform actions, such as Run, with
your targets.
Now, to access your project settings, you select your project in the
navigator, you select the popover at the top of the editor, and select
your project there.
Target
You have references to source code files and resource files on disc,
targets which actually build those files into products like your app,
Build settings which configure how your targets build their products,
and schemes which configure how you perform actions, such as Run [test, build], with
your targets.
A target contains the instructions to build one thing like an app or a
framework.
The thing that your target produces is called its product. The set of
steps that your target takes to build its product are called build
phases.
And lastly, a target has Build settings to configure how it builds its
product.
Now, one thing to note is that both projects and targets have Build
settings, and targets inherit the value set at the project level but
can override them with a target-specific value.
A target's build phases do things like cause dependencies to build
first, compile the source files in that target, and link the target
against libraries and frameworks.
To summarize:
Targets
Helps put a set of files together to build/run a product/module/package
Usually it ends up just being a product you ship to app store.
But often it can be a module that you just run unit-tests against it.
Like a single app can have an iOS target along with a watchOS target. Or just a single iOS Target. Or a single iOS target along with a test target, etc.
If you go to your target's Build Phase >> Compile Sources you'll see every file that's being built for that target. Example:
To explicitly quote Apple docs:
A target specifies a product to build and contains the instructions for building the product from a set of files in a project or workspace. A target defines a single product; it organizes the inputs into the build system—the source files and instructions for processing those source files—required to build that product. Projects can contain one or more targets, each of which produces one product.
The instructions for building a product take the form of build settings and build phases, which you can examine and edit in the Xcode project editor. A target inherits the project build settings, but you can override any of the project settings by specifying different settings at the target level. There can be only one active target at a time; the Xcode scheme specifies the active target.
A target and the product it creates can be related to another target. If a target requires the output of another target in order to build, the first target is said to depend upon the second. If both targets are in the same workspace, Xcode can discover the dependency, in which case it builds the products in the required order. Such a relationship is referred to as an implicit dependency. You can also specify explicit target dependencies in your build settings, and you can specify that two targets that Xcode might expect to have an implicit dependency are actually not dependent. For example, you might build both a library and an application that links against that library in the same workspace. Xcode can discover this relationship and automatically build the library first. However, if you actually want to link against a version of the library other than the one built in the workspace, you can create an explicit dependency in your build settings, which overrides this implicit dependency.
Schemes
A given target can be put through different actions.
build
run
test
profile
archive
You can have a scheme that has all the diagnostics enabled (which makes debugging slow) vs. a scheme that doesn't have any. Or a scheme that runs certain performance related tests vs. a scheme that runs both unit-tests and performance tests. You can edit a scheme so that it performs such actions as:
Building multiple targets
Executing scripts before or after any action
Sending emails before or after any action
Running with memory management diagnostics
Producing either a debug or release build for any action.
For more on that see Customizing the build schemes for a project
To put it all together:
Once you hit run, Xcode will look at the selected scheme. It will find its associated target(s). Use the Build Phases of that target and its Build Settings (any Project Settings that isn't overridden by the target settings will get included) to build a product into the selected destination (the destination can be an iPhone simulator or a physical iPhone or watchOS, etc).
AGAIN WATCH THE WWDC VIDEO!
My take:
Target -- a lower abstraction -- various kinds of builds. Each target has its own Build Settings (so if you split into several targets, take care of that huge sheet individually for each target). Targets have a convenient way of including/excluding files, so you can configure the build effectively on a per-file basis.
Scheme -- a higher abstraction -- guides a target through various ways of deployment (Run, Test, Archive). Has modest ways of configuring the build through Environment Parameters, but employs the Build Settings from the target. Creating / editing / deleting schemes is cheaper and easier than targets.
You can have several schemes guiding one target in several different ways.

Resources