Testing is a fundamental part of baking in quality to your codebase. Testing helps quickly check that all the functionality in your app is working and ensures that you are writing better code. Fortunately, with XCTests, writing unit tests for functionality in your app is simple.
Tutorial:
To start with, get yourself a test project. I have provided one that you can download here:
https://github.com/rtking1993/UnitTest-Calculator-Tutorial-Start
This application is a simple calculator app that can perform operations on two numbers. If you build and run it on Xcode you should see it working correctly. However, what we are going to do now is add some unit tests to the operation logic of this app to be absolutely sure that things are running as they should.
The first thing we do is go to File > New > Target. We want to add an iOS Unit Testing Bundle, similar to the image below. This will add a test target to our project and also create some automatic files for us to help get us started.
The last thing we want to do before we start writing our tests is to go into the File Inspector on CalculatorInteractor and ensure that our file is available in both the Main and Test target. Your file should have the two ticks for both targets.
Then we want to create a new file, call it something like CalculatorInteractorTests and place it amongst your new test files. Now we are ready to write some test functions.
Every time the unit tests are run, setup is called to perform any tasks that will prepare the tests. We are going to instantiate our CalculatorInteractor in here.
Our first function is called testAddition(), it is very important that all of your tests start with the word “test”. Otherwise, you will not be able to run them as tests. Inside this function, we are going to instantiate two numbers before calling our calculatorInteractor to perform the addition operation.
This addition operation will return us a result. We know that 9+4 should give us 13. Because we know this, we can write an XCTAssert, which will check our result against this expectation and succeed or fail depending on whether the check matches. This is how we can be sure that our addition calculation is working correctly.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MARK: Frameworks | |
import XCTest | |
// MARK: CalculatorInteractorTests | |
class CalculatorInteractorTests: XCTestCase { | |
// MARK: Variables | |
var calculatorInteractor: CalculatorInteractor! | |
// MARK: Setup Methods | |
override func setUp() { | |
super.setUp() | |
calculatorInteractor = CalculatorInteractor() | |
} | |
// MARK: Addition Tests | |
func testAddition() { | |
let numberOne: Float = 4 | |
let numberTwo: Float = 9 | |
let result = calculatorInteractor.add(numberOne: numberOne, to: numberTwo) | |
XCTAssertEqual(result, 13) | |
} | |
} |
Now we have written our first test function, we want to try and write some more for the rest of our operations. Here is a list of some, but not all of the possible tests that could be created to fully test the CalculatorInteractor.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MARK: Frameworks | |
import XCTest | |
// MARK: CalculatorInteractorTests | |
class CalculatorInteractorTests: XCTestCase { | |
// MARK: Variables | |
var calculatorInteractor: CalculatorInteractor! | |
// MARK: Setup Methods | |
override func setUp() { | |
super.setUp() | |
calculatorInteractor = CalculatorInteractor() | |
} | |
// MARK: Addition Tests | |
func testAddition() { | |
let numberOne: Float = 4 | |
let numberTwo: Float = 9 | |
let result = calculatorInteractor.add(numberOne: numberOne, to: numberTwo) | |
XCTAssertEqual(result, 13) | |
} | |
func testAdditionNegative() { | |
let numberOne: Float = -3 | |
let numberTwo: Float = -6 | |
let result = calculatorInteractor.add(numberOne: numberOne, to: numberTwo) | |
XCTAssertEqual(result, -9) | |
} | |
// MARK: Subtraction Tests | |
func testSubtraction() { | |
let numberOne: Float = 9 | |
let numberTwo: Float = 4 | |
let result = calculatorInteractor.subtract(numberOne: numberOne, from: numberTwo) | |
XCTAssertEqual(result, -5) | |
} | |
func testSubtractionNegative() { | |
let numberOne: Float = -6 | |
let numberTwo: Float = -12 | |
let result = calculatorInteractor.subtract(numberOne: numberOne, from: numberTwo) | |
XCTAssertEqual(result, -6) | |
} | |
// MARK: Multiplication Tests | |
func testMultiplication() { | |
let numberOne: Float = 9 | |
let numberTwo: Float = 4 | |
let result = calculatorInteractor.multiply(numberOne: numberOne, by: numberTwo) | |
XCTAssertEqual(result, 36) | |
} | |
func testMultiplicationNegative() { | |
let numberOne: Float = -2 | |
let numberTwo: Float = -12 | |
let result = calculatorInteractor.multiply(numberOne: numberOne, by: numberTwo) | |
XCTAssertEqual(result, 24) | |
} | |
// MARK: Division Tests | |
func testDivision() { | |
let numberOne: Float = 28 | |
let numberTwo: Float = 2 | |
let result = calculatorInteractor.divide(numberOne: numberOne, by: numberTwo) | |
XCTAssertEqual(result, 14) | |
} | |
func testDivisionNegative() { | |
let numberOne: Float = -9 | |
let numberTwo: Float = -3 | |
let result = calculatorInteractor.divide(numberOne: numberOne, by: numberTwo) | |
XCTAssertEqual(result, 3) | |
} | |
} |
Have a go and see whether you can find all of the test cases. This is a great exercise to help familiarize yourself with unit tests.