One of the announcements that excited me most during last year's WWDC was Xcode's built-in support for code coverage. As of Xcode 7, you no longer have to jump through a bunch of hoops to find out how well your test suite has covered your code.

Code coverage is not enabled by default, though. In this tutorial, I show you how easy it is to enable code coverage for a project in Xcode and I also highlight a few benefits of having code coverage enabled.

Project Setup

Fire up Xcode 7, create a new project based on the Single View Application template, and name it Covered. Set Language to Swift and check Include Unit Tests at the bottom to have Xcode generate a test target for us.

Project Setup

Project Setup

Writing Unit Tests

Create a new Swift file by choosing the Swift File template from the iOS > Source section and name it Person.

Create a New Swift File

Open Person.swift and declare the following structure.

struct Person {

    let first: String
    let last: String

    var fullName: String {
        return "\(first) \(last)"
    }

}

Writing unit tests for Person shouldn't be too difficult. Right? Create a new file by choosing the Unit Test Case Class template from the iOS > Source section and name the file PersonTests. Set Subclass of to XCTestCase and Language to Swift.

Create a New Unit Test Case Class

Create a New Unit Test Case Class

Make sure to add the unit test case class to the CoveredTests target.

Add Unit Test Case Class to CoveredTests Target

Testing the Person structure is pretty easy.

import XCTest
@testable import Covered

class PersonTests: XCTestCase {

    override func setUp() {
        super.setUp()
    }

    override func tearDown() {
        super.tearDown()
    }

    func testInitialization() {
        let person = Person(first: "Bart", last: "Jacobs")

        XCTAssertNotNil(person)
        XCTAssertEqual(person.first, "Bart")
        XCTAssertEqual(person.last, "Jacobs")
    }

    func testFullName() {
        let person = Person(first: "Bart", last: "Jacobs")

        XCTAssertEqual(person.fullName, "Bart Jacobs")
    }

}

Select the Covered scheme and choose an iPhone simulator from the list of simulators. Select Test from Xcode's Product menu or hit Command + U. Open the Test Navigator on the left to make sure every test passed.

Inspecting the Results in the Test Navigator

Enabling Code Coverage in Xcode

Code coverage is enabled in the scheme editor. Click the Covered scheme and choose Edit Scheme.... Select Test on the left and check the checkbox Gather coverage data. That is it.

Enable Code Coverage

Enable Code Coverage

To collect code coverage data, run the test suite one more time. To see the code coverage report, open the Report Navigator on the left, select the report for the last test run, and open the Coverage tab at the top.

Code Coverage Report

You can see that Person.swift is completely covered by the unit tests we wrote. What I like most about Xcode's code coverage is the integration in the source editor. Open Person.swift and add another computed property as shown below.

var fullNameLastFirst: String {
    return "\(last) \(first)"
}

Run the test suite again and revisit Person.swift. On the right of the source editor, you see a gutter that indicates how many times the unit tests entered a particular code path. Colors indicate which code paths have not been entered, giving you a clear hint where the test suite is lacking coverage.

Code Coverage in Source Editor

Be Careful

Xcode's code coverage tracks which code paths are executed by the test suite and which are not. This can result in false positives. If you inspect the code coverage report, you notice that it says ViewController.swift and AppDelegate.swift are also partially covered by the test suite. But we didn't write any unit tests for these classes.

To run the test suite, Xcode creates an instance of the application, which means an instance of the AppDelegate class is initialized. The same goes for the class of the initial view controller of the storyboard, ViewController. That is why the code coverage report indicates that AppDelegate.swift and ViewController.swift are partially covered by the test suite.

What's Next?

Code coverage is a fantastic addition to Xcode. I really like the fact developers no longer have to use third party solutions and the integration in the source editor is the cherry on the cake.

Questions? Leave them in the comments below or reach out to me on Twitter. You can download the source files of the tutorial from GitHub.