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

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

Related

Xcode 8 Ambiguous expansion of macro NSLocalizedString

I have the following in my unit test .pch file to allow my unit tests to find the right bundle for the localization files and this was working fine until I upgraded to Xcode8.
#undef NSLocalizedString
#define NSLocalizedString(key, comment) [[NSBundle bundleWithIdentifier:#"Tests-Unit"] localizedStringForKey:(key) value:#"" table:nil]
Now, I get the warning
Ambiguous expansion of macro NSLocalizedString
Which would explain why my unit tests fail as they can't find the localized string value anymore.
Any ideas what is wrong there? Is there something I need to now do differently?
EDIT:
I have a feeling it has something to do with all my source file being in 2 targets i.e one for the project and one for the unit tests which is the way we had it setup. I'm trying to clean this up and removed all my source file from the unit test target and added the
#testable import ProjectName
instead to a Unit test file to be able to access my code for testing but i'm now getting
File 'MyFile.swift' is part of module 'ProjectName'; ignoring import.
I eventually got it all working again.
Let’s pretend our project is called Panda and it consists of both Obj-C and Swift files. All of those files are in both our Panda and PandaTests target.
STEP 1: Ensure all your files have the right Target Membership i.e. Panda target: Only the source files, development frameworks, images etc and PandaTests target: Only the test files, testing frameworks, mock data etc
STEP 2: Ensure your Panda Project has the Build Settings -> Enable Testability set to Yes.
STEP 3: Ensure your PandaTests Project has the Build Settings -> Product Module Name set to PandaTests.
STEP 4:
Do a nice clean by holding down the Option button and then clicking on Product. You should see a Clean Build Folder option.
STEP 5:
For Swift Unit Tests, add #testable import Panda. Since we have now removed all our source code files from the PandaTests target, the unit tests need a way of accessing our project files. This enables our Swift unit tests to access all our Swift files and those Obj-C files that have been included in our Panda-Bridging-Header.h.
In your project Build Settings add -Wno-ambiguous-macro to Other C Flags
It solves the issue (warning is gone), but not sure what are the side effects.

Can't access app code from XCTest

I have a growing swift project that I have been writing both unit and UI tests for along the way. My UI tests run just fine, but my unit tests have stopped compiling. I am using "#testable import X", but anytime I try to access a class from the project, even if I make that class public, I get a "Use of unresolved identifier" error. I have no idea what I could have changed to cause things to start failing.
Choose "Clean" from the Xcode "Product" menu and then recompile. That will often get it working again. For some reason, we have to "Clean" before the classes are made available to the test target.
My original answer below outlines the old solution before #testable was available to us.
--
Make sure the source file for PostCell is included in the list of source files for the tests target.
You can do this by going to the tests target and adding it to the list of "Compile Sources":
Or by clicking on "Target Membership" to the "File Inspector" for the source in question:

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.

Import XCTest in to existing project

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.

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