Test Driven Development — XCTests (Xcode 10 & Swift 4)
By: Awais Akram
Tags: Test Driven Development, Xctest, Xctestcase, Unit Testing, Swift

TDD Cycle

There is no right or wrong way to develop mobile application or software. However, there are dozens of techniques and approaches that can make the process faster and the results — better. The test-driven development methodology (TDD) is one of them.

Being a very popular software development methodology, it is widely used by agile software development teams. It can significantly speed up the development process, and can make it more efficient and cost-effective in the long run.

What is Test-Driven Development ?

Test Driven Development is a way of writing software. At its core is a simple cycle: Write a test, write as little code as possible to make the test pass, and then refactor (tidy up) the code. It sounds deceptively simple, but it’s a powerful way to write your code.

How Test-Driven Development Works ?

At the beginning the test case obviously will fail because the code is not yet implemented. This phase is usually called the red phase. The developers then write the code to make sure the test case pass successfully and does not break any components or current test cases, the code in this phase does not have to be fully optimized and efficient. This phase is called the green phase. After this, the developer should refactor the implementation of the code by cleaning, maintaining the codebase and optimize the efficiency of the code. This cycle then should be repeated as new test case is added. Each unit of test should be made as small and isolated as possible to make it easier to read and maintain.

What are you going to build?

We are going to build a simple calculator with just 4 basic arithmetic functions (Division, Multiplication, Addition & Subtraction) in Xcode 10 and Swift 4. Since we know 20 + 10 = 30… if the function returns 30 the test will pass, otherwise the test will fail and we know we will need to fix our function.

Unit Tests Modules:

Many developers practice test driven development (TDD). TDD involves writing test code before writing the production code associated with that test. The purpose of Unit Testing is to divide the application into small little components and then test it. Each component should work independent of others, so we will also divide the app into 4 tests.

Setting things up:

Let’s create a new project in Xcode with include unit tests checkbox checked.

Include Unit Tests checkbox is checked

Take a look at the project in Xcode. These are the main files we are running unit tests on:

1. Maths.swift

The Maths.swift class contains the Maths engine, the core arithmetic functions that are going to be test in 4 components i.e Unit Tests.

2. MathsTest.swift

The MathsTest.swift class contains the XCTests (Xcode Unit Test cases). This class is inherited from XCTestCase.

Maths.swift class in detail:

In our Maths.swift class we have the Maths Engine, the core mathematical functions.

Here, we have 4 basic arithmetic functions:

1. Addition

2. Subtraction

3. Multiplication

4. Division

All functions described in this class takes two parameters as input (num1 & num2) and returns the relevant output.

MathsTest.swift class in detail:

As you can see MathsTest.swift class is inherited from the XCTestCase class.

If any of you are wondering what the “@testable import” statement does when you use it in unit tests, it basically imports your module and lets you write unit tests against its internal entities.

We have also created an object of Maths() class here named as math.

Unit Test (Test Cases / XCTests)

In our MathsTest.swift class we also have 4 Unit Test Cases for 4 different functions.

1. testAdd

2. testSubtract

3. testMultiply

4. test Division

Whenever a function in XCTest class is prefixed by test keyword then it automatically become a unit test. That’s why all the functions written in MathsTest.swift class are prefixed by test keyword.

Unit Tests also have a diamond shape in the starting.

XCTAssertEqual: Asserts that two expressions have the same value.

TIME TO RUN THE TESTS:

Let’s run the tests by pressing Command (⌘) + U, You’ll see that all the tests have been failed because in TDD the first step is to make the test fail and then make it pass and then followed by re-factoring. Whenever a test fails a red cross diamond appears at the declaration(starting) of the function.

IMPLEMENTING THE CODE:

Let’s go to the Maths class and write the all the functions according to maths logic.

As you can see the Core functionality of all functions are right according to Mathematics, let’s go back to MathsTest.swift class and run the tests again by pressing Command (⌘) + U.

You’ll observe that the all tests have been passed successfully. Whenever a test passes a green tick diamond appears at the declaration(starting) of the function.

CHANGING THE CORE LOGIC:

How about altering a function logic and testing wether the output remains same or the test cases we wrote above are actually correct and working.

Altered add function

Explanation:

The add function in math class has been altered and returns difference of two numbers instead of their sum. The test case should fail in this case.

Dry Run of add function:

num1 – num2 = result

10 – 20 = -10

result ≠ expected // XCAssertEqualFailed

-10 ≠ 30

Test Case Failure

As you can see the test failed because the XCAssert throw an error that expected and real result is not same, so we made a test fail just to make sure that the test case we wrote is correct.

XCTAssert

XCTAssert is one of a family of asserts for unit testing from the XCTest framework, and should only be present in Unit Test Targets (i.e. not in your application code). If the assert fails, it does not terminate the execution of the test harness or hosting application, but records and reports the failure.

XCTAssert Variations

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.

Here’s all you need to do to get started with unit tests in iOS

Add a unit test target. A unit test target is a separate executable with a single purpose, running your unit tests. When you ship your app to the App Store, this test target is not included. Although it’s not recommended, you can have compiler errors or bugs in this target, and it won’t affect the product your deliver to the App Store. Import your app or framework module into the unit test target. Xcode has a handy import statement that makes this nice and neat. You don’t need to give all of your files membership in the unit test target like you used to. Write tests and run them in Xcode. You can write and run your tests in one place. Just hit command U and see what passes or fails.

There’s quite a lot more to discuss about Unit Tests. I just wanted to show you that unit tests aren’t some giant monster. Anyone can start writing them in just a few minutes.

Thank you for reading the article. You can find the source code here in my GitHub repository.

Happy Coding !