jonleighton
jonleighton

Reputation: 1051

How can I use Elixir's doctest to test a protocol implementation?

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?

Upvotes: 3

Views: 509

Answers (2)

Guy Argo
Guy Argo

Reputation: 407

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

Upvotes: 0

jonleighton
jonleighton

Reputation: 1051

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

Upvotes: 4

Related Questions