Here is the problem: Sometimes you want to test an element that could be nil. For example, I recently wanted to test if a view controller has a right bar button item with a given target. This could be done like this:

func testViewController_HasAddButtonInNavigationBar() {
  let _ = viewController.view
  
  XCTAssertNotNil(viewController.navigationController)
  XCTAssertNotNil(viewController.navigationItem.rightBarButtonItem)
  let addBarButton = viewController.navigationItem.rightBarButtonItem!
  let target = addBarButton.target
  XCTAssertEqual(target as! TimerTableViewController, viewController, "The view controller should be the target of the right bar button")
}

The problem with this code is, that if there is no right bar button item the test execution crashes. Let’s make it kind of better:

func testViewController_HasAddButtonInNavigationBar() {
  let _ = viewController.view
  
  if let _ = viewController.navigationController {
    XCTAssertNotNil(viewController.navigationItem.rightBarButtonItem)
    if let addBarButton = viewController.navigationItem.rightBarButtonItem {
      let target = addBarButton.target
      XCTAssertEqual(target as! TimerTableViewController, viewController, "The view controller should be the target of the right bar button")
    }
  } else {
    XCTAssertFalse(true)
  }
}

Uhhg… Now it doesn’t crash but it’s really ugly. Here comes the rescue with guard:

func testViewController_HasAddButtonInNavigationBar() {
  let _ = viewController.view
  guard let _ = viewController.navigationController else { XCTFail("There should be a navigation controller"); return }
  guard let addBarButton = viewController.navigationItem.rightBarButtonItem else {
    XCTFail("The navigation bar should have a button on the right")
    return
  }
  guard let target = addBarButton.target else { XCTFail("The bar button should have a target"); return }
  XCTAssertEqual(target as! TimerTableViewController, viewController, "The view controller should be the target of the right bar button")  
}

This is beautiful! Thanks Swift 2.0 and thanks guard! If you enjoyed this post, then make sure you subscribe to my feed.

Update: As suggested in the comments by Stephan Michels I changed XCTAssertFalse() to XCTFail(). Thanks Stephan!

Update 2: David Owens II wrote on Twitter that you can get the same behavior without guard when adding set.continueAfterFailure = false to the setUp(). Thanks David!