【问题标题】:Elixir - testing a full scriptElixir - 测试一个完整的脚本
【发布时间】:2019-04-21 23:45:21
【问题描述】:

我正在编写一个测试来检查一个函数(当新文件进入文件夹时由 GenServer 自动调用),该函数使用管道调用同一模块中的其他函数以读取文件,处理其内容以插入它,如果需要并返回一个列表(:errors 和 :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: %{}"?

【问题讨论】:

    标签: testing pattern-matching elixir phoenix-framework gen-server


    【解决方案1】:

    你觉得这段代码怎么样?有什么建议吗? (考虑到我自愿混淆了名称)。

    基于意见。

    如果我想测试这个,只测试 processFile 函数是正确的方法吗?

    是的。

    或者我应该公开更多它们并单独测试它们?

    不,这是一个实现细节,测试它是一种反模式。

    当我测试 processFile 函数时,我会检查我是否收到了一个列表。有什么方法可以确保这个列表只有我正在等待的元素,因此错误:“字符串”或确定:%{}”?

    您会收到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] == []
    

    【讨论】:

    • 您好,感谢您的帮助。移动到地图会删除重复的键,不是吗?另外,我不想测试返回的keyword 实际上包含任何:ok 元组,而是它不包含意外的东西——除了:ok:error 元组。
    • 1.是的,如果您需要重复的密钥,Keyword 是您的最佳选择。 2. 然后简单地断言Keyword.keys(result) -- ~w|ok error|a == []
    • 这不起作用 - 根据 doc def "删除左侧列表中第一个出现的项目,为右侧的每个项目" - 只有第一个!要删除所有出现的:ok:error,它将不起作用。转换为MapSet 会删除一些元素...但是,我可以转换为映射并绑定到一个新变量,以便仅检查预期元素的键是否在这里,而无需依赖这个新变量来处理其他任何事情: ) 再次感谢
    猜你喜欢
    • 2016-04-12
    • 2019-11-20
    • 2020-05-15
    • 1970-01-01
    • 2018-09-20
    • 2021-05-31
    • 2012-02-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多