Testing in Elixir:: Chapter 1: Introduction

Part 2

Hey, welcome back!

The previous part of this chapter is found here

So, unfortunately the calculator we built in the last chapter isn’t going to make us billions… not right now, at least.

But before we cry into the gold-plated seat of our jet ski we may have prematurely bought, we have a new request from Product:

Hey, new team mate! *wave*

If you haven’t been documenting your code throughout, the request for documentation typically goes one of two ways:

  1. Met with a groan, a sigh, some huffing and puffing and other weird sounds, to convey that the request is a chore, and that if the developer was any good they could just read the code and pick it up in “20 minutes”
  2. A frantic whirlwind of slack messages and shouts across the office of “Dave, in accidental_godclass_we_will_refactor.rb, how do we get to the 5th nested clause in the if statement… you know the one you get if you foo the bar while sshing into jenkins?”

Being the responsible developers we are though, as well as knowing that this calculator will be THE calculator that the known world will rely on, we should document our code properly and help out our new developer friend.

Elixir is amazing for documentation. It considers documentation a first-class citizen and there is a library called ExDoc that will automagically generate a webpage for your documentation.

In fact, if you have ever looked at the Elixir docs, these were built using the same tools and approaches that we will be using!

This is where we left off our calculator in the last lesson. Notice the @moduledoc false ? This is what we are going to be using to write our documentation.

To demonstrate documentation writing, we will first add a dependency to our project, in our mix.exs, inside the deps add the line {:ex_doc, “~> 0.16”, only: :dev, runtime: false}, and run the following commands to install our new library:

mix deps.get && mix deps.compile

When writing documentation in Elixir you have @moduledoc and @doc . The former is used to describe what the module does and the second allows us to generate examples that can not only be run in iex, but can also be tested using ExUnit.

Yup — testable documentation.

So, let’s update our calculator with a description:

As you can see, in order to add module documentation we wrap our description in three quotes: """

Running mix docs in the terminal will generate a doc/index.html file which, if we open with any browser, will give us a page that looks like this:

Automagically generate documentation for all!!

Okay, that’s pretty cool. So, let’s up the ante and provide some testable examples:

This one has a few moving parts, but follows the similar wrapping in quotes as @moduledoc did.

We begin our @doc by adding a description of what the function does. Then, to provide testable examples, we follow a specific pattern of:

  • ## Examples . This needs to be on its own line, with a line space above and below
  • iex> . This needs to be indented four spaces from the ## Examples line
  • The module name must be in full, with any name spacing included
  • The function call and the expected response need to be on separate lines

After writing these examples and running mix docs , we now get an even more impressive page generated:

Yup, this is pretty awesome

By following this pattern we can now use ExUnit to test our documentation, which should catch any changes we make in the future. This in turn will allow us to keep our documentation update, as these tests will fail in a suite run as normal.

So, how do we get ExUnit to test our documentation examples?

We add the following line to our module’s test:

doctest ModuleName

Anticlimactic, huh?

See line 3? Yup, that’s all we need to do. Now when mix test is run, documentation is checked.

And this ticket is done and our new developer should be very happy with us!!

After finishing the last ticket, another one comes through for us to do. Probably a good job, as people in the office are surely wondering why we have replaced our chair and desk with a gold plated jet ski… Quickly, before reality sets in!

A fair request. I mean, while you could get around this by using lots of addition and negative numbers, our user experience testing wasn’t the most successful. So, lets make things easier!!

This should be quite quick to do if we repeat the approaches we have taken previously. So, after a coffee — and occasional eye rolling at our text editor not behaving — we have the following:

And by running mix docs we now get a much more impressive piece of documentation to play with:

Testing wise, our test file is tweaked to incorporate doctest , but we have alsobextracted out common behavior into its own describe block. We know that we return the same message on the wrong type being passed in, so we extract it into a describe block that looks at common behavior:

Congratulations, this concludes Chapter 1.

The repo for all code used can be found here

The README.md also contains the planned upcoming chapters. If there is anything you would like to see, then leave a comment.