avatarMarcin Kozak

Summary

The provided content advocates for embracing unit testing as a beneficial and enjoyable aspect of software development, emphasizing its role in improving code quality and development efficiency.

Abstract

The article on the undefined website discusses the importance of unit testing in software development, encouraging developers to not only understand its necessity but also to find joy in the process. It acknowledges that many developers dislike writing tests but argues that unit testing is essential for ensuring code works as expected and reduces the risk of undetected bugs. The author shares their personal journey from being required to write tests to genuinely enjoying the practice, highlighting the time-saving and effectiveness of unit testing. The article suggests that enjoying writing tests can be achieved by recognizing the benefits of unit testing, such as easier code development, safer changes, and the ability to run quick checks. It also recommends learning unit testing early in one's programming career and adopting a testing framework that suits the developer's language and style. The author emphasizes that unit testing should not be postponed and that integrating it into the development process from the start can lead to better code and a more enjoyable coding experience.

Opinions

  • The author believes that unit testing, while often disliked, is a critical component of software development.
  • Enjoying unit testing can lead to a more effective and pleasant coding experience.
  • Learning to write tests early in one's programming journey is highly beneficial.
  • Unit tests should be written concurrently with code, not postponed until later stages of development.
  • The author suggests that the key to enjoying unit testing is understanding its value in saving time and improving code quality.
  • Using a suitable testing framework can enhance the experience of writing unit tests.
  • Documentation testing, such as Python's doctest, is praised as a method to further integrate testing into the development workflow.
  • The article posits that writing unit tests can transition from a chore to a liked, if not loved, part of coding when approached with the right mindset and tools.

Make Yourself Enjoy Writing Unit Tests

Most developers dislike writing tests. If you’re among them, do your best to change that.

Photo by Joshua Lawrence on Unsplash

Unit testing constitutes one of several essential aspects of a software product, or rather of its development. I would not say the most important one, but definitely essential. Unit testing enables developers to test their code divided into independent components, that is, small, individual units of code: functions, methods, classes, modules — and any objects, for that matter.

Unit testing is accomplished by writing code dedicated to testing particular units of the application, and then running this testing code. If a particular test passes, nothing happens. If it fails, the user is informed about this in this or another way, depending on the framework used. Seeing that something has gone wrong, the developer can work on the code unit that has not passed the test.

When the whole codebase is covered with unit tests, and you run them as often as needed (e.g., after even minor changes), you increase the probability that the code works as expected. The same way, you reduce the risk that something can go wrong and unnoticed. Partial test coverage is better than none, but the smaller the coverage, the bigger the risk that your code is invalid.

This article does not assume you’re familiar with unit testing — or that you are familiar with it, for that matter; nor does it introduce unit testing. I do not aim to explain how to write unit tests. Each programming language has its own, sometimes quite specific, testing frameworks. Thus, introducing unit testing would require focusing on a particular language, while here I want to discuss general, language-agnostic topics; topics that work in any programming language, for any unit-testing framework. If you lack basic knowledge of unit testing, grab a good book and read about it. I will not propose one, as to be honest, I know only books on testing related to the languages I work with (Python, Go and R). I think it’s best for you to learn unit testing from a book on your programming language, not a general one. The reason is simple: it will be easier for you, as this will be your territory. General resources on testing can be valuable, but for those who know the topic well, not for beginners.

In this article, we will discuss why it’s good to enjoy writing tests. This wording suggests that I will be subjective. And indeed, I will share my story and opinion with you. Maybe your story is similar; maybe your opinion is. Or maybe not, but you will like them so much as to accept my opinion as yours. Maybe you will disagree with me, which is nothing wrong. We’re being subjective here. Even if this is the case and you disagree with me, it’s possible that the article will provoke you to think about testing, helping you organize your thoughts about unit tests, writing them — and liking them.

Most developers dislike writing tests. They write them because they have to; because unit tests are essential; because the product they work on must be covered by tests; because their company requires unit tests for all its products; or for one of many other possible reasons.

