# Doctest - a library to test Erlang doc attributes

**URL:** <https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614>\
**Category:** Libraries\
**Tags:** documentation-attributes, documentation, eunit, doctest, erlang\
**Created:** [May 9, 2024, 5:46pm UTC](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614 "2024-05-09T17:46:15Z")\
**Posts on this page:** 11\
**Page:** 2

<div class="post-metadata">

**Author:** ![williamthome](https://erlangforums.com/user_avatar/erlangforums.com/williamthome/32/471_2.png) [@williamthome](https://erlangforums.com/u/williamthome)\
**Post date:** [February 17, 2025, 9:01pm UTC](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614/21 "2025-02-17T21:01:53Z")

</div>

> [@weaver](#):
>
> Is it expected that records would work properly if they’re defined in a `.hrl` file? For example, should this work?
> 
> ````erlang
> %% @doc This function returns a record
> %%
> %% ```
> %% > record_module:abc().
> %% #abc{}
> %% '''
> 
> ````

AFAIK, this is not possible. You should return the expanded record tuple as the result. Record expressions are translated to tuple expressions during compilation.

---

<div class="post-metadata">

**Author:** ![williamthome](https://erlangforums.com/user_avatar/erlangforums.com/williamthome/32/471_2.png) [@williamthome](https://erlangforums.com/u/williamthome)\
**Post date:** [February 17, 2025, 9:06pm UTC](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614/22 "2025-02-17T21:06:03Z")

</div>

> [@weaver](#):
>
> I’ll have to try out the bindings API!

Please try it in the [v0.12.0](https://hex.pm/packages/doctest/0.12.0) release.

## Changes

- Change print order and add new lines in EUnit report by [@williamthome](https://github.com/williamthome) in [#67](https://github.com/williamthome/doctest/pull/67)
- Add bindings option by [@williamthome](https://github.com/williamthome) in [#68](https://github.com/williamthome/doctest/pull/68)
- Deprecate `-doctest` attribute by [@williamthome](https://github.com/williamthome) in [#69](https://github.com/williamthome/doctest/pull/69)

## Breaking changes

The `-doctest` attribute is now deprecated and the `doctest.hrl` was removed.

This is no longer valid:

```erlang
-ifdef(TEST).
% The doctest header sets `doctest_transform` as a parse_transform:
-include_lib("doctest/include/doctest.hrl").
-doctest #{
    % Options
}.
-endif.

```

Instead, do this:

```erlang
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
% The EUnit header will automatically export this function because it ends with "_test"
doctest_test() ->
    doctest:module(?MODULE, #{
        % Options
    }).
-endif.

