Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XCTest'ing a tuple

I am trying to build a unit test like so:

// region is a (Double, Double) tuple
XCTAssertEqual(region, (0.0, 200.0))

But Xcode is giving me an error: Cannot invoke 'XCTAssertEqual' with an argument list of type ((Double, Double), (Double, Double))

Is there a different way to test tuples without extracting their members and testing individually?

like image 259
GW.Rodriguez Avatar asked Jul 04 '16 01:07

GW.Rodriguez


2 Answers

XCTAssertEqual requires that the two parameters passed to it are Equatable, which you can see from the method signature. Note that expression1 returns T?, and T must be Equatable:

func XCTAssertEqual<T : Equatable>(_ expression1: @autoclosure () throws -> T?, _ expression2: @autoclosure () throws -> T?, _ message: @autoclosure () -> String = default, file: StaticString = #file, line: UInt = #line)

But Swift tuples aren't Equatable, so you can't use them with XCTAssertEqual.

Tuples do have an == method — they just don't conform to the protocol — so you could do something like this:

let eql = region == (0.0, 200.0)
XCTAssertTrue(eql)

Or even:

XCTAssertTrue(region == (0.0, 200.0))
like image 86
Aaron Brager Avatar answered Oct 23 '22 16:10

Aaron Brager


Edit: I've expanded on this answer in a blog post, How to Make Specialized Test Assertions in Swift

A disadvantage of using

XCTAssertTrue(region == (0.0, 200.0))

is the inadequate reporting it gives upon failure:

XCTAssertTrue failed -

Now you have to track down what the actual values are, to understand what went wrong.

But you can add diagnostic information to the assertion like this:

XCTAssertTrue(region == (0.0, 200.0), "was \(region)")

For example:

XCTAssertTrue failed - was (1.0, 2.0)

If you plan to have several tests that compare this tuple, I wouldn't want to have to repeat this everywhere. Instead, create a custom assertion:

private func assertRegionsEqual(actual: (_: Double, _: Double), expected: (_: Double, _: Double), file: StaticString = #file, line: UInt = #line) {
    if actual != expected {
        XCTFail("Expected \(expected) but was \(actual)", file: file, line: line)
    }
}

Now the test assertion is

assertRegionsEqual(actual: region, expected: (0.0, 200.0))

Upon failure, this yields a message like

failed - Expected (0.0, 200.0) but was (1.0, 2.0)

like image 23
Jon Reid Avatar answered Oct 23 '22 15:10

Jon Reid