Seldom, however, do developers like writing tests. I am a rare exception. Why do I like unit testing and writing tests? To be honest, I don’t know. I suspect that this is because of my story. When I heard the concept of unit testing for the first time, I started writing them. I had to write them, that’s true; they were a must in the project I worked in back then. This is not unusual, as unit testing is an important element of the code base in all software-development projects. I quickly realized how helpful unit tests can be (of course, those well-written) for both the code and the project; how easier it is to develop code and how graceful it can become; and how safer and quicker development is.

It was when I noticed these things that my perspective changed. While before I was writing unit tests because I had to, I started writing them because they were so useful. One thing led to another, and soon I started enjoying writing unit tests; ever since, I find pleasure in writing them. They calm me down — because I know they reduce the risk that the changes to the code are not bug-free and that the code will not work as expected.

For these reasons, I want to convince you that it’s worth to enjoy writing unit tests — because doing something you enjoy is much easier and more effective than doing something you don’t like.

I will also try to propose how you can try to make yourself to enjoy writing unit tests. This is a subjective thing, so you will have to decide yourself what works for you and what does not. I do hope that you will find at least one method that works, as the essential purpose of this article is to help you find a way to start enjoying writing unit tests.

Doing something you enjoy is much easier and more effective than doing something you don’t like.

Of course, there is not a single recipe. Many of you will fail, and even if they start or continue writing tests, they will still force themselves to do this. But I hope some of you will not only learn that unit tests are essential in software development, but also that they can support you in writing high-quality code, being as much helpful as to actually make you like writing them.

There is one essential condition you must meet in order to enjoy writing tests: You must enjoy writing code.

You must enjoy writing code.

Writing tests means coding, so if you don’t enjoy coding, then of course you will not enjoy writing tests. In addition, unit testing aims to help you achieve better code when working on an application, not to write this application.

Those for whom it’s a first journey towards unit testing can use this article for one more thing. In order to convince you why it’s worth enjoying unit testing, I will provide some explanation of its essential aspects. Thus, reading this article should help you gain the basic knowledge of unit testing and related topics.

Learn to enjoy writing tests

Unit tests as an essential part of code

Think if you know the following story. You start writing a program. So, you wrote the very first function, and you want to check if it works. You run the function for several expected arguments, and you see it works fine. Great. So, you write another function. The program has now two functions. You check if the second function runs fine, by running it with several expected arguments. Something is wrong, so you revise the function, and you check it again with the arguments that failed before. One more change (something small did not work correctly), and one more check (with the same arguments), and all works fine. You also check if it works for those arguments for which it worked fine before; better safe than sorry. It does, all is fine.

Now, it’s time to check if the first function will take the output of the second function. You check this, and you see it does not. The first function needs to be changed a little. You do so, and you check it with the output of the second function; it works fine. You should, however, check the first function with the same arguments you checked it with at the beginning, those that were not the output of the second function… What were these arguments? Difficult to remember everything, you’re just a human. You found them, and so you check… No, the function does not work! Why? And so, and so forth…

Two days pass. The application grows bigger and bigger. You have five functions, and every time you change something or write a new function, you need to spend a lot of time on checking if everything works. Sometimes it does, but other times you see that a change in one function calls for a change in another, and then you again must check both functions… and then you should actually check if all the other functions that cooperate with these two work fine with them…

Do you know the situation? I do. This is exactly how I proceeded during the beginning of my programming journey. I know many others follow this approach, as I’ve heard it from many data scientists (which does not mean all) I’ve interviewed for various positions. Many self-taught developers, without a programming or computer-science background, do the same.

Do note that in this approach, you run many tests manually., one after another. Sometimes you run just several of them, sometimes a lot. Unfortunately, such an approach has quite a few disadvantages:

  • You have to check yourself whether the result is as expected, as opposed to automatic checking.
  • You have to control which tests to run: which functions to check and with what arguments. To make things simpler, you can write a dedicated program that will do this for you.
  • In interpreted languages, such testing is often done in an interactive session. That way, the tests are not independent even though they should. So, depending on what has been done in the session, the tests can differ from session to session. (I’ve been there!)

As you see, you need to be very careful when organizing such manual testing. Although above I’ve called this approach testing, this is not formal testing. This is rather manual checking of the program. The point is, note how much effort goes to such an approach.

