Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is use of generics valid in XCTestCase subclasses?

I have a XCTestCase subclass that looks something like this. I have removed setup() and tearDown methods for brevity:

class ViewControllerTests <T : UIViewController>: XCTestCase {
    var viewController : T!

    final func loadControllerWithNibName(string:String) {
        viewController  = T(nibName: string, bundle: NSBundle(forClass: ViewControllerTests.self)) 
        if #available(iOS 9.0, *) {
            viewController.loadViewIfNeeded()
        } else {
            viewController.view.alpha = 1
        }
    }
}

And its subclass that looks something like this :

class WelcomeViewControllerTests : ViewControllerTests<WelcomeViewController> {
    override func setUp() {
        super.setUp()
        self.loadControllerWithNibName("welcomeViewController")
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    func testName() {
       let value =  self.viewController.firstNameTextField.text
        if value == "" {
            XCTFail()
        }
    }
}

In theory, this should work as expected -- the compiler doesn't complain about anything. But it's just that when I run the test cases, the setup() method doesn't even get called. But, it says the tests have passed when clearly testName() method should fail.

Is the use of generics a problem? I can easily think of many non-generic approaches, but I would very much want to write my test cases like this. Is the XCTest's interoperability between Objective-C and Swift the issue here?

like image 395
avismara Avatar asked Feb 08 '16 15:02

avismara


2 Answers

XCTestCase uses the Objective-C runtime to load test classes and find test methods, etc.

Swift generic classes are not compatible with Objective-C. See https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-ID53:

When you create a Swift class that descends from an Objective-C class, the class and its members—properties, methods, subscripts, and initializers—that are compatible with Objective-C are automatically available from Objective-C. This excludes Swift-only features, such as those listed here:

  • Generics

...

Ergo your generic XCTestCase subclass can not be used by XCTest.

like image 143
Gwendal Roué Avatar answered Sep 21 '22 03:09

Gwendal Roué


Well, actually its totally doable. You just have to create a class that will be sort of test runner. For example:

class TestRunner: XCTestCase {
    override class func initialize() {
        super.initialize()
        let case = XCTestSuite(forTestCaseClass: ViewControllerTests<WelcomeViewController>.self)
        case.runTest()
    }
}

This way you can run all your generic tests.

like image 40
Paweł Sękara Avatar answered Sep 18 '22 03:09

Paweł Sękara