Testing 长生不老药-测试完整脚本

Testing 长生不老药-测试完整脚本,testing,pattern-matching,elixir,phoenix-framework,gen-server,Testing,Pattern Matching,Elixir,Phoenix Framework,Gen Server,我正在编写一个测试来检查一个函数(当新文件进入文件夹时由GenServer自动调用),该函数使用管道调用同一模块中的其他函数,以便读取文件,处理其内容以插入文件(如果需要),并返回一个列表(:errors and:ok maps) 结果如下: [ error: "Data not found", ok: %MyModule{ field1: field1data, field2: field2data

我正在编写一个测试来检查一个函数(当新文件进入文件夹时由GenServer自动调用),该函数使用管道调用同一模块中的其他函数,以便读取文件,处理其内容以插入文件(如果需要),并返回一个列表(:errors and:ok maps)

结果如下:

[
          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
def processFile(文件)do
insertResultsMap=
File.read!(档案)
|>getLines()
|>extractMainData()
|>枚举映射(fn(x)->插入行(x)结束)
|>枚举分组依据(fn x->elem(x,0)结束)
handleErrors(Map.get(insertResultsMap,:error))
updateAnotherTableWithLines(Map.get(insertResultsMap,:ok))
终止
defp getLines(docContent)do
String.split(docContent,“\n”)
终止
defp extractMainData(文档行)do
Enum.map(fn(x)->String.split(x,“,”)结束)
终止
defp插入行([field1,field2,field3,field4])do
属性=%{
字段1:字符串修剪(字段1),
字段2:字符串修剪(字段2),
字段3:字符串修剪(字段3),
字段4:字符串修剪(字段4)
}
mymodule.create_stuff(属性)
终止
defp句柄错误(错误)do
{:ok,file}=file.open(@errorsFile,[:append])
保存错误(文件、错误)
文件。关闭(文件)
终止
defp saveErrors(_,[]),do::ok
defp saveErrors(文件,[{:error,changeset}| rest])do
changes=for{key,value}otherModule.doStuff(dataForUpdate.field1,dataForUpdate.field2)
终止
我有几个问题,其中一些问题很基本,因为我还在学习:

  • 你觉得代码怎么样?有什么建议吗?(考虑到我自愿混淆的名字)
  • 如果我想测试这一点,只测试
    processFile
    函数是否正确?或者我应该公开更多,并单独测试它们
  • 当我测试
    processFile
    函数时,我会检查是否收到一个列表。是否有任何方法可以确保此列表中只有我正在等待的元素,因此
    错误:“String”
    确定:%{}
你觉得代码怎么样?有什么建议吗?(考虑到我自愿混淆的名字)

基于意见

如果我想测试这个,只测试processFile函数是否正确

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

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

当我测试processFile函数时,我会检查是否收到了一个列表。是否有任何方法可以确保这个列表中只有我正在等待的元素,从而出现错误:“String”或ok:%{}

您将收到一个
关键字
。要检查显式值,可以使用:

foo = processFile(file)
assert not is_nil(foo[:ok])
OTOH,我最好从那里返回一张地图并匹配它:

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

要断言结果没有为
:ok
s和
:error
s保存的任何内容,可以使用列表减法:

assert Enum.uniq(Keyword.keys(result)) -- [:ok, :error] == []

嘿,谢谢你的帮助。移动到地图会删除重复的关键点,不是吗?另外,我不想测试返回的
关键字
实际上包含任何
:ok
元组,而是它不包含意外的内容-除了
:ok
:error
元组。1。是的,如果您需要重复的密钥,
关键字
是最佳选择。2.然后简单地断言
关键字.keys(result)-~w | ok error | a=[]
。这不起作用-根据文档定义“为右侧的每个项目删除左侧列表中第一个出现的项目”-只删除第一个!若要删除所有出现的
:ok
:error
,它将不起作用。转换为
地图集将删除某些元素。。。但是,我可以转换成一个映射并绑定到一个新变量,以便只检查预期元素的键是否在这里,而不依赖这个新变量做任何其他事情:)再次感谢