テスト時に利用するfixture()
でいくつかのパターンのデータを定義したい
- RailsにおけるFactoryBotのTraitsのイメージ
- どこかにありそうだけど、手元でやってみる
利用イメージ
user_fixture([:japanese])
user_fixture(email: "test@example.com")
user_fixture([:japanese, email: "test@example.com"])
user_fixture([:japanese, :male, email: "test@example.com"])
実装
test/support/data_trait.ex
- 各fixtureモジュールで
use
できるようにモジュールを定義 - 引数を再帰的に処理する
- Atomなら
_trait
に引き渡す。このatomに相当する処理を各fixtureモジュール側に実装する - List(
[{:email, "test@example.com}]
)なら、マージしてしまう
- Atomなら
defmodule DataTrait do
def trait do
quote do
defp trait(obj, []), do: obj
defp trait(obj, [head | tail]) when is_atom(head) do
_trait(obj, head) |> trait(tail)
end
defp trait(obj, list) do
obj
|> Map.merge(Map.new(list))
end
defp _trait(obj, :touch), do: obj
end
end
defmacro __using__([]) do
apply(__MODULE__, :trait, [])
end
end
test/support/fixtures/user_fixtures.ex
- 対応する
_trait()
を実装する
defmodule UsersFixtures do
use DataTrait
def user_fixture(traits \\ []) do
%User{}
|> trait(traits)
|> Repo.insert!()
end
defp _trait(user, :japanese),
do: Map.put(user, :language, "japanese")
defp _trait(user, :male),
do: Map.put(user, :sex, "male")
end
結論
- 複雑なものだと辛そうではあるが、基本的なパターンなら問題なさそう(かな)
- 複雑な準備は
user_fixture()
ではなくuser_hoge_fixture()
みたいにするからいいかな、たぶん…