```

---

<div class="post-metadata">

**Author:** ![weaver](https://erlangforums.com/user_avatar/erlangforums.com/weaver/32/2142_2.png) [@weaver](https://erlangforums.com/u/weaver)\
**Post date:** [February 18, 2025, 3:19pm UTC](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614/23 "2025-02-18T15:19:18Z")

</div>

> [@weaver](#):
>
> Is it expected that records would work properly?

> [@williamthome](#):
>
> AFAIK, this is not possible.

How does the shell do it? The thread linked below suggests some options but they all seem hacky… I have to imagine the shell has a better solution.

> [@How to evaluate expressions containing record reference?](https://erlangforums.com/t/how-to-evaluate-expressions-containing-record-reference/3273):
>
> Hi, How can I evaluate expressions such as: “X = P#person.age.” using something like erl\_eval:exprs and friends? Sort of like this (non-working code): my\_eval() -\> PersonDef = {attribute,38,record, {person,[{record\_field,38,{atom,38,name}}, …

---

<div class="post-metadata">

**Author:** ![garazdawi](https://erlangforums.com/user_avatar/erlangforums.com/garazdawi/32/175_2.png) [@garazdawi](https://erlangforums.com/u/garazdawi)\
**Post date:** [February 18, 2025, 3:43pm UTC](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614/24 "2025-02-18T15:43:35Z")

</div>

> [@weaver](#):
>
> How does the shell do it?

The shell cheats by reading the abstract code of the module and then when printing tuples, it checks if the tuple could possibly be a record and if so prints it as such. I’ve long though that we should expose an API for user code to do the same, but have not yet gotten around to it so right now it is very internal to the shell and cannot be used for any other purpose.

---

<div class="post-metadata">

**Author:** ![weaver](https://erlangforums.com/user_avatar/erlangforums.com/weaver/32/2142_2.png) [@weaver](https://erlangforums.com/u/weaver)\
**Post date:** [February 18, 2025, 3:47pm UTC](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614/25 "2025-02-18T15:47:12Z")

</div>

Thanks for the background! Makes sense that it’s difficult to do in user code. Happy to use tuple syntax for now 😁

---

<div class="post-metadata">

**Author:** ![williamthome](https://erlangforums.com/user_avatar/erlangforums.com/williamthome/32/471_2.png) [@williamthome](https://erlangforums.com/u/williamthome)\
**Post date:** [February 18, 2025, 4:20pm UTC](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614/26 "2025-02-18T16:20:01Z")

</div>

Thank you for refreshing my mind!  
I’ll implement it! o/

---

<div class="post-metadata">

**Author:** ![williamthome](https://erlangforums.com/user_avatar/erlangforums.com/williamthome/32/471_2.png) [@williamthome](https://erlangforums.com/u/williamthome)\
**Post date:** [February 18, 2025, 4:47pm UTC](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614/27 "2025-02-18T16:47:27Z")

</div>

# New release

[v0.13.0](https://hex.pm/packages/doctest/0.13.0)

## Changes

- Introduce records option by [@williamthome](https://github.com/williamthome) in [#71](https://github.com/williamthome/doctest/pull/71)  
Example:

---

<div class="post-metadata">

**Author:** ![weaver](https://erlangforums.com/user_avatar/erlangforums.com/weaver/32/2142_2.png) [@weaver](https://erlangforums.com/u/weaver)\
**Post date:** [February 20, 2025, 4:23pm UTC](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614/28 "2025-02-20T16:23:25Z")

</div>

Currently, running this on OTP 25 with `-feature(maybe_expr,enable)` raises an error when edoc tries to generate the doc chunks:

```erlang
at line 3: bad attribute

```

I encountered this using `./rebar3 edoc` on this codebase as well, but **rebar3\_ex\_doc** seems to handle it OK. I’m not sure what that library is doing differently to parse the `-feature` macro OK… is it an edoc option I need to pass?

---

<div class="post-metadata">

**Author:** ![williamthome](https://erlangforums.com/user_avatar/erlangforums.com/williamthome/32/471_2.png) [@williamthome](https://erlangforums.com/u/williamthome)\
**Post date:** [February 20, 2025, 8:50pm UTC](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614/29 "2025-02-20T20:50:26Z")

</div>

Indeed, [it is failing](https://github.com/williamthome/doctest/pull/73), but without any error output. Locally, in OTP-25, I’m receiving this error: `{features_not_allowed, [maybe_expr,maybe_expr]}`.

Unfortunately, I’ll be busy for the next few days to look into this =/  
Please keep me updated if you find any possible solution.

---

<div class="post-metadata">

**Author:** ![williamthome](https://erlangforums.com/user_avatar/erlangforums.com/williamthome/32/471_2.png) [@williamthome](https://erlangforums.com/u/williamthome)\
**Post date:** [March 1, 2025, 12:49pm UTC](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614/30 "2025-03-01T12:49:30Z")

</div>

Hi! Did you find a solution?

---

<div class="post-metadata">

**Author:** ![williamthome](https://erlangforums.com/user_avatar/erlangforums.com/williamthome/32/471_2.png) [@williamthome](https://erlangforums.com/u/williamthome)\
**Post date:** [April 3, 2025, 9:49pm UTC](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614/31 "2025-04-03T21:49:20Z")

</div>

Fixed in [v0.13.1](https://hex.pm/packages/doctest/0.13.1).

Please note that you must enable the maybe expr also via `ERL_FLAGS` to make it work in `OTP-25`, e.g.:

```erlang
ERL_FLAGS="-enable-feature maybe_expr" rebar3 eunit

```

Without it, it will fail.  
It is not required to enable it via `ERL_FLAGS` for OTP \>= 26.

See [How to enable maybe\_expr?](https://erlangforums.com/t/how-to-enable-maybe-expr/2154)

[Previous page](https://erlangforums.com/t/doctest-a-library-to-test-erlang-doc-attributes/3614.md?page=1)
