× {{alert.msg}} Never ask again
Receive New Tutorials
GET IT FREE

Tutorial: Swift Unit Testing with XCTest

– {{showDate(postTime)}}

Josh Brown is the founder of Roadfire Software, an iOS consultancy company that builds apps for other businesses ranging from small startups to Fortune 500 companies such as Salesforce. He has been exclusively developing iOS apps for 4 years now and has plenty experience teaching others how to build apps in his iOS workshops.

This article was originally posted on Roadfire’s blog


If you’ve done unit testing in Objective-C, you’re probably already familiar with XCTest (even if you chose to use a third-party framework instead). What’s nice about it is that when you run your tests in Xcode, you get:

1. pretty red or green icons next to your failing or passing tests, respectively
2. output in the test navigator, again with pretty red or green icons
3. the ability to run a single test case
4. the ability to run all the tests in a class
5. a red line running across the editor when a test fails, showing you which assertion failed (sorta like a build error)

Did you know that you can get all of this by using XCTest with Swift, too? (Yeah, OK, you probably did…) But do you know how to use XCTest with Swift?

Here’s an example from SwiftFonts, an app that lists the fonts in iOS. Now, since iOS gives us the fonts, this is a pretty simple app. There’s only one problem: the fonts need to be ordered properly before we show them to a user! (like this…)

See SwiftFonts on GitHub

So…

I wrote a sort function in the view controller. It was decent, except for the fact that I accidentally wrote it to sort the fonts in each section in reverse alphabetical order (and didn’t even notice it)…

I did realize, however, that the ViewController was absolutely the wrong place to be sorting fonts (in fact, it’s absolutely the wrong place to do lots of things). So I decided to pull the sortFontNames function out into a class of its own. And when I did this, I thought, “hey, I could test that pretty easily now.” So I went ahead and wrote two tests using XCTest. And that’s when I discovered that I was sorting the fonts in a group in reverse alphabetical order (thank goodness for tests!).

Here’s the first test, which ensures that any font names that don’t contain a hyphen come before any font names that do contain a hyphen. (You’ll note that an alphabetical sort doesn’t work in this case – you can try it for yourself if you don’t believe me.)

func testCompareHyphenWithNoHyphen() {
    let fonts = ["Arial-ItalicMT", "ArialMT"]
    let expected = ["ArialMT", "Arial-ItalicMT"]
    let sorted = sorter.sortFontNames(fonts)
    XCTAssertEqual(expected[0], sorted[0], "the array should be sorted properly")
    XCTAssertEqual(expected[1], sorted[1], "the array should be sorted properly")
}

Pretty simple, right? First, we create an unordered array of fonts. Then we set up our expected order. Next we ask our sorter to sort the fonts. And finally, we assert that the expected values are equal to the sorted array’s values from our sorter. And that String in the XCTAssertEqual is the message that’s printed if the test fails.

In the next test, I wanted to make sure that two font names that both contained hyphens were sorted alphabetically. So…

func testCompareHyphenWithHyphen() {
    let fonts = ["Avenir-Roman", "Avenir-Oblique"]
    let expected = ["Avenir-Oblique", "Avenir-Roman"]
    let sorted = sorter.sortFontNames(fonts)
    XCTAssertEqual(expected[0], sorted[0], "when two fonts contain a hyphen, they should be sorted alphabetically")
    XCTAssertEqual(expected[1], sorted[1], "when two fonts contain a hyphen, they should be sorted alphabetically")
    }}

Same idea as before, just with different font names this time. And if you’ve been wondering where that sorter came from, it’s just defined as an instance variable (instance constant?) at the top. Here’s the entire test class:


import XCTest
import SwiftFonts

class FontSorterTests: XCTestCase {

    let sorter =  FontSorter()

     func testCompareHyphenWithNoHyphen() {
        let fonts = ["Arial-ItalicMT", "ArialMT"]
        let expected = ["ArialMT", "Arial-ItalicMT"]
        let sorted = sorter.sortFontNames(fonts)
        XCTAssertEqual(expected[0], sorted[0], "the array should be sorted properly")
        XCTAssertEqual(expected[1], sorted[1], "the array should be sorted properly")
    }

    func testCompareHyphenWithHyphen() {
        let fonts = ["Avenir-Roman", "Avenir-Oblique"]
        let expected = ["Avenir-Oblique", "Avenir-Roman"]
        let sorted = sorter.sortFontNames(fonts)
        XCTAssertEqual(expected[0], sorted[0], "when two fonts contain a hyphen, they should be sorted alphabetically")
        XCTAssertEqual(expected[1], sorted[1], "when two fonts contain a hyphen, they should be sorted alphabetically")
    }
}

All of the code for SwiftFonts is on GitHub (including these tests), in case you want to see the FontSorter or the ViewController. Or the (untouched) AppDelegate. Or the (boring) Info.plist. Or… nah, never mind… Just go check out the FontSorter.


Josh BrownNeed Josh’s help? Book a 1-on-1 session!

View Josh’s Profile

or join us as an expert mentor!



Author
Josh Brown
Josh Brown
4.9
iOS consultant, author, and teacher
I enjoy teaching, training, and mentoring, and have spent the past 5 years entirely focused on iOS. I've done pairing, taught workshops, coauthored a book, and written about iOS on my blog....
Hire the Author

Questions about this tutorial?  Get Live 1:1 help from iOS experts!
Ben Gottlieb
Ben Gottlieb
5.0
Senior iOS Developer
I've been in mobile since Apple's premier handheld was the Newton. I've worked on top grossing iOS apps, and consulted with companies large and...
Hire this Expert
Gbenga Oladipupo
Gbenga Oladipupo
5.0
Senior Mobile Engineer with many years of experience
Senior Mobile Engineer with 9 years of active programming experience. I'm proficient in Kotlin, Dart, Java and Python. I have helped many new...
Hire this Expert