DidactMacros

DidactMacros

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.

Showing Posts 1 to 10

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.

DidactMacros

DidactMacros OP

Ah thanks a lot, that clears things up.

I am interpreting that doctest validates the tests that I put in @doc for example?

sodapopcan

sodapopcan

To answer this, @doc lines (or perhaps just any comment out line? I’ve never tried anything else) that start with iex> or ...>. The latter is how you do a line continuation. The assertion appears on its own line directly after the last prompt. Basically, you are testing exactly as it would work in an iex session.

@doc """
## Examples

    iex> 1 + 1
    2
"""

As per the docs, you should also indent examples four spaces. Again, I’m not sure if this is strictly required as I’ve never tried any other way.

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.

sodapopcan

sodapopcan

This got me thinking if there is a flag or tag that can be used to exclude doctests (none that I can find yet). I feel like putting them in their own file breaks the locality of testable examples as now you have to go elsewhere to see read parts of the doc. Also, how does this affect ex_docs?

DidactMacros

DidactMacros OP

Yeah, unit testing for development doc testing for illustration.

Thanks again.

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:

sbuttgereit

sbuttgereit

Hehe… I actually, do in fact do that… but that’s a different topic I believe

I misread your comment. I don’t split docs away from the thing that they document; the API surface of the module is split from the implementation… and the docs follow the API surface functions.

DidactMacros

DidactMacros OP

Would splitting effect the doc format (i.e. when the htm doc is generated)?

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
Alvinkariuki
How Can I Optimise Compile Time Dependencies I have been building an elixir application for about 2 years now. Many modules and files ha...
New
dillonoconnor
Is there any way to avoid the Hologram compiler running when using iex? It seems like the front-end code could potentially be disregarded...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews