0

An answer to a similar question has this question.

In order to test a function with doctests, you must be able to predict the output of your function.

Issue

As mentioned in the title I would like to stick with using doctests but this doesn't seem to be working and I don't believe there isn't a way to do it.

Code

  @doc """
  Update a field(s) in a setting record

  ## Examples

      iex> example = Setting.get(id: 4)
      iex> Setting.update(example, %{keyname: "an_example"})
      {:ok, %Elements.Setting{_}}


  """
  @spec update(struct :: Elements.Setting, changes :: map()) :: {:ok, Ecto.Schema} | {:error, Ecto.Changeset.t()}
  def update(struct, changes) do
    ...
  end

Above is the code that I've been trying and variations of it. Such as using _ where the data is going to be unexpected. Just the bits that wouldn't have changed.

For example, ideally I would want the return value to look like {:ok, %Elements.Setting{keyname: "an_example", _}. So the documentation passes but it's also legible to users what they are reading and can see the effects of the code that was before it.

iex

iex(6)> Setting.update(example, %{keyname: "an_example"})
{:ok,
 %Elements.Setting{
   __meta__: #Ecto.Schema.Metadata<:loaded, "settings">,
   children: #Ecto.Association.NotLoaded<association :children is not loaded>,
   id: 4,
   inserted_at: ~N[2018-08-17 07:53:23.000000],
   keyname: "an_example",
   name: "Display Breadcrumb",
   parent: #Ecto.Association.NotLoaded<association :parent is not loaded>,
   parent_id: 2,
   updated_at: ~N[2018-08-17 10:29:46.707878]
 }}

Based of the quoted answer at the start you can probably notice that at the very least the inserted_at: ... and updated_at: ... are going to be different meaning the test will always fail.

Is there anything that can be done or even any workaround?

shmink
  • 189
  • 1
  • 3
  • 12

1 Answers1

0

You should put the documentation on what %Elements.Setting{} is to where it belongs (the module that defines this struct,) and stick to matching what you just explicitly set:

iex> example = Setting.get(id: 4)
iex> with {:ok, %Setting{} = result} <- Setting.update(example, %{keyname: "an_example"}),
...>   do: result.keyname == "an_example"
true

The values you want to show are test-specific and very misleading for anybody who is supposed to read the documentation.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • What makes the documentation misleading to read? I'm showing how the function works. – shmink Aug 17 '18 at 11:25
  • All these `id=4` etc are implementation details and should be described where they belong. To show how it works, the code above is perfectly enough: it shows it returns `{:ok, %Setting{}}` tuple with a new value assigned to the respective key of the struct. – Aleksei Matiushkin Aug 17 '18 at 11:43
  • For instance, showing `name: "Display Breadcrumb"` is quite misleading. I am puzzled: is it hardcoded? Where it came from? Is it a default value? Why?! – Aleksei Matiushkin Aug 17 '18 at 11:46
  • It's just a random database filled with some values I could expect. – shmink Aug 17 '18 at 13:08