Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing Swift 2.0, @testable import, and scheme targeting issues

I have recently converted my app, and unit tests over to Swift 2.0. I am using @testable import AppName in my Tests.swift files.

Due to an issue with not being able to execute subclasses in multiple targets (see here for the issue), my class EntityName can only be of Target Membership AppName, and NOT AppNameTests.

The problem is, once I switch over to the AppNameTests schema to run unit tests, code in the module AppName can't find the class EntityName and I get

Use of undeclared type 'EntityName'

How do I get AppName to compile when running tests from the AppNameTests scheme without that entity class not a member of the scheme?

like image 997
tyler Avatar asked Aug 28 '15 14:08

tyler


2 Answers

Due to an issue with not being able to execute subclasses in multiple targets

When compiling the same Swift code as part of different targets, the compiler actually generates different classes. So this behaves as designed, but is almost certainly not what you want when running an app's unit tests.

There are two ways I'd recommend you set up your models to allow testing:

1. Public models (recommended)

In your app target:

import RealmSwift
public class MyModel: Object {}

This code should only be compiled as part of your application target, and your unit tests can be set up in the following way:

import MyApp
// should be able to access `MyModel`

Easy enough?

2. @Testable (Swift 2 only)

This approach relies on the @testable keyword introduced in Swift 2.

In your app target:

import RealmSwift
internal class MyModel: Object {} // ACL cannot be `private`

Again, this code should only be compiled as part of your application target, and your unit tests can be set up in the following way:

@testable import MyApp
// should be able to access `MyModel`

Make sure MyApp's build settings have Enable Testability set to YES.

This approach may be preferred to public models if you're building a framework where some internal models shouldn't be accessible from users of that framework.

Realm has a dedicated section of their documentation detailing these common approaches to testing which you can read here: https://realm.io/docs/swift/latest/#avoid-linking-realm-and-tested-code-in-test-targets

like image 169
jpsim Avatar answered Nov 20 '22 15:11

jpsim


I had to stop targeting my entire apps .swift files to be have membership of MyAppTests, and rely solely on @testable import MyApp

like image 35
tyler Avatar answered Nov 20 '22 16:11

tyler