DidactMacros

DidactMacros

Doctest documentation vs testing in a mix project

I went to take a look at the ExUnit.DocTest documentation and the examples provided…

The doctest macro loops through all functions and macros defined in MyModule, parsing their documentation in search of code examples.

A very basic example is:

iex> 1 + 1
2

Expressions on multiple lines are also supported:

iex> Enum.map([1, 2, 3], fn x ->
...>  x * 2
...> end)
[2, 4, 6]

…do not resemble the unit testing implementation in the mix stub file that examples the format for unit testing.

defmodule ModuleNameTest do
    use ExUnit.Case
    doctest ModuleName

    test "greets the world" do
        assert ModuleName.hello() == :world
    end
end

Rather the emphasis is ostensibly on multi-line syntax, and different types of doc testing.

What role does doctest play in mix unit testing?

Does the default file utilise doctest , or is the macro simply present in the starter test file in case of eventual use of doctest tests?

Calling doctest(Module) will generate tests for all doctests found in the module.

It is not clear to me what format these are to take inside the module in order to be identifiable.

Marked As Solved

sbuttgereit

sbuttgereit

I would argue really none.

Doctests test the code examples in the documentation and I would suggest not thinking of them in anyway beyond that or as being related to unit testing. As such they’re relatively simple in form and assumptions are made about those examples such that the macro can automatically generate a test for them.

As for mix stub file. It’s really conflating two things. The doctest ModuleName is just testing the examples and the more extensive unit tests are in the test "greets the world" do [...] lines (and presumably tests thereafter. For a brief example this is fine, but I can see where it could confuse matters some, too.

I actually don’t mix the unit and doc tests in my own tests. I separate out the doctest into its own testing module. That way I can run the documentation testing or run the unit tests alone depending on what I want to focus on.

Also Liked

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Think of it less as “the tests I put in @doc” and more like “it tests that the examples I have in my docs run properly”. The goal is to help you catch changes to your code that invalidate your doc examples, not replace your unit tests with doc tests.

sbuttgereit

sbuttgereit

I believe there is.

I’ve mentioned elsewhere that I split my tests into three kinds of testing: unit, integration, and doc tests; each kind of test exists in testing modules which don’t mix kinds of test. This allows me to do something like: @moduletag :unit. Here’s an example of a doctest module:

defmodule DoctestsTest do
  use AuthenticationTestCase, async: true

  @moduletag :doctest
  @moduletag :capture_log

  doctest MscmpSystAuthn
end

I then use the --only flag with mix test, for example mix test --only doctest. This will run the doctests and exclude the unit and integration. When I run mix test --only integration, I get only the integration tests and not the unit or doctests. I have to imagine that the other tag oriented mix test options also work as expected.

However, I have also found that explicitly tagging the doctests like I am isn’t necessary. Even when I don’t add the @moduletag :doctest module attribute, the tag is still respected when including or excluding the doctests as though I added it. That tagging must be happening behind the scenes (or something to that effect). I would expect that this probably would work for your scenario of mixed unit/doctest files if you tagged everything else individually; a @moduletag might override the doctest identification (or not, I’ve not tried it)… but it gives hint that excluding doctest on the command line without any additional tagging might be possible.

sodapopcan

sodapopcan

OHHHHHHHHHHHHHHHHH I completely misunderstood! Yes, this makes a lot of sense and I quite like this idea. I thought you were saying you moved the actual documentation to a different module from their functions which is what raised my eyebrow :sweat_smile:

Where Next?

Popular in Questions Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&query=perfume&page=2, I would like to get: ...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New

Other popular topics Top

Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

We're in Beta

About us Mission Statement