I have a project that is mixed Obj-C and Swift and I am having some issues getting my unit tests to work.
I'm using the #testable import moduleName directive to import my files, however it does not appear to be importing all the files. I have full access to pretty much all of my Obj-C models, manager classes etc. but none of the view controllers (95% of which are in Obj-C) are available from within the XCTestCase, along with all of my Swift files.
I have imported #testable import ModuleName at the top of the XCTestCase,
I have also edited the target to enable testability, but the only way I can access these files seems to be if I set the files target membership manually, which if I have understood everything correctly, I should not need to do.
Any suggestions?
Yeah I just also went from the same problem about the Unit testing with the project having both Objective-C & Swift languages.
So basically what i found was
You have to add the respective file and all the required files to Test target. And also required to add them to the Bridging_Header to access those files
Moreover the reason behind using the
#testable
is to test methods internal .... methods.
#testable import moduleName
This is used for the purpose of visibility of methods, i.e like internal methods can now be visible in unitTest but atill private methods won’t.
Related
I'm attempting to write some unit tests. But, somehow, some classes are found and others are not.
Their targets are the same as is seemingly everything else. And yet some classes I can use and others are not found.
I have #testable import MyProject at the top of course.
In my image below you can see what I mean. Of two classes of the same grouping only one is being recognized:
Double-check and ensure that your file has the correct Target Membership
Fixed by adding an import statement for the class to the Swift bridging header.
Currently we have modularized our Swift project, using multiple targets. The targets compile to .framework files that are dependencies of the higher targets. We have a Common module target, a few Product module targets, and the original App target. Common will hold very low level code, shared libs, and any specific code that may be shared by multiple product targets.
So the App will do:
import Common
import Product1
import Product2
And Product1 target code might do:
import Common
Generally the flow is Common -> Product* -> App, where Common will never reference the other direction.
Unfortunately Common has grown large, and has a lot of code that may not be needed for every import.
What I'd like to be able to achieve in Swift, is something like this:
import Common.API
import Common.PurchaseCheckout
I've looked into module-maps, which allow for setting up the import submodules, but it is all focused around objective-c headers, and not Swift. Is there a swift variation?
The specific need is that we want to create a light-weight SDK that only uses some of the features, and as soon as we "import Common", it bloats the SDK, and it adds dependencies on quite a few unrelated cocoa-pods also. We can include files in the SDK target file-by-file, but were hoping modularization would make things simpler.
EDIT
It appears I can use such things as:
import class Common.FileDownloadAPI
import class Common.FileUploadAPI
possibly in my code to create the impression of a partial import. However, modulemaps seem to be a way in objective-c to do this for you, creating the submodule. I do not want to have to write 100 class imports to import half of the 200 files that a submodule might do in one import. So still looking for ideas.
I want to have a way to import my Swift Cocoapods globally in every class, how can I achieve this?
I tried a lot of things and they didn't work. Here are some ways I haven't tried and thought may be possible if found a way to work them:
Have a general import statement like UIKit and put everything in there. (Edit: This failed)
Somehow put Swift frameworks in the Obj-C briding header and import the stuff in there.
You should be able to import it globally by adding #_exported before the import.
#_exported import MyPodModuleName
However, like the other answer mentions, doing that for an entire module is not recommended, because it introduces implicit coupling between modules.
Hence instead try something like:
import Foundation
#_exported import class MyModuleName.MyClassName
#_exported import class MyModuleName.MyOtherClass
It's strongly discouraged in Swift because that would introduce implicit coupling between modules.
However, you can make a certain symbol available globally by declaring a typealias in the module that imports the other module:
import ModuleName
public typealias ClassName = ModuleName.ClassName
As of Swift4:
Being in a Swift project
Want to have another Swift project globally
imported (and using cocoapods)
I just managed to do that by adding the following line to my bridging header:
#import <PodName/PodName-Swift.h>
How good/bad this practise is? Not sure, but I just wanted some extensions globally available in my project. this did the trick.
There is no way to do this. And this is not a bug, this is a language feature (so far, as speaking of Swift 2.2).
Swift uses modules (Apple introduced them in Xcode 5 for Objective-C) and each file is an semantic unit, so you need to explicitly inform Xcode which modules are exposed to defined file.
Not only there is no support for your described behaviour, but you shouldn't also try to bypass it. Using unnecessary (unused) modules could theoretically produce slower code (taking into account that compiler uses this information to its optimisation process).
You can manually achieve the same functionality by:
Creating the Objective-C Bridging Header file;
Adding #import <UIKit/UIKit.h> to the Objective-C Bridging Header file (so that you don't need to repeat this for every single .swift file).
for pods you have to do like #import <SwiftyJSON/SwiftyJSON-umbrella.h>
A reason you wouldn't want to do this:
Imagine if both your frameworks would use the same method name, it would make things ambiguous for the compiler.The compiler won't know which method it should run.
To find out more see this question
To access swift files from objective-c, you need to import the ModuleName-Swift.h header, as described here, where "ModuleName" is the Product Module Name (and typically the project name).
Unless I'm missing something, this isn't very good for code reuse. If I make an obj-c class that uses some swift code, my import for the swift class will include the project name. If I want to reuse that class in another project, I'll have to change that import so it includes the project name for the new project.
So if I want to make my class part of a library that can be used by any project, what am I supposed to do?
I installed Quick and Nimble frameworks for tests in Swift. But inside test class my class' types is unresolved. In the top of test class I make imports:
import UIKit
import Nimble
import Quick
import MyProject
I know my main target should be at target dependencies and no classes files (except test classes) should be added to compile sources of test target.
Why my files is not visible in test target?
In XCode 7, you can include internal ivars with a line:
#testable import
No need to make the ivars public if you want to keep them conceiled from the outside world...
You need to declare your classes as public. Otherwise, you won't see anything from your test bundle
Also, the default access level of every property/ function is just its own target. So you also need to declare them public