setup/teardown dets tables between each test in elixir?
Asked Answered
E

0

7

We are trying to run each test in a completely clean dets environment, and each test is responsible for its own setup. We're running into issues where we can not completely remove the directory between tests.

How can we reset dets? Did we incorrectly assume blowing away the entire directory and restarting the application was sufficient setup? Is it better to remove all records between runs?

Assume:

  • async: true is not set for any tests.
  • dets is required
  • The majority of answered code should (if at all possible) be in elixir, not erlang.

Example code:

setup do
  #clean up anything that wasn't already clean (failed teardown, etc)
  TestSetup.teardown_dets(:myappatom, "dets")

  on_exit fn ->
    TestSetup.teardown_dets(:myappatom, "dets")
    Application.ensure_all_started(:myappatom)
    Process.sleep(300)
  end
end

And the guts of the teardown function...

def teardown_dets(application_atom, directory) when is_bitstring(directory) do
  teardown_dets(application_atom, [directory])
end
def teardown_dets(application_atom, directories)
  when is_atom(application_atom) and is_list(directories)
do
  #stop the applications completely
  Application.stop(application_atom)

  #blow away all dets while the application is stopped
  try do
    directories
    |> Enum.map(&File.rm_rf(&1))
  rescue
    error in File.Error -> IO.puts("First file removal failure. Re-attempting.  Initial error information #{error.message}")
  after
      Process.sleep(3000) #wait for whatever it was to get out of the way

      directories
      |> Enum.map(&File.rm_rf!(&1))
  end

end

Example errors when running mix test are stdout showing:

dets: file "dets/event_listener_stream_positions_test" not properly closed, repairing ... but not as an error, just regular output to console.

And then an actual failure in the test: ** (File.Error) could not remove files and directories recursively from "dets": file already exists

Exequies answered 1/6, 2017 at 15:44 Comment(6)
(This would be way easier for us to debug if you could reproduce the error in a minimal new application.)Nightrider
I remove individual files between runs with :file.delete(...) and it works fine. If the directory is reused for dets during new runs anyway, you could just try deleting the files to find which one is causing the issue.Casie
Why not delete_all_objects(...)? it's supposed to be constant-timeWergild
@Wergild because deleting all objects would nuke other asynchronously running tests.Tocharian
@Tocharian Since the question text contains "Assume: async: true is not set for any tests", I don't think that would be a problem.Rosario
In some situations it can be useful to rely on the name of the test (available in the test context) as a unique name, e.g. test "something", %{test: test} do -- it might be an extreme strategy in this case, but it can be an effective way to isolate a test's side effects.Cockcrow

© 2022 - 2024 — McMap. All rights reserved.