我想测试与主机系统交互的Elixir模块,并且具有副作用的方法。对于这个问题并保持简短,假设它是几个目录的创建。这些目录当然应该在运行测试后删除,如果测试(很长时间)由于任何原因(坏模块代码,错误的测试代码等)而失败。
我想知道如何最好/最优雅地解决这个清理步骤。我查看了ExUnit.Callbacks.on_exit/2的文档,但它的示例仅用于设置和简单拆解(不涉及传递状态)。我也在线搜索,但没有发现任何有用的东西,所以可能是我的想法本身并不好 - 我也愿意接受重构这个问题的建议。
defmodule SimpleTest do
use ExUnit.Case
setup_all do
ts = Time.utc_now |> Time.to_string
{:ok, [timestamp: ts]}
# paths to be cleaned are not yet known here
end
test "first test", context do
path = "/tmp/dir" <> context[:timestamp]
assert :ok == SimpleModule.mkdir(path)
assert :eexist == SimpleModule.mkdir(path)
# [path] should be passed on to cleanup
end
test "second test", context do
path = "/tmp/dir" <> context[:timestamp]
path2 = "/tmp/dir2" <> context[:timestamp]
SimpleModule.mkdir(path)
SimpleModule.mkdir(path2)
assert File.exists?(path)
assert File.exists?(path2)
# [path, path2] should be passed on to cleanup
end
defp cleanup(context) do
Enum.each(context[:dirs], fn(x) -> File.rmdir(x) end)
end
end
defmodule SimpleModule do
def mkdir(path) do
File.mkdir(path)
end
end
我现在想要在每次测试后添加一个对cleanup/1
的调用以及要删除的目录列表。以下想法是我尝试过的事情:
on_exit(fn -> cleanup(context) end)
更新的上下文:这似乎有效,但我无法确定是否推荐它,以及它是否会将调用置于测试内部(开始/结束) on_exit(fn -> cleanup(context) end)
函数中调用setup context
:文档执行此操作,但我不知道如何将任何新状态/上下文传递给它。只有在设置函数中已经完全定义了所有上下文时,它似乎才有用。也许我也在过度思考这个问题...我只是有一些糟糕的调试经验,不完全清理并导致无休止的递归(应该已经被我的代码捕获,但还没有),所以我只是想确保我做对了,并以正确的方式学习它。除了这些测试,到目前为止,Elixir是一个非常愉快和完美的体验!
答案 0 :(得分:2)
在这种特殊情况下,我只会在你的设置功能(你的第三个解决方案)中注册on_exit
回调。
不是单独删除路径,而是删除父目录:
@test_dir "/tmp/base_test"
setup do
File.mkdir(@test_dir)
on_exit fn ->
File.rm_rf @test_dir
end
end
然后在测试中使用@test_dir
作为基本目录
答案 1 :(得分:0)
您还可以在测试用例的内部 中注册要执行的回调,并将其传递给特定路径。
test "first test", context do
path = "/tmp/dir" <> context[:timestamp]
on_exit(fn -> cleanup(path) end)
assert :ok == SimpleModule.mkdir(path)
assert :eexist == SimpleModule.mkdir(path)
end
test "second test", context do
path = "/tmp/dir" <> context[:timestamp]
path2 = "/tmp/dir2" <> context[:timestamp]
SimpleModule.mkdir(path)
SimpleModule.mkdir(path2)
assert File.exists?(path)
assert File.exists?(path2)
on_exit(fn -> cleanup(path) end)
on_exit(fn -> cleanup(path) end)
end
您可以在测试用例的任何时候注册它,它将在测试结束后执行。您也可以使用参考术语进行注册。
如ExUnit docs中所述:
on_exit / 2回调是按需注册的,通常撤消由设置回调执行的操作。 on_exit / 2也可以引用,以允许将来重写回调。已注册的on_exit / 2回调始终运行,而setup和setup_all的失败将阻止所有剩余的setup回调的执行。