Using Guard in Unit Tests

I have just discovered how cool the new guard statement is to keep unit tests lean and shallow – avoiding if-let nesting, that is.

Consider this test case:

func testAssigningGroup_AddsInverseRelation() {
    insertFile() // Create new entities into the temporary context
    let file = soleFile()    // -> File?
    let group = soleGroup()  // -> Group?
    file?.group = group
    if let files = group?.files {
        XCTAssertEqual(files.count, 1)
        XCTAssert(files.anyObject() === file)

There are two optionals I have to deal with. That’s why I throw in assertions to cover problems. I don’t want to assert anything new here, though: the test helper soleFile() is valdiated in another test case already. But I need some kind of failure in case the Core Data test case goes nuts.

Consider this Swift 2 version of the test case:

func testAssigningGroup_AddsInverseRelation() {
    guard let file = soleFile() else {
        XCTFail("no file")
    guard let group = soleGroup() else {
        XCTFail("no group")
    // Precondition
    XCTAssertEqual(group.files.count, 0) = group
    // Postcondition
    XCTAssertEqual(group.files.count, 1)
    XCTAssert(group.files.anyObject() === file)

The guard-let pattern propagates the constant to the outer scope, as opposed to if-let. It’s a great way to stay “shallow”.

I also noticed that I missed to test preconditions. The shallow Swift 2 version revealed this: the test wasn’t symmetric. There simply was nothing after the guard clause to verify or enforce an expected preconditional state.

Unwrapping optionals makes assertions easier. And failing to unwrap the optional will now produce a test failure among preconditions. I like that.

Browse the blog archive