Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot override init() function in Swift XCTestCase

I'd like to override the init function for XCTestCase in UI testing for a few reasons:

  • To launch the app, outside of setUp() so that the app doesn't need to relaunch for every test (this is tedious and slows down tests)
  • To initialize other classes that provide general navigation through the app, which must me initialized with a test case (self).

What I have now looks like this:

import XCTest

class UITest: XCTestCase {

    let app = XCUIApplication()

    // Helper packages
    var helper: UITestHelper!

    override func setUp() {
        super.setUp()

        // Helper package instantiation
        helper = UITestHelper(withTestCase: self, forApp: app)

        continueAfterFailure = false
        app.launch()
    }

... tearDown(), tests ....

When I call:

override init() {
    super.init()
    foo()
}

I get Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

like image 442
Bridge Dudley Avatar asked Jun 08 '18 15:06

Bridge Dudley


1 Answers

init is not the designated initializer of XCTestCase. The designated initializer is initWithInvocation:. This takes an NSInvocation, which is not available in Swift. The only way to do what you're describing is in ObjC.

This isn't documented because it's not supported. It may be possible to achieve what you're describing, but it is likely to break in subtle ways, and you should explore other solutions to your problem.

The crashing is a byproduct of ObjC initialization semantics. Every ObjC class must respond to init (because it's inherited from NSObject). However, there are quite a few ObjC objects that do not initialize properly when init is called. (NSError is somewhat famous for this problem.) The only way to know is by documentation. The much more complex Swift initialization system is an attempt to remedy the problems in the ObjC initialization system.

I would break up your deeper goals into separate questions and ask how to address them (you should also make it very clear that you're talking about UI tests; while your code indicates that, it's not clear from the text). Make sure what you're describing isn't going to break Xcode 10's new parallel testing features, and changes to ordering.

like image 145
Rob Napier Avatar answered Oct 14 '22 18:10

Rob Napier