Unit Testing in Xcode
Opened this issue ยท 4 comments
Testing is Key
So far I've not been able to spend time on researching or implementing tests. There are two types of testing that are possible on iOS.
- Unit Tests
- UI Tests
In this issue, my focus will be to figure out How one goes about writing unit tests in XCode
I'm starting by looking at the following Video and blogs on Ray Wenderlich
- https://www.youtube.com/watch?v=-VdQfX6q_a8
- https://www.raywenderlich.com/141405/uni-testing-macos-part-12
I'd like to spend ~a day and a half trying to get a reasonable idea about unit testing and I am hoping to write a short walkthrough on how one would unit test for swift 3.1
WIP
What is Unit Testing
Practice that involves testing function/methods of our code that let us verify if the functions work as expected.
func add(x: Int, y: Int) -> Int {
var total = x + y
return total
}
We have created a very simple function which returns the sum of two values. A Unit test would test this function add
and see if it returns what we expected.
add(x:1, y:2)
should return 3
So how do we go about testing in Swift using XCode?
When creating a new project make sure you've selected the Unit Test
checkbox when creating your XCode project.
All this will do is create the appropriate folder and a couple of demo files inside the project as seen in the screenshot below
We won't be spending any time with the existing file that has been created, so let's get started and create a new file with the Unit Test Case Class
Found in iOS Templates
You can call this file testingAddition for now, but usually, it's good practice to keep the naming convention similar to the files you will be testing from your real project.
As an example, if you had a view controller called ReturnAddedValuesViewController.swift
you'd want to name your test file ReturnAddedValuesViewControllerTest.swift
You'll get the following in your newly created file.
import XCTest
class testingAddFunc: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}
Each Test file contains a:
- a setUp function which runs before every test.
- a tearDown function that runs after every test.
- a testExample function which we can use as a template for all of our unit tests
- a testPerformanceExample function which we can use for testing performance of our functions
If we delete the example functions testExample
and testPerformanceExample
and then add a test for our add functions
func testAddFunc() {
let viewController = ViewController()
// this assert will fail as the total is 3
XCTAssertEqual(viewController.add(x: 1, y: 2), 4, "returns 4")
}
Important Note the function name must start with the word test
for XCode to recognise it as a test. If the function name was just AddFunc() you would notice the run test button disappear from XCode.
with test
without test
In the above test, we are first initialising the viewController, and then using the AssestEqual method which checks if the result of the first argument is equal to the result of the second argument.
In our case, passing the add function from the view controller as the first argument and the expected result as the second argument.
We can then run the test by pressing the play
button next to the test. **The test should fail as the total should equal to 3 and not 4, if we make the change and then run the test again, we should see the test pass!
func testAddFunc() {
let viewController = ViewController()
// this assert will pass as the total is 3
XCTAssertEqual(viewController.add(x: 1, y: 2), 3, "returns 3")
}
There you have your first unit test in XCode using Swift 3.1.
Issues
Testing by importing the viewController seems to work fine, but I am currently trying to implement something similar for a TableViewController and finding that it is slight more difficult that in the example above. I'll post my solution to that issue here once I've found the best way to tackle it.
So It's taken me a little longer to work this simple readme up as I was trying to implement this simple function inside of the time project.
- Turns out it is slightly more complicated to pull functions from a tableViewController than just a ViewController. So Once this readme is complete, I'll spend some time trying to figure out the best way to write it for our app.
Update for the Readme above
When testing with a slightly complex app, in our case Time has a table view entry point with a navigation controller. Here are the steps I've taken to get to the functions inside of our TableViewController
func testExample() {
// we need to initialize the storyboard
let storyBoard = UIStoryboard(name: "Main", bundle: Bundle.main)
// then initialize the navigation controller
let navigationController = storyBoard.instantiateInitialViewController() as! UINavigationController
// we now need to extract the TableViewController which is the first child of the navigation controller.
let tableViewController = navigationController.viewControllers[0] as! TasksTableViewController
// Follow the same steps for any tests that may be present inside the viewController.
let total = 3
XCTAssertEqual(tableViewController.addTwoNumbers(x: 1, y: 2), 3)
}
It's almost as if you're learning something ... ๐ค ๐ (keep up the great work!) ๐