Написание doctests при возврате структуры

Ответ на аналогичный вопрос содержит этот вопрос.

Чтобы протестировать функцию с помощью doctests, вы должны быть в состоянии предсказать вывод вашей функции.

Проблема

Как упоминалось в заголовке, я хотел бы придерживаться использования doctests, но это, похоже, не работает, и я не верю, что это невозможно сделать.

Код

  @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

Выше приведен код, который я пробовал, и его варианты. Например, использование _, когда данные будут неожиданными. Просто биты, которые не изменились бы.

Например, в идеале я бы хотел, чтобы возвращаемое значение выглядело как {:ok, %Elements.Setting{keyname: "an_example", _}. Таким образом, документация проходит, но она также понятна для пользователей, что они читают, и могут видеть эффекты кода, который был до нее.

икс

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]
 }}

Основываясь на процитированном ответе в начале, вы, вероятно, можете заметить, что, по крайней мере, inserted_at: ... и updated_at: ... будут разными, что означает, что тест всегда будет терпеть неудачу.

Есть ли что-нибудь, что можно сделать или хотя бы обходной путь?


person shmink    schedule 17.08.2018    source источник


Ответы (1)


Вы должны поместить документацию о том, что такое %Elements.Setting{}, туда, где она принадлежит (модуль, который определяет эту структуру), и придерживаться соответствия тому, что вы только что явно установили:

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

Значения, которые вы хотите показать, зависят от теста и вводят в заблуждение любого, кто должен читать документацию.

person Aleksei Matiushkin    schedule 17.08.2018
comment
Что делает документацию вводящей в заблуждение? Я показываю, как работает функция. - person shmink; 17.08.2018
comment
Все эти id=4 и т. д. являются деталями реализации и должны быть описаны там, где они принадлежат. Чтобы показать, как это работает, приведенного выше кода вполне достаточно: он показывает, что возвращает кортеж {:ok, %Setting{}} с новым значением, присвоенным соответствующему ключу структуры. - person Aleksei Matiushkin; 17.08.2018
comment
Например, показ name: "Display Breadcrumb" вводит в заблуждение. Я озадачен: это жестко запрограммировано? Откуда оно взялось? Это значение по умолчанию? Почему?! - person Aleksei Matiushkin; 17.08.2018
comment
Это просто случайная база данных, заполненная некоторыми значениями, которые я мог ожидать. - person shmink; 17.08.2018