3

I want to be able to doctest the implementation of a protocol in Elixir.

Here is some example code:

defprotocol Size do
  def size(data)
end

defmodule Foo do
  defstruct []

  defimpl Size do
    @doc """

    ## Examples

        iex> Size.size(%Foo{})
        0
    """
    def size(foo) do
      0
    end
  end
end

This test code doesn't work (because it only finds functions defined in the Foo module, outside of the defimpl):

ExUnit.start()

defmodule FooTest do
  use ExUnit.Case
  doctest Foo
end

How can I test the defimpl block?

jonleighton
  • 1,041
  • 8
  • 12

2 Answers2

4

It turns out that defimpl defines a module behind the scenes. This can be found via the impl_for function on the protocol:

iex(1)> Size.impl_for(%Foo{})
Size.Foo

So we can doctest this module like so:

defmodule FooTest do
  use ExUnit.Case
  doctest Foo
  doctest Size.Foo
end

Note that if both Size and Foo are in the same module (say MyModule), the module name must be specified twice:

defmodule FooTest do
  use ExUnit.Case
  doctest MyModule.Foo
  doctest MyModule.Size.MyModule.Foo
end
jonleighton
  • 1,041
  • 8
  • 12
0

Prepend the name of the protocol in front of the path. For the given example, it would be:

defmodule FooTest do
  use ExUnit.Case
  doctest Foo
  doctest Size.Foo
end

For the longer example, it's just:

defmodule FooTest do
  use ExUnit.Case
  doctest MyModule.Foo
  doctest Size.MyModule.Foo
end

Per Valim: https://groups.google.com/g/elixir-lang-talk/c/zNMFKOA-I7c

Guy Argo
  • 397
  • 4
  • 10