You must spend much time to do this, and the only way to make sure that such double-checking provides the same result is to write a dedicated program. Note that you’re just one step from writing formal unit tests.

This is actually a good thing. You’re almost writing formal unit tests. The trick is to make them unit tests, and more often than not, you can do it with little fuss.

And once you’ve made this step, your life is going to change — it’s going to change for the better!

Learn to write tests from the beginning of your programming career

From the above story, and millions of similar ones from around the globe, it follows that even those who do not write tests test their code. Testing code does not have to mean writing formal tests using existing frameworks. You just have to do that because you have to check if the code runs as expected. Can you imagine writing code without checking it at all?

Now recall the program we mentioned, the one which contained code that aimed to check if the application worked. We could call it a unit-testing program; formal or not, it’s still testing. It can be written better or worse, but it helps you test your application.

Since you write it anyway, write it the right way. The sooner you start writing unit tests, the better. There are guides, rules and frameworks to help you write unit tests, and they can help a lot.

The sooner you start writing unit tests, the better.

You can — and should — understand this sentence twofold:

  1. When you start writing code for your project, don’t put off writing unit tests. They should help you develop your code, so delaying to write them makes no sense.
  2. When you start learning programming, start learning unit testing in this language as soon as possible.

I know statisticians, data scientists, and self-taught developers who, after several years of learning programming, still don’t know what unit testing is. If you’re among them, I’m asking you to change that. You should not only know what unit testing means; you should also know how to write unit tests — and you should use them. It’s never too late, so why not start today? You will not regret this decision!

So, we can enrich the above suggestion with the following one: When you start learning a programming language, don’t postpone learning unit testing in this language.

Not necessarily do I mean here Test-Driven Development (TDD), in which you start writing a function (or any other coding unit, but for simplicity I will call it a function) by writing a test for it. It will not pass, of course, since you have not written the function. After having written unit tests that describe the expected behavior of the function, you develop it so that it passes the tests. When the function works fine and all the tests pass, you can proceed with the same approach to add new functionalities: write tests that do not pass, and then develop a function (write a new one or develop an existing one) so that it passes the tests.

TDD resonates with agile software development. TDD, however, does not have to be that easy for beginners. Fortunately, you do not have to be this strict from the very beginning. You can use a slightly modified approach, which we can describe as follows. You write the function’s first draft, and then you implement unit tests that well represent the expected performance of the function. Then you check if the function passes the tests, and if not, you revise it — until it passes all the tests. Then you update the function and add new tests. In other words, you develop the function in small steps, adding in the meantime new tests to represent the changes. Of course, every time you update the function, you run all the tests, not just the ones for the recent changes.

Remember to make unit tests as independent as possible. This rule helps you run tests in isolation.

When you work on another function, you can — and usually should — run all the tests, just in case. It’s safer. For this to work, you should follow the rule of thumb of making unit tests quick. If they take 2–3 seconds and you can run them with just one command or mouse click, you waste no time. Even up to 10 seconds is not a problem. But when you need to wait for half a minute or even over a minute, sometimes you will decide not to run the tests; that’s why it’s good to make them quick.

With time, you will also add integration tests, which test whether two units of your code integrate well with each other. Sometimes you will not even know that a particular test is an integration test, but don’t worry about that. It’s just naming, and what counts is that you’ve covered your code with unit tests.

Do you see a difference between this approach and the previous one? Even though you will spend additional time on writing tests, at the end of the day you will save time — the time you would spend checking the code. All in all, not only will you save time but also you will write better code; and you will follow one of the most important rules of software development: cover your code with tests.

In this article, I want to convince you to at least try to learn to enjoy writing unit tests, not to explain how to write them. Hence, I will not dig deeper into unit testing. There are thousands of positions on this topic, usually specific to a particular programming language. So, grab a good position about testing in your language and read it to learn more.

The point is that if you notice how much time you can save thanks to tests, you may start liking writing them.

Don’t postpone!

