Up to this point, my experience with Erlang professionally has mostly been with ejabberd. I’ve created many ejabberd modules and have had to modify ejabberd core for certain projects (sometimes heavily). Now that my current client work at CitrusByte is over, I’ve been notified I will be working on a fairly customized Erlang/OTP application. Without going into too much detail, I have just began seriously looking at EUnit.
In the past I have unit tested my Erlang source files by manually creating a test method and running it via a bash script. This works, but it is a bit hard to manage and you don’t get a lot of things for free; I just used pattern matching for the unit tests. Now that I’m starting a new project, I decided to start right with a proper unit testing framework. For those of you not familiar with the practice of “unit testing,” this article is not for you and you should google around, there are thousands of resources available.
For some reason I assumed Erlang would come shipped with EUnit, and spent a good 10 minutes “debugging” why my unit tests weren’t available! Of course I was wrong, I had to go grab EUnit myself. You can grab it by checking it out of the EUnit trunk via SubVersion. I know there is a ZIP file also available on process-one’s website but the code is pretty outdated so I recommend checking out the trunk.
Go into the download eunit/ directory and type make to compile all the Erlang source files. After doing this, make sure to copy your eunit/ directory to the Erlang lib directory, which can be found by running code:lib_dir().
Basics of EUnit
There are quite a few resources for EUnit which I’ll link at the end of this article. So as not to totally reinvent the wheel I’m only going to cover a few topics here and will trust that you have the drive to read the other articles which are fantastic for getting off the ground.
EUnit is minimally invasive to your code. By this I mean the only real change you need to make to your source files to get it up and running is to include a header file. Here is an example of the preprocessor command I use:
This header file does do a small amount of magic. That is, it automatically exports a test/0 method from the module if it doesn’t exist already. This test method automatically calls any methods ending in _test or _test_ (a subtle but important difference).
The *_test methods are expected to return anything on success, or throw an exception on failure. Erlang actually has a great testing construct baked into the language: pattern matching. This is what 90% of your tests will use. The following is an example test:
reverse_test() -> [3, 2, 1] = lists:reverse([1, 2, 3]).
This test will pass. If instead I put [3, 1, 2] it would have raised a badmatch exception and the test would have failed. Simple, isn’t it?
Getting More Advanced
This is just the surface of EUnit, but luckily, the rest of it isn’t much harder to understand. Unfortunately, EUnit doesn’t have mocks/stubs, which many Ruby programmers may miss (as we are all spoiled with our RSpec). I’m not going to cover any more of EUnit in this article since there are a handful of articles who do this already, and I don’t want to steal their thunder.
But one last thing I really liked…
Hiding Your Tests In Production Systems
Its great that EUnit automagically exports your test methods and runs them and all that but after the tests pass and the green icon shows, nobody really wants these in a running system. Unsurprisingly, EUnit developers already thought of this and offer an easy way out: Simply define NOTEST before you include the EUnit header file. If this is defined, nothing will happen.
I put NOTEST in all my files right away. Don’t worry, to run the tests you don’t have to manually remove this line. When you compile your Erlang source files for testing, add the -DTEST flag to the compiler, which will define the TEST macro. This overrides NOTEST. An example erlc command:
erlc -DTEST module.erl
The following is a list of valuable resources I found picking up Erlang. All gain my stamp of approval (if that means anything to you).
- The Official EUnit Summar Page
- Paul Nelson’s EUnit-Based Erlang Tutorials
- Kevin Smith’s Screencast on EUnit - Highly recommend if you’re willing to spend a small amount of money. Its worth it.
As a final note or disclaimer: I haven’t used EUnit a great amount yet in a professional environment so this is a very high-level overview of EUnit. I’m sure as time goes on and this new project goes on, I will have more to say.