💡

【Elixir】tmp_dirタグを使ってテスト用のtmpディレクトリをサクッと作成する

2022/02/09に公開

Elixirのv1.11からExUnitに @tmp_dir タグの設定が増えており、これを指定することでテストケースごとに一時ディレクトリを作ってくれます。

ファイル読み書き系のmoduleのテストを書きたいときに地味便利です。

defmodule MyTest do
  use ExUnit.Case, async: true

  @tag :tmp_dir
  test "with tmp_dir", %{tmp_dir: tmp_dir} do
    assert tmp_dir =~ "with tmp_dir"
    assert File.dir?(tmp_dir)
  end
end

https://hexdocs.pm/ex_unit/main/ExUnit.Case.html#module-tmp-dir

解説

公式ドキュメントを読むのが早いですが、一応解説してみます。

@tmp_dir タグを指定すると、mix projectの直下に tmp ディレクトリが作られ、テストコードのmoduleとtest case名に従ってフォルダが作成されます。

仮に次のようなpathのmix projectにいるとして、

$ pwd
/Users/koga/sample

次のようなテストコードを書いたとすると、

defmodule SampleTest do
  use ExUnit.Case
  doctest Sample

  @tag :tmp_dir
  test "tmp dir test", %{tmp_dir: tmp_dir} do
    IO.inspect(tmp_dir, label: "#{__MODULE__}:#{__ENV__.line} #{DateTime.utc_now}")
  end

  @tag tmp_dir: "mypath"
  test "other test", %{tmp_dir: tmp_dir} do
    IO.inspect(tmp_dir, label: "#{__MODULE__}:#{__ENV__.line} #{DateTime.utc_now}")
  end
end

テスト実行後、このような結果が得られます。

$ mix test
.Elixir.SampleTest:7 2022-02-09 14:33:44.086622Z: "/Users/koga/sample/tmp/SampleTest/test-tmp-dir-test"
.Elixir.SampleTest:12 2022-02-09 14:33:44.092065Z: "/Users/koga/sample/tmp/SampleTest/test-other-test/mypath"

tmp/<テストのmodule名><test case名>/<tmp_dirを明示的に指定したら追加されるディレクトリ> という構造になっていることがわかります。

sample # mix projectのroot
└── tmp
    └── SampleTest
        ├── test-other-test
        │   └── mypath
        └── test-tmp-dir-test
  • テストケースごとにディレクトリが作られるため、他のテストと衝突しない
    • async: true の時に大事
  • テストを開始するタイミングでディレクトリが再作成される[1]ため、毎回クリーンな状態でテストを行える
    • テスト実行時に初期化。終了後は作成したファイルなどは残っている

といった点がポイントです。

脚注
  1. https://github.com/elixir-lang/elixir/blob/79cd891eb86ecb7654a7acdb63769cfdd950a5c0/lib/ex_unit/lib/ex_unit/runner.ex#L392 あたりのコードを見ると分かりやすいです ↩︎

Discussion