Motivation

Let’s start by talking a little bit about what reasons I have to test my systems the way I do.

Let me start by telling you that I learned to work this way in my OOP course at UBA. The course was based on Smalltalk, and it was delivered by one of the best teachers I ever had: Hernán Wilkinson. In Smalltalk, the whole image (remember: the code, the VM, even your editor… they all live in the same image) is designed to be used in a TDD fashion, with lots of tools that simplify your life if you work that way. So… I learned to work that way. Later on, when I started working with Erlang I found that even when it was not as easy as it was in Smalltalk, it was entirely possible to keep using TDD. And that’s what I did!

But that’s my story, why would you use TDD when writing Erlang code? Well, let me tell you a couple of things I consider valid reasons for that:

If you’re testing it anyway, why don’t you write a test for it?

Most of the times, writing tests in Erlang is not difficult. It gets tricky when multiple processes are involved and you have to deal with concurrency and what-not. But particularly in those situations, even if you don’t follow TDD, you usually test your code. You don’t just write the code and let it be, you open up a console, compile your module (not necessarily in that order) and write some commands to verify that your functions actually do what you want them to do.

If you don’t have erlang-history installed (and you should!), the second you close that console you loose all the expressions you evaluated. In order not to loose them, you copy them in a text file somewhere. In that case, why don’t you just put them inside a function (or multiple ones) and pattern match their results? If you do that, you suddenly have a test! That requires almost no additional effort but now that test is easily repeatable. That’s a huge win.

Refactoring Code

Being able to confidently refactor your code is one of the main reasons to write tests in the first place, regardless of the language you choose. This subject was covered extensively on the internet already, I won’t go in detail here. If you want just one link to read, check StackOverflow.

Tests as Specs

Usually the main purpose of the tests I write is to specify the expected behavior of my system. I write the tests to say “This is what this function should do”, “This is how this module should work”, “This is what this API must return in this scenario”, etc. Later on when I wonder What did I write this function for? I want to be able to go to the test that exercises it and find the answer.

Open-Source

Most of the code I write this days belongs to open-source libraries. It’s crucial for those projects to be thoroughly tested. That’s because they will be used by people that will rely on them. As an open-source user, I always tend to trust the libraries I use. If there is an error, the libraries are the last place I consider debugging: my code goes first, of course. So, as an open-source author, I like to be able to confidently state that the libraries that I provide do work as intended. Note that having tests doesn’t automatically ensure the absence of bugs, but at least having tests ensure that, if my users use the library like the tests, they’re on the safe side.