1 minute read

tags

Programming Phoenix 1.4 책에서 태그를 정의해 setup/2 함수 인자로 넘기는 테스트 코드를 봤다. 저걸 몰라서 셋업 인자를 다르게 할 일이 있으면 함수를 추출해 테스트 코드에서 호출했다. 책에서 태그를 활용하는 방법을 배웠다.

defmodule InfoSysTest.CacheTest do
  use ExUnit.Case, async: true
  @moduletag clear_interval: 100 # <-- 1

  setup %{test: name, clear_interval: clear_interval} do # <-- 2
    {:ok, pid} = Cache.start_link(name: name, clear_interval: clear_interval)
    {:ok, name: name, pid: pid}
  end

  test "clears all entries after clear interval", %{name: name} do # <-- 3
    assert :ok = Cache.put(name, :key1, :value1)
    assert Cache.fetch(name, :key1) == {:ok, :value1}
    assert eventually(fn -> Cache.fetch(name, :key1) == :error end)
  end

  @tag clear_interval: 60_000 # <-- 4
  test "values are cleaned up on exit", %{name: name, pid: pid} do # <-- 5
    assert :ok = Cache.put(name, :key1, :value1)
    assert_shutdown(pid)
    {:ok, _cache} = Cache.start_link(name: name)
    assert Cache.fetch(name, :key1) == :error
  end
end

2번 코드에서 test, clear_interval 키와 값을 인자로 받는다. test 키는 known tags로 ExUnit 모듈에서 ExUnit.Callbacks.setup/2 함수를 호출할 때, 넣어준다. 그럼 clear_interval 키와 값은 어디에서 넣는 걸까?

ExUnit.Callbacks.setup/2 함수를 호출할 때, 태그를 읽어서 같이 넘긴다. 1번 코드로 정의한 clear_interval 태그가 인자로 넘어간다. 이 값을 다른 테스트에서 바꾸려면 어떻게 하면 될까? 4번 코드처럼 같은 이름으로 태그를 정의하면 된다. 그러면 5번 테스트를 실행할 때는 clear_interval 값으로 100이 아닌 60,000을 사용한다. 반면 태그를 정의하지 않은 3번 코드에선 1번 코드에 정의한 100을 사용한다.

만약 setup 인자를 바꿀 방법이 없다면 어떻게 하면 될까?

test "values are cleaned up on exit", %{test: name} do
  %{pid: pid} = start_cache(name, 60_000)

  assert :ok = Cache.put(name, :key1, :value1)
  assert_shutdown(pid)
  {:ok, _cache} = Cache.start_link(name: name)
  assert Cache.fetch(name, :key1) == :error
end

defp start_cache(name, clear_interval) do
  {:ok, pid} = Cache.start_link(name: name, clear_interval: clear_interval)
  {name: name, pid: pid}
end

테스트에서 clear_interval 값을 다르게 하려면 start_cache/2 함수를 만들어서 호출해야 한다. setup/2 함수에서 호출하는 걸 start_cache/2 함수로 추출했으니 setup/2 함수는 제거한다. 테스트 케이스마다 셋업 코드가 늘어서 읽기가 힘들어지고 관리 비용 또한 상승한다.

태그를 읽어서 setup/2 함수 인자로 넘기는 건 훌륭한 결정이다. 이 결정 때문에 테스트 케이스에 값 좀 바꾼다고 setup/2 함수에 있는 코드를 덜어내거나 할 필요가 없다. 테스트 코드와 셋업 코드 분리가 더 용이해졌다.