Эликсир - тестирование полного скрипта

Я пишу тест для проверки функции (автоматически вызываемой GenServer, когда новый файл попадает в папку), которая вызывает другие функции в том же модуле с каналами для чтения файла, обработки его содержимого, чтобы вставить его, если необходимо, и возврата список (: ошибки и: ok карты).

результаты выглядят так:

[
          error: "Data not found",
          ok: %MyModule{
            field1: field1data,
            field2: field2data
          },
          ok: %MyModule{
            field1: field1data,
            field2: field2data
          },
          error: "Data not found"

код :

  def processFile(file) do
    insertResultsMap =
      File.read!(file)
      |> getLines()
      |> extractMainData()
      |> Enum.map(fn(x) -> insertLines(x) end)
      |> Enum.group_by(fn x -> elem(x, 0) end)

    handleErrors(Map.get(insertResultsMap, :error))
    updateAnotherTableWithLines(Map.get(insertResultsMap, :ok))
  end

  defp getLines(docContent) do
    String.split(docContent, "\n")
  end

  defp extractMainData(docLines) do
    Enum.map(fn(x) -> String.split(x, ",") end)
  end

  defp insertLines([field1, field2, field3, field4]) do
    Attrs =  %{
      field1: String.trim(field1),
      field2: String.trim(field2),
      field3: String.trim(field3),
      field4: String.trim(field4)
    }

    mymodule.create_stuff(Attrs)
  end

  defp handleErrors(errors) do
    {:ok, file} = File.open(@errorsFile, [:append])
    saveErrors(file, errors)
    File.close(file)
  end

  defp saveErrors(_, []), do: :ok
  defp saveErrors(file, [{:error, changeset}|rest]) do
    changes = for {key, value} <- changeset.changes do
      "#{key} #{value}"
    end
    errors = for {key, {message, _}} <- changeset.errors do
      "#{key} #{message}"
    end

    errorData = "data: #{Enum.join(changes, ", ")} \nErrors: #{Enum.join(errors, ", ")}\n\n"

    IO.binwrite(file, errorData)
    saveErrors(file, rest)
  end

  defp updateAnotherTableWithLines(insertedLines) do
    Enum.map(insertedLines, fn {:ok, x} -> updateOtherTable(x) end)
  end

  defp updateOtherTable(dataForUpdate) do
    "CLOSE" -> otherModule.doStuff(dataForUpdate.field1, dataForUpdate.field2)
  end

У меня есть несколько вопросов, некоторые из них будут довольно простыми, поскольку я все еще учусь:

  • Что вы думаете о коде? Какие-нибудь советы? (учтите, что я добровольно запутал имена).
  • Если я хочу это проверить, правильно ли это проверять только processFile функцию? Или я должен сделать больше из них и протестировать их индивидуально?
  • Когда я тестирую функцию processFile, я проверяю, что получаю список. Есть ли способ убедиться, что в этом списке есть только элементы, которых я жду, например error: "String" или ok: %{} "?

person Jeremy Belolo    schedule 19.11.2018    source источник


Ответы (1)


Что вы думаете о коде? Какие-нибудь советы? (учтите, что я добровольно запутал имена).

Основано на мнении.

Если я хочу это проверить, правильно ли это проверять только функцию processFile?

да.

Или я должен сделать больше из них и протестировать их индивидуально?

Нет, это деталь реализации, а тестирование - антипаттерн.

Когда я тестирую функцию processFile, я проверяю, что получаю список. Любой способ убедиться, что в этом списке есть только элементы, которых я жду, например, ошибка: "String" или ok:% {} "?

Вы получите Keyword. Чтобы проверить явное значение, можно использовать:

foo = processFile(file)
assert not is_nil(foo[:ok])

OTOH, мне лучше вернуть карту оттуда и сопоставить ее с шаблоном:

assert %{ok: _} = processFile(file)

Чтобы утверждать, что результат не имеет ничего, кроме :oks и :errors, можно использовать вычитание списка:

assert Enum.uniq(Keyword.keys(result)) -- [:ok, :error] == []
person Aleksei Matiushkin    schedule 19.11.2018
comment
Привет, спасибо за помощь. Перемещение к карте приведет к удалению повторяющихся ключей, не так ли? Кроме того, я не хочу проверять, что возвращенный keyword на самом деле содержит какой-либо :ok кортеж, а скорее, что он не содержит ничего неожиданного, кроме кортежей :ok и :error. - person Jeremy Belolo; 19.11.2018
comment
1. Да, если вам нужны повторяющиеся ключи, Keyword - это то, что вам нужно. 2. Затем просто подтвердите Keyword.keys(result) -- ~w|ok error|a == []. - person Aleksei Matiushkin; 19.11.2018
comment
Это не сработает - согласно doc def Удаляет первое вхождение элемента в левом списке для каждого элемента справа - только первое! Удалить все вхождения :ok и :error не получится. Преобразование в MapSet приведет к удалению некоторых элементов ... Но тогда я мог бы преобразовать в карту и привязать к новой переменной, чтобы проверить, находятся ли здесь только ключи ожидаемых элементов, не полагаясь на эту новую переменную ни для чего другого :) Спасибо снова - person Jeremy Belolo; 20.11.2018