I'm trying to add Swift unit tests to an all Objective-C based project. If I attempt to test the code the build will fail with the following error:
#testable import Foo // No such module 'Foo'
However, if I add a Swift file to the Foo target, the unit tests will build and run correctly, so it seems Xcode will only generate the Foo module if there is a Swift file in it. How can I force Xcode to create a module when it doesn't include a Swift file? (I'd like to avoid having the unnecessary Swift file if possible.)
It appears that the problem is using the #testable import Foo. Simply removing the line allows the unit tests to build and run.
I have a scenario where I need to use a plugin as well as a static library into my xcode project. The plugin will be dynamically loaded into the system. Now, the static library is also getting used in creation of the plugin.
While executing my project I am getting a warning saying :
Class A is getting referenced from /staticLibraryPath and plugin. One of them will be used.
Please let me know, how to resolve the warning or a better way of implementing the scenario.
The issue is a name class of the two ClassA types found in both plugin and library
I assume you have control over the source of either plugin / library.
.. rename Class A in one instance to make the names not clash -- I don't think there is another way to get rid of the warning/error
I am in the process of adding Swift classes to an existing Objective-C project. As part of this, I have added a MyProjectTests.swift to the target MyProjectTests. It imports Swift classes from target MyProject with import MyProject and that works just fine.
I now want to use #import Swift; in MyProjectTests.mas well. However, the compiler issues the error Module 'MyProject' not found.
I have these questions:
Make both import and #import succeed in test target
Why can it be the case that the Swift compiler sees module MyProject but the Objective-C compiler does not? What build settings in MyProjectTest do I have to change to make #import MyProject succeed as well.
Export Objective-C classes from main target
Ultimately MyProjectTest.swift and MyProjectTest.m also need access to Objective-C classes from target MyProject. So far I have multi-targetted such files, but I want to switch to using modules also here.
My current understanding is that this is a matter of providing a module.map file which would list header files for the classes I wish to "export".
What are the exact steps I have to go through? Where should I place the header file and which build settings do I need to change in the two targets MyProject and MyProjectTests?
I currently have a (so far empty) module.map inside my project and build settings for target MyProject include Defines Module: Yes, Product Module Name: MyProject.
UPDATE I am by now wondering whether it might be impossible to expose (Objective-C) files from an iOS application (instead of framework) project as a module. But then it already seems to work for Swift files (somehow).
I've by now concluded that this is not possible with current Xcode (6.1.1) tooling. (What a waste of time!)
The old scheme of bi-targeting source files to both MyProject and MyProjetTest also presents several challenges for a mixed Objective-C/Swift project with a non-trivial amount of code:
Its Objective-C part defines a legacy NS_ENUM(Integer, Repeat) which name-clashes with Swift.Repeat<T>. Referring to it as MyProject.Repeat (not MyProjectTests.Repeat) causes problems when compiling for target MyProjectTests, which changing this target's Project Name (also) to MyProject (not: MyProjectTests) does not seem to solve.
Compilation of constructs where Swift class A employs Objective-C class B, which in turn employs Swift class C does not seem to be possible in a straightforward way. Since the compiler has not yet produced MyProject-Swift.h with the definition of C, it cannot compile B. But since it cannot compile B it cannot compile A and therefore cannot produce MyProject-Swift.h. Catch 22, or so it seems.
Bi-targeted Swift code imports Swift classes from auto-generated MyProject-Swift.h. For the target MyProjectTests this name does not apply, yet that's what it is in the source files. I did not want to go down the road of changing MyProjectTests' Project Name (see above). Importing the right auto-generated file via the targets *.pch may be possible, but then it may be not ...
Recently I started Unit testing my application. This project (in Xcode4) was created without a unit test bundle so I had to set it up.
I have followed the steps from here: http://cocoawithlove.com/2009/12/sample-mac-application-with-complete.html
And It was working well for simple classes but now I am trying to test a class that depends on another and that on another, etc.
First I got a linker error so I added *.m files to the test case target but now I get a warning for every class I am trying to test:
Class Foo is implemented in both MyApp
and MyAppTestCase. One of the two will
be used. Which one is undefined.
I wonder why is that? How can I solve this? Maybe I missed something when setting the unit test target?
Edit - The Solution
Set "Bundle Loader" correctly to $(BUILT_PRODUCTS_DIR)/AppName.app/AppName
Set "Symbols Hidden by Default" to NO (in Build Settings of the target application). This is where the linker errors come from because it is YES by default!. I've been struggling with this for so long!.
Source: Linking error for unit testing with XCode 4?
Class Foo is implemented in both MyApp and MyAppTestCase. One of the two will be used. Which one is undefined.
I wonder why is that?
because both images (the app and the unit test bundle) define the implementation of the class. the class is dynamically loaded into the objc runtime. the objc runtime uses a flat namespace. how this works:
the binary is loaded, starting with its dependencies
as each binary is loaded, the objc classes register with the objc runtime
if a class with a specific name is loaded twice, the behaviour is undefined. one implementation of a class (with identical names) can be loaded into the objc runtime.
the typical problem here is that you will be returned one implementation - your app will likely crash when the type conflicts (when the class does not come from the same source file).
you typically avoid this by either renaming a class, or export the class in one image. renaming the class obviously does not apply to your case. you have one file Foo.m which is being compiled, exported, and loaded by two images when it should be in one.
this should be interpreted by you as a duplicate symbol linker error. even though the implementation is the same source file (and the implementation is the same) - this a problem that you must fix.
How can I solve this?
if Foo.m is a class of the app, you have to remove (do not compile and link) Foo.m from the unit test. if it's part of the unit test, then do not compile and link it into the unit test target.
then, follow the instructions in the post for linking/loading your unit test to the app. it's in this general area of the post: where "WhereIsMyMac" is the name of the application you're unit testing. This will let the testing target link against the application (so you don't get linker errors when compiling). the important part is that your test files are compiled in the unit test target (only), and your app's classes are compiled and linked into the app. you can't just add them - they link and load dynamically.
Maybe I missed something when setting the unit test target?
From the article you linked:
Note: The testing target is a separate target. This means that you need to be careful of target membership. All application source files should be added to the application target only. Test code files should be added to the testing target only.
the part that you got wrong is probably the link and load phases of the unit test bundle.
If you are using Cocoapods, your podfile only needs the dependencies in the section for the main target, not the test targets. If you do add duplicate dependencies for the test targets, you'll get the OP's error message.
target 'MyProject' do
pod 'Parse'
end
target 'MyProjectTests' do
end
target 'MyProjectUITests' do
end
For me, all I needed to do was uncheck the checkbox that makes the Foo class a member of the unit test target. It should not be a member of both targets, and should look like this:
In case you can't see the image, it's a screenshot of the Xcode "Target Membership" pane. There are two targets: one with an "A" application icon and the test name. The other is the unit test target, and has a unit test icon:
Target Membership
[X] Foo
[ ] FooTests
For me this happened because I deployed to the device and then to the simulator as I have NSZombies enabled. The solution was to switch to the simulator configuration & do a Product -> Clean then switch to the device configuration & do the same. Error went away. It's to do with build cache.
The reason is that you override RUNPATH_SEARCH_PATHS of your App Target`s build setting defined in other target.
Solution:
Go to your App Target and find RUNPATH_SEARCH_PATHS build setting and use there $(inherited) flag for both: Debug and Release
Come across the same issues, My situation is Class NSNotification is implemented in both /System/Library/Frameworks/Foundation.framework/Foundation, is there any dude come across the same issue, any direction or advise will be appriciated.
I'm trying to unit test C functions with the SenTestingKit framework. I declares functions in a header file and defines implementations in a corresponding C file. And I imports the header file in the unit test class. But when I build the test cases, the build result says the functions 'symbol(s) not found'.
Is there anything I should do to make it work?
Is it the right way to unit test C functions?
You need to add the implementation file to the Unit Test target so it gets compiled in. Importing the header is not enough.