One That’s As Important As Clean Code: Clean Test

Aldi Naufal Fitrah
6 min readMar 21, 2022

--

source: https://www.behance.net/gallery/53068979/clean-code-icon

Clean Code

Ever since before Robert Cecil Martin, or we may call him “Uncle Bob” published his stunning masterpiece titled “Clean Code: A Handbook of Agile Software Craftsmanship”, the term clean code had already become massively popular and been referenced in almost every software project. After the release, the book itself has already become such the Bible for programmers, where most if not all of our codes will most likely be justified based on that “holy” book.

Code is clean if it can be understood easily — by everyone on the team. Clean code can be read and enhanced by a developer other than its original author. With understandability comes readability, changeability, extensibility, and maintainability.

— Wojtek Lukaszuk

As a beginner in the programming world, one would not really care about the code quality he/she wrote, because understanding the logic itself might have gobbled up a large amount of brainpower and therefore nothing much left to think about the cleanliness of the code. It is not totally wrong considering the scope of a beginner project, but it will eventually become a serious issue as the scope grows. Consistently writing a bad code is like forming a snowball towards our work which will grow exponentially and one day will crush all our effort on it.

source: https://campcamp.fandom.com/wiki/Campfire_Tales

No, it was not just a spooky tale that we usually tell kids in a campfire. Uncle Bob himself wrote that there was a successful company which was selling an app that was vastly used by lots of professionals in the late 80s. Everything went well until the release cycle began to slow down, bugs were not fixed, the load time took longer than ever, and crashes were inexorable. The company then went to bankruptcy and it was confirmed by the former engineer there that they had rushed their way to deliver the product, and had injected a huge amount of messy code in the process. As time goes by, more features were added and so were low-quality code, to the extent that they were not maintainable anymore. “It was the bad code that brought the company down”, wrote Uncle Bob.

However, writing a good quality code for the features is not the only thing that is necessary for a big software development project. Our speed will in the end become slower if clean code is only applied in our production code, as we will run into the situation where changes need to be done but we are very afraid to do so due to a lack of guarantee that it will not break any other parts of the code. In this case, unit test is here to save the day.

Clean Test

In the Clean Code book, Uncle Bob allocated one chapter on this topic. He mentioned one of his experience in coaching a team that enabled quick and dirty code in their tests. This led to several severe issues that hindered their performance. Dirty test code is just the same with dirty production code, they are hard to change. But as the wise man said,

Uncertainty is the only certainty there is, and knowing how to live with insecurity is the only security.

— John Allen Paulos

Therefore, as the team modify the production code, numerous old tests begin to fail and it is extremely hard to alter them to pass again. As a result, majority of the developers blamed the messy and hard to change tests when their managers questioned about the prolonged estimation. “Test code is just as important as production code. It is not a second-class citizen” was Uncle Bob’s take from the story. He strongly believes that unit test is the one that gives flexibility, maintainability, reusability, and so many other -ilities that in the end and the most important, will obliterate our fear of making changes to the code.

So what makes our tests clean? 3 things, as written in the book, which are readability, readability, and readability. These 3 things themselves came from clarity, simplicity, and the density of expression. This also implies that standard rules like indentation and meaningful names for variables & functions also apply to our tests. The following codeblocks will show you an example of a messy and a clean test.

source: https://github.com/uasoft-indonesia/badaso-lms-module/blob/staging/tests/Feature/CourseApiTest.php#L14-L19

I personally like to follow the Given-When-Then convention which is highly encouraged when writing test, not only on the body, but also in the test name. I use the pattern test<FuntionOrBehaviorName><Condition>Expect<Result> for the test function name. Even though it may end up in a so long name, it won’t be a problem since no other part of our codes will call the function. On the other hand, this makes the readers understand what the test is all about without even reading the whole function body and this way, test report will also be more readable.

Another concept that you may want to apply to your test culture is One Assert per Test. It may seem too verbose and repetitive, but the advantage can be clearly seen when applied continuously where each tests has one and only one assertion and readers won’t have to think twice of what scenario is being tested in a particular test. Yet, I found myself on the same boat as Uncle Bob, where he agreed on this principle as a good guideline, but cannot be blindly followed for the rest of our lives.

Instead of One Assert, I support the one suggested by Uncle Bob, that is Single Concept per Test. It is pretty similar with One Assert per Test, but we are more encouraged not to be afraid to add more assertion as long as it still lies in the same concept we are testing.

source: https://github.com/uasoft-indonesia/badaso-lms-module/blob/staging/tests/Feature/CourseApiTest.php#L36-L78

The example above hopefully is able to show what I meant by single concept per test. I have several assertions there in one test function, but all of them is part of one same objective.

F.I.R.S.T.

Last thing I want to address regarding to the clean test is the F.I.R.S.T. principle. It said that clean tests should comply the following rules:

Fast. It should run quickly so you’re not afraid to run them frequently and able to spot mistakes swiftly.

Independent. No matter how the order is, each test should result in the same outcome because they don’t depend on each other. This also means that one can run a particular test separately and still getting the same result.

Repeatable. We most likely have several environments while developing our projects. A good test should be executed and give the same output regardless of where we are running the test.

Self-Validating. Verdict of a test should be in boolean. It is either the test passed or failed. One should not need to read through a long logs just to find out whether the test crashed or not.

Timely. As the TDD technique suggested, tests should be written just before the production code to ensure that there’s no excuse such as the production code is too hard to test.

To summarize my quite long writing, clean code is decidedly important in a software development process as it prevents the bad quality code to creep in and trigger a time bomb. Nevertheless, it won’t grant us the power to make changes in our code without anxiety, but clean tests will. It will guard you from breaking the existing production code so you have no worries even when deconstructing the most complicated logic in the legacy code. For that reason, do start your consistent test culture and do not treat tests as a second-class citizen. Quoting from Uncle Bob’s conclusion in the same chapter, “If you let the tests rot, then your code will rot too. Keep your tests clean.

References:
- Martin, R. (2008). Clean Code. Prentice Hall.

--

--