Unit Test Part I — The Do’s

Imen Gharsalli
4 min readNov 8, 2017

--

If you have been involved in software development, you have most likely heard the term unit test before. I have spent quite some time studying and working on test in general, and I would like to summarize the most important concepts about unit testing, TDD and ATDD among others through this article. So why unit test ?

The purpose behind unit test is to make sure that the most atomic behavioral units are working properly. And the reason why we need to verify that these individual units of code work as expected is in order to reduce the use of higher level tests , as a means to defects detection, such as acceptance, system and integration tests as they are more costly.

The F.I.R.S.T principles

In order to make sure that you are writing unit tests correctly, it is so important to understand the F.I.R.S.T principles. F.I.R.S.T stands for Fast, Isolated, Repeatable, Self-Validating and Timely.

Fast means that running unit tests at anytime should be no problem as far as time is concerned. Since you have multiple tests to run, execution time should ideally be at the scale of milliseconds.

Isolated means that tests should be independent from one to an other. In other terms, the order of the tests should be random.

Repeatable indicates that all test methods need to be independent from execution environment. In fact, each method should have its own data, and the results should be the same regardless of the time of their execution. Yet, you can always use Utility classes in order to setup data to be reusable if you have common data between multiple methods.

Self-Validating means no manual interventions, no interpretations, with unit test you live in color : green or red, it’s up to you to decide.

Timely represents the importance of the time at which you write your unit tests, which brings us to the next section in which we are going to discuss TDD, ATDD and POUTing.

TDD

TDD stands for Test Driven Development and represents a development process that relies on the repetition of the following cycle : test, code and refactor. In fact, the first step consists of writing a test that fails. This test is written in order to check a feature that has not been implemented yet.

The purpose now is to turn the test from red to green. This requires an implementation of the feature. At this point, the written code does not have to be good. In fact you should write as little as you can and focus rather on making the test pass. Once you’re done with this initial code, you should run the test. If the test passes and it should eventually, the next and final step consists of working on refactoring your code. This includes applying best practices and doing the necessary changes in order to obtain clean code.

It’s so important to understand that following the TDD principles relies on testing one feature at a time, meaning the whole feature, but nothing more than that specific feature. Also, while respecting the single responsibility principle which allows you to make sure that your tests never get too complicated, you need to keep going in small steps; remember test a little, code a little.

Finally, you should have the tendency to perform state verification rather than behavior verification. Yet, if there’s no state to check, then you might want to do a behavior check.

ATDD

ATDD stands for Acceptance Test Driven Development which is a development methodology that involves a collaboration between developers, testers, product owners and customers in order to define acceptance criteria prior to coding, typically in an agile project.

The aim is to make sure that the requirements are understood and respected by all parties. Acceptance criteria are checked through acceptance tests. These tests represent a quick feed back about the required functionalities of a complete user feature.

In order to speed up acceptance test, it’s important to simulate its dependencies. Also, any components should have their own acceptance tests so that you do not decrease code coverage once you have them combined.

POUTing

POUTing stands for Plain Old Unit Testing which is basically the practice of writing unit tests for existing code. It’s interesting to use POUTing for code that you do not wish or cannot test drive.

You can use POUting to reinforce your test after TDDing. Although there has been studies that show that tests that are written after coding are better than test that are written before, POUTing comes with a number of disadvantages such as the risk of testing the implementation rather than the requirement.

There’s also the risk of writing code with testability problems and the possibility of writing code with design issues, since tests can be an excellent way to perform design improvements. Encountering these issues can definitely slow you down since you would need to correct these issues before moving on with your tests, when you could have avoided them on the first place with TDDing.

This article is basically a general presentation along with few tips and tricks about the mentioned testing approaches. There will be part II very soon in which I will mention the worst practices that you should stay away from and some examples that illustrate the different concepts that we discussed. I will also make room for faking in unit tests and the transition from legacy code to clean code.

--

--