8

问题

我想测试一个Elixir模块,它与主机系统交互并且有副作用的方法。对于这个问题并保持简短,假定它是创建几个目录。这些目录当然应该在运行测试后被删除,并且如果测试(很长)会因为任何原因(错误的模块代码,错误的测试代码等)而失败。Elixir/ExUnit:将测试用例的上下文传递给拆卸/清除方法(on_exit)是可能的吗?

我想知道如何最好/最优雅地解决这个清理步骤。我查看了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)更新的上下文:这似乎工作,但我无法确定它是否被推荐,并且它在测试(开始/结束)内的位置有所不同。
  • setup context函数中调用on_exit(fn -> cleanup(context) end):文档执行此操作,但我不知道如何将任何新的状态/上下文传递给它。它似乎只在所有上下文已经在设置功能中完全定义时才有用。

也许我也在试图解决这个问题......我只是因为不完整的清理和导致的无尽的递归(应该被我的代码捕获,但还没有),所以我只是想要一些不好的调试经验确保我做正确的事情并以正确的方式学习它。除了那些测试,Elixir迄今为止是一个非常愉快和完美的体验!

回答

1

在这种特殊情况下,我只需在您的设置功能(您的第三种解决方案)中注册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作为基本目录中你的测试

相关问题