Unit Tests and Test Driven Development (Xcode 8 and Swift 3)
When you use unit tests you are using code to test your project rather than running the simulator and navigating through the app. Testing is not a necessary practice when developing — but if you have good tests set up it makes building and refactoring your code much safer.
The way that we can test code using code is by comparing a functions result to an expected result. So if we have a function that returns the sum of two integers we can give it parameters that have an expected result. Since we know 2 + 3 = 5… if the function returns 5 the test will pass, otherwise the test will fail and we know we will need to fix our function.
Many developers practice test driven development (TDD). TDD involves writing test code before writing the production code associated with that test. In this post I’ll build a simple project that uses Unit Tests and TDD.
Setting Up Your Project
To use Unit Tests in your project there needs to be a separate target set up from the main project. You can do this by checking off the “Use Unit Testing” box when you are creating a new project.
If you have already created your project you can create the new target by selecting your project in the Project Navigator, selecting the “+” button under “Targets”, and choosing “iOS Unit Testing Bundle”
In both cases Xcode creates a new directory, default Info.plist, and .swift file. The .swift file includes some examples of functions that can be used in XCTest framework, but we will make our own file from scratch.
Setting Up Testing .swift Files
To keep things organized I’ll create a tests.swift file for each .swift file in my project. To demonstrate this I’ll create two new .swift files in my project followed by corresponding tests.swift files.
Since we are practicing TDD here lets start by creating some tests for the code that will go in the Math.swift file. I’ll jump into my MathTests.swift file and set up the file for testing.
When you set up the tests.swift file you will want to import the XCTest framework and your project with @testable included. This allows the Unit Tests to look through your project for any classes that are defined in the test.
Next we define the class as a child of XCTestCase. I’ve also included an initial variable and two functions. The “setUp” function gets called before every test method in the class and the “tearDown” gets called at the end of every test method. You can do some customization if needed here — but we wont need them for our example.
Now in true TDD fashion I have written part of the implementation of the test before writing production code. Since my Math.swift file doesn’t have any code the tests can’t find it. So lets head to the Math.swift file and declare the class to fix the issue.
After a quick build the error is fixed! Remember since we imported our project we can declare variables using classes in the project.
Writing Tests for Math
We want a function that takes in 3 integers which gets the sum of the first two and multiplies it by the third. Since we are practicing TDD, lets write the test first.
This is the basic structure of a test function:
In order for the function to get called when you run the test the name must always start with “test”. Here the function is named “testAddAndMultiply” because I intend to make a function in my Math class called “addAndMultiply”.
Next we see “XCTAssert” which is actually a function. If the value of the expression is true the test will pass (false = fail). Lets complete the test using some numbers that we would expect to work in our “addAndMultiply” function.
Since we are writing the test before production code we get an error saying the method addAndMultiply doesn’t exist. So lets go define it in our Math class! I’ll intentionally write this method so that it will fail the test.
Now that the function has been implemented in production code we can run the test using command+U. Remember we are expecting this to fail because we used division instead of multiplication to find the product.
The test shows a white “x” in a red diamond when the test fails. We can add a second parameter in the XCTAssert function to help the test be more descriptive when showing errors.
So the test is telling us we should be getting 36 but the function is returning 1. Now that we have some insight as to what is going wrong I can go fix the addAndMultiply function and run the test again.
Now the test passes and shows a little white check mark in a green diamond!
XCTAssert has many other variations of the function that night make testing a bit easier. It all boils down to a bool… but you can certainly use some of the other options if you prefer.
Ill implement another test in the for the Action class and try using a different XCTAssert function. Feel free to check out the project on my GitHub!
Thanks for reading :)