Elixir - 测试完整的脚本
Elixir - testing a full script
我正在编写一个测试来检查一个函数(当新文件进入文件夹时由 GenServer 自动调用),该函数使用管道调用同一模块中的其他函数以读取文件,处理其内容以插入如果需要它和 returns 一个列表(: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
功能是否正确?或者我应该制作更多 public 个并单独测试它们?
- 当我测试
processFile
函数时,我检查我是否收到了一个列表。有什么方法可以确保这个列表只有我正在等待的元素,因此 error: "String"
或 ok: %{}
" ?
What do you think of the code? Any advices? (take into account I voluntarily obfuscated names).
基于意见。
If I want to test this, is it the right way to test only processFile function?
是的。
Or should I make public more of them and test them individually?
不,这是一个实现细节,测试它是一个反模式。
When I test the processFile function, I check that I'm receiving a list. Any way to make sure this list has only elements I'm waiting for, thus error: "String" or ok: %{}"?
您收到 Keyword
。要检查显式值,可以使用:
foo = processFile(file)
assert not is_nil(foo[:ok])
OTOH,我最好 return 从那里制作一张地图并对其进行模式匹配:
assert %{ok: _} = processFile(file)
要断言结果除了 :ok
s 和 :error
s 之外没有任何东西,可以使用列表减法:
assert Enum.uniq(Keyword.keys(result)) -- [:ok, :error] == []
我正在编写一个测试来检查一个函数(当新文件进入文件夹时由 GenServer 自动调用),该函数使用管道调用同一模块中的其他函数以读取文件,处理其内容以插入如果需要它和 returns 一个列表(: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
功能是否正确?或者我应该制作更多 public 个并单独测试它们? - 当我测试
processFile
函数时,我检查我是否收到了一个列表。有什么方法可以确保这个列表只有我正在等待的元素,因此error: "String"
或ok: %{}
" ?
What do you think of the code? Any advices? (take into account I voluntarily obfuscated names).
基于意见。
If I want to test this, is it the right way to test only processFile function?
是的。
Or should I make public more of them and test them individually?
不,这是一个实现细节,测试它是一个反模式。
When I test the processFile function, I check that I'm receiving a list. Any way to make sure this list has only elements I'm waiting for, thus error: "String" or ok: %{}"?
您收到 Keyword
。要检查显式值,可以使用:
foo = processFile(file)
assert not is_nil(foo[:ok])
OTOH,我最好 return 从那里制作一张地图并对其进行模式匹配:
assert %{ok: _} = processFile(file)
要断言结果除了 :ok
s 和 :error
s 之外没有任何东西,可以使用列表减法:
assert Enum.uniq(Keyword.keys(result)) -- [:ok, :error] == []