The point is to not postpone writing tests; not until you finish writing the function (as then the tests will probably show that the function does not work as expected); not until the evening; not until the end of the week; not until the end of the sprint (in agile software development); and most of all, not until the end of the project.

Many developers dislike writing tests, so they postpone writing them. When the project has a large codebase, writing tests for it becomes a heavy and risky task, for two reasons. First, you must write a lot of tests simply because of the amount of code to be covered with them.

Second, more often than not, you will see that some functions do not work as expected. When you run them for a specific configuration of your application, it can work fine, but are you sure the configuration will never change?

Third, note that most likely, you will spend more time on writing the code (including tests) than when writing tests during writing code. This is because you have to test the code anyway, and doing so without tests — as I showed above — is both inefficient and ineffective.

Thus, you should not postpone writing tests. But also, you should not postpone learning to write unit tests.

You should not postpone writing tests. You should not postpone learning to write unit tests.

How to enjoy unit testing?

I promised I’d tell you how to make yourself enjoy unit tests. I don’t know what will work for you, but I can tell you what worked for me.

I think I started to like writing unit tests when I learned how much time I can save and how more effective my coding becomes. When you notice this, you will at least understand and appreciate that unit testing is your friend. A close friend, one whom you can trust.

It’s not that easy to ignore such a friend; nor is it wise. But that’s was not the whole story. Then, I increased my liking when I noticed how simple it is to run unit tests. Just one minor command, and I see everything. It cannot be simpler! Compare it to manual checking of all the functions and the whole application. It’s like a second against minutes, and sometimes even dozens of them.

After I started liking unit testing, I decided to learn a little more about them. My first shot was pytest, a Python unit testing framework. Once I noticed how simple it was to write even quite advanced tests, I thought, “Hey, this is getting even better!”

Still not the whole story! The last point, one that made me fall in love with unit testing, was learning documentation testing. In Python, you can use doctest for this. When writing documentation, you write code (in a particular format) and its output (so it’s sort of regression testing), and then, with one command, you can run this code and check if the output is as expected. Isn’t that wonderful? I went crazy when I learned this — literally crazy! What’s more, you can use doctest not only as a documentation-testing framework but also as a unit-testing one. This was so great to me that ever since, I just cannot imagine coding without testing; enough to look at any open-source Python I (co-)authored (you can find them in my GitHub repo), and you will see either pytest or doctest tests, or both.

Documentation testing is available in quite a few programming languages, in various forms. For instance, Go offers a tool for testable examples, which are automatically rendered inside the documentation. If your language does not offer any such tool, you may look for general tools that work with various languages. One example of this is byexample.

At this point, I loved writing unit tests. It’s easier to like something when you know how to do it, so remember to spend some time one learning the framework of your choice; don’t stop after a couple of hours of attempts. Some languages offer more testing frameworks, and you may like one more than others, so when you feel a particular one does not suit you, try another one.

I wish you that like me, when you reach this point, you will enjoy writing unit tests. And if not, at least you’ll appreciate them and see that they make coding much simpler.

That’s all for today. Thanks for reading. I hope I have convinced you that writing unit tests is a critical aspect of coding, no matter what language you are working in. Even this would mean our common success. But it would only be half of the battle won. I don’t want you to spend your whole life torturing yourself with writing unit tests. I wish you like writing tests, enjoy it — because your work comfort would change for the much better.

Many developers dislike unit tests, and in particular, writing them. I doubt I am the only exception to this rule, but I believe the group is too small. I hope you will join us. At least now you know it’s possible to enjoy writing unit tests. After all, it’s an extremely effective tool, without which writing code is far more difficult and therefore far less enjoyable.

Why would you not want to make your life simpler by enjoying something that, most likely, you will do on a daily basis throughout your career?

So, here’s a challenge for today: decide to use unit testing; the challenge for tomorrow: start writing unit tests; and the challenge for the day after tomorrow: appreciate how helpful they are, and how simpler and more enjoyable your coder’s life has become.

Eventually, you will enjoy unit testing and writing unit tests!

Mission accomplished.

Resources

https://en.wikipedia.org/wiki/Test-driven_development

Testing
Test
Unit Testing
Programming
Coding
Recommended from ReadMedium