Search code examples
iosswiftxctestxctestcase

Is it possible to call a different overloaded function in the same function?


I'm trying to write a simple extension to XCTestCase so that I don't have to unwrap everything when checking true or false. It's like the normal XCTAssertTrue but takes a Bool? instead. (XCTAssertEqual takes optionals, so it's odd this one doesn't)

// Currently have this
XCTAssertTrue(thing?.isValid ?? false)
XCTAssertFalse(thing?.isValid ?? true)

// I want this to work on optionals
XCTAssertTrue(thing?.isValid)
XCTAssertFalse(thing?.isValid)
extension XCTestCase {
    func XCTAssertTrue(_ expression: Bool?, _ message: String = "", file: StaticString = #file, line: UInt = #line) {
        if let unwrapped = expression {
            XCTAssertTrue(unwrapped, message, file: file, line: line)
        }
        XCTFail("It was nil.", file: file, line: line)
    }
    
    func XCTAssertFalse(_ expression: Bool?, _ message: String = "", file: StaticString = #file, line: UInt = #line) {
        if let unwrapped = expression {
            XCTAssertFalse(unwrapped, message, file: file, line: line)
        }
        XCTFail("It was nil.", file: file, line: line)
    }
}

Problem is it calls itself instead of the other XCTAssertTrue, which has different parameters. But why can't it tell the difference?

I can fix it by renaming them to something like XCTAssertOptionalTrue, but I'd like them to have the same name for ease of use. Is this possible?


Solution

  • You can’t write an overload, because this is Objective C under the hood so there are no overloads! Anyway, you're doing way too much work here. The goal apparently is: "Given an Optional Bool, fail if nil, otherwise unwrap and assert true or false". The way to say that is:

    XCTAssertTrue(try XCTUnwrap(thing?.isValid)) // or XCTAssertFalse
    

    Observe that this assumes that your test... function is a throws function. Well, if it isn't, it should be! The ability of a test... function to throw is a very important feature; throwing causes the test to fail instantly, which is just what you want.