# Interesting feature of Elixir: Documentation as Tests

One of the coolest feature I came across in Elixir - our code documentation becomes our unit tests. I was amazed by its simplicity when I saw it in action in sample app I was writing. I feel this is one of the most incredibly and helpful feature I saw in any modern programming language in recent times. (Python has similar functionality using Python’s doctest.)

Let me explain this by giving a quick demo using few simple examples: Math functions sum and multiply.

Lets say this is our `Maths`

module

```
defmodule Maths do
def sum(num1, num2) do
num1 + num2
end
def multiply(num1, num2) do
num1 * num2
end
end
```

First, lets add simple documentation to this `Maths`

module and its functions `sum`

and `multiply`

```
defmodule Maths do
@moduledoc """
Provides functions for mathematical computations
"""
@doc """
Returns sum of two numbers
"""
def sum(num1, num2) do
num1 + num2
end
@doc """
Returns multiplication of two numbers
"""
def multiply(num1, num2) do
num1 * num2
end
end
```

To generate documentation for this module and its functions, we need to run command (on console) `mix docs`

on our Elixir project root.

This will generate following files and outcome

- Docs successfully generated.
- View them at "doc/index.html".

NOTE: If you face any error while running command `mix docs`

then verify if your project `mix.exs`

file has hex packages `ex_doc`

and `earmark`

present. If not, then we will need to add following 2 lines

```
{:earmark, "~> 0.1", only: :dev},
{:ex_doc, "~> 0.11", only: :dev}
```

Opening file `/doc/index.html`

shows following nice documentation created by Elixir out of the box. Very neat.

Now we will write few examples in our documentation for functions `sum`

and `multiply`

and they will become tests. First, lets run these two functions in our console using `iex -S mix`

```
iex(9)> value = Maths.sum(1,2)
3
iex(10)> value
3
iex(11)>
iex(11)> value = Maths.multiply(2,4)
8
iex(12)> value
8
iex(13)>
```

We will copy paste same examples in our documentation now (three tabs indentation inside Examples block is important below.)

```
@doc """
Returns sum of two numbers
## Examples
iex> value = Maths.sum(1,2)
iex> value
3
"""
def sum(num1, num2) do
num1 + num2
end
@doc """
Returns multiplication of two numbers
## Examples
iex> value = Maths.multiply(2,4)
iex> value
8
"""
def multiply(num1, num2) do
num1 * num2
end
```

Generate documentation again using command `mix docs`

and it will now look nicely formatted as shown in following screenshot.

These documentation examples will lead to some very interesting behaviour. Testing in Elixir is first class citizen i.e. unit testing is fully featured out of the box in Elixir without a real need to add any additional plugins or libraries to write and run tests around our code. Elixir’s built-in test framework is `ExUnit`

and it includes everything we need to thoroughly test our code. And its the `ExUnit.DocTest`

that allows us to generate tests from the code examples.

So the real magic starts now, lets run our tests and see this in live action. Following command on console will run our example tests from documentation

```
mix test
```

This will now show outcome as

```
Compiling 1 file (.ex)
..
Finished in 0.03 seconds
2 tests, 0 failures
```

Lets attempt to make our tests fail by writing incorrect outcome for `sum`

function i.e. lets change the Example snippet for `sum`

to

```
## Examples
iex> value = Maths.sum(1,2)
iex> value
5
```

And lets run command `mix test`

again. This time the output is

```
Compiling 1 file (.ex)
.
1) test doc at Maths.sum/2 (2) (MathsTest)
test/maths_test.exs:3
Doctest failed
code: value = Maths.sum(1,2)
value === 5
lhs: 3
stacktrace:
lib/maths.ex:11: Maths (module)
Finished in 0.05 seconds
2 tests, 1 failure
```

So the output clearly says its expecting value `3`

whereas it got value as `5`

. Lets fix it and run again.

```
## Examples
iex> value = Maths.sum(1,2)
iex> value
3
```

And lets run command `mix test`

again. This time there will be 0 failures.

```
Compiling 1 file (.ex)
..
Finished in 0.03 seconds
2 tests, 0 failures
```

Another attribute we can add to our functions is `@spec`

, which then allows us to define the types that the inputs and outputs of the function will take. It then gets added to pages i.e. documentation created by ExDoc and allows us to get a better understanding of how to use the function. For example:

```
@spec multiply(integer, integer) :: integer
def multiply(num1, num2) do
num1 * num2
end
```

This will show up in our documentation as follows:

Further reading and references on DocTesting:

DocTests in Elixir

Thanks to josevalim and milmazz, owners and maintainers of ExDoc.

### Subscribe to Engineering At Kiprosh

Get the latest posts delivered right to your inbox