Testing Swift code with preconditions
Asked Answered
K

1

12

How do you write tests for Swift methods that have preconditions? Here is an example:

func doublePositive(n:Int) -> Int {
    precondition(n >= 0)
    return 2*n
}

Using XCTAssertThrowsError does not work:

func testDoublePositive() {
    XCTAssertEqual(10, testObject.doublePositive(5))    // Works
    XCTAssertThrowsError(testObject.doublePositive(-1)) // Breaks 
}

This generates an error when running the test:

Thread 1:EXEC_BAD_INSTRUCTION (Code=EXCI386_INVOP, Subcode=0x0)

Is there a way to test preconditions of Swift?

Krahmer answered 18/4, 2016 at 11:46 Comment(5)
there is no standard way to "catch" failure in precondition, it will always stop the program, there are some tweaks though , have a look at cocoawithlove.com/blog/2016/02/02/…Stymie
@Stymie Wow, that's a nice article, thanks!Krahmer
I can't wait to see this in non-test code. I'm glad this allows you to test what you're trying to test, but I hate that website... because I guarantee there's someone implementing this in their main target and orphaning crashed threads just to prevent the app from crashing... (And I say that, because I've seen it happen for their similar Objective-C article...)Peremptory
@Peremptory I wish Apple made it simpler for developers to test preconditions, because they are in the best position to do it. An option to generate exceptions on precondition/assertion failures would do the trick: one would turn it on in debug builds, and turn it off in release builds. Apple could even reject apps compiled with this option turned on if they do not want the catch-all practice to proliferate.Krahmer
I agree. It's important for you to be able to test your code... I just know this stuff gets abused. :(Peremptory
U
8

You test Swift methods that have preconditions by only testing behavior with inputs that meet those preconditions. The behavior when the precondition is not met is clear without further testing, since preconditions are baked into the standard library.

If you doubt you've correctly specified a precondition, you can pull out the precondition expression into a Boolean function, then test that for correctly discerning valid from invalid inputs.

However, you can create for yourself what you wish for here:

An option to generate exceptions on precondition/assertion failures would do the trick: one would turn it on in debug builds, and turn it off in release builds.

Instead of calling Apple's precondition, you can write your own function, say, require. This could be conditionally compiled to act as you wish. You would then use this everywhere you'd otherwise be using precondition.

Udder answered 13/5, 2017 at 22:2 Comment(1)
Well, that will work, except for the preconditionFailure and fatalError which return NeverDervish

© 2022 - 2024 — McMap. All rights reserved.