Skip to main content

In my last job interview – almost 2 years ago – I received a question about writing unit tests inside the iOS code. With the confidence of a developer with 8 years of experience in the iOS branch, my answer and my opinion at that moment were that if the developers are high-profiled and write good code writing unit tests is not necessary. Also, my answer continued with a conclusion: if the company has a testing team why do we (iOS developers) take their job? Throwing back on the answer and from today’s perspective, my feelings about the topic are mixed: First of all, I’ve learned more about the importance of the unit tests, and secondly, I’ve continued to work in an environment where we are not obligated to write tests.

Some basics

We should consider our code as pieces of code – called UNITS. The purpose of a unit test is to make validation of our code, and this will allow us to be sure that our code meets the design and fulfil the goal.

In XCode and iOS, the Unit tests are written in a separate target. The most important thing is the XCTest framework. The basic rule is that only the methods that start with the word test will be considered as unit tests by the compiler. Here is an example:

func testFormatForCard() {
    let formatter = DateFormatter()
    formatter.dateFormat = “ddMMyyyy”
    let date = formatter.date(from: “28061978")!
    XCTAssertEqual(date.formatForCard(), “28.06.1978”)
}

Once a test method is written with the proper semantic, the method is associated with rhombus sign on the left side:

Unit Tests with rhombus sign

We can run the tests to see if our code is good or if something is not working. If the test passes, the empty rhombus sign is changed with a green checkmark sign:

Figure 2: Test passed

In case of a failing test we have an assertion and a red sign:

Figure 3: Failed unit test

We can see in image 3 that intentionally the programmer entered the wrong output date 29.06.1978. That’s the way we should think when writing unit tests. First, we have to write the failing state and after that, we should enter the expected correct output. If in the second case the test passes, then we have created a useful unit test for that piece of code (unit). The general idea behind is if we change something in our code, and we made a mistake unintentionally the test should fail and warn us to fix the code.

Unit Test in practice

1. Code Coverage

There is a built-in option inside XCode for checking the code coverage of the tests. The ideal scenario is that 100% of our code is covered by unit tests. But is this really necessary? Will we be better programmers if our full code is supported with tests? Can we spend better the time we spent covering the tiniest pieces of code with proper tests?

In my opinion, writing unit tests is a philosophy and knowing the principles lead us to write qualitative code. That’s, of course, our goal as programmers. Covering the most important part of the code, especially the parts of code that are often changed like networking managers, parsers are a better option than trying to be perfect and writing 100% coverage.

2. Test Driven Development

The popular blog website for programmers Ray Wenderlich emphasizes the FIRST principles as a good way to follow writing unit tests. The basics of these principles are that the test should be fast, autonomous, repeatable, the output should be either “pass“ or “fail”, and ideally, the tests should be written before coding – Test Driven Development TDD.

The recommendation by TDD is writing tests before starting to fix a bug in the code. My opinion on this topic is also a mixing approach. Depending on the time you have, if the deadline is not close on the horizon, you can write tests before coding, or before starting to fix bugs in code, but that’s not always possible, and you won’t make a mistake if you skip this step sometimes.

Conclusion

I can say that writing unit tests is good for every programmer on his way to becoming great. The quality of coding could dramatically improve using unit tests. The philosophy of writing tests and thinking how the code should be structured to allow the tests to pass, will make you write cleaner code, better structured, using more protocols, make reusable classes… As in the strategy games, you shouldn’t always be a slave of the principles – the most important is to fulfill the goals in a quality manner. If you have enough time and not a strict deadline of the project you can make a bigger code coverage, but something around 75% is good enough.