13
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ElixirAdvent Calendar 2023

Day 4

Testの書き方 LiveView編

Last updated at Posted at 2023-11-07

Testの書き方 LiveView編

LiveViewのテストモジュールは、以下の手順で定義することができる。

  • テストモジュールに必要なモジュールをインポートする。
  • セットアップ関数を定義する。
  • テストを記述する。

モジュールのインポート

LiveViewのテストモジュールを定義するためには、最低限以下の記述を必要とする。

  • use 省略Web.ConnCase
  • import Phoenix.LiveViewTest

これらは、Phoenixの接続のテストとLiveViewのテストを行えるようにするものである。

セットアップ関数の定義

LiveViewではライフサイクルにデータを追加することができる(socket.assigns)。

このデータ込みのテストを作成するためには、
テストを初期化するセットアップ関数を定義する必要がある。

セットアップ関数は次のように定義することができる。

# セットアップ関数を定義
defp init_data(_) do
  %{name: "Taro"}
end

セットアップ関数は次のように、テストに指定することができる。

describe "Test HomeLive.Index" do
  # describe別にsetup関数を指定することができる
  setup [:init_data]

  # セットアップ関数の戻り値のマップにあるものが指定できる
  test "home page", %{conn: conn, name: name} do

  end
end

またsetup_allマクロを使用することで、モジュール内のすべてのテストの初期化処理を行うことができる。

次のように記述する。

setup_all do
  # 初期化処理
end

これらの実行順は次のようになる。

  1. setup_allマクロ
  2. セットアップ関数

よってテスト全体に適用したい初期化処理setup_allマクロに、テストごとの初期化処理セットアップ関数で行うと良い。

データが異なる場合のセットアップ関数

データの値が特定の状態のときのLiveViewをテストしたい場合、
複数セットアップ関数を用意するとよい。

defp when_name(_) do
  %{name: "Taro", age: nil, from: nil}
end
defp when_age(_) do
  %{name: "Taro", age: 34, from: nil}
end
defp when_from(_) do
  %{name: "Taro", age: 34, from: "north pole"}
end

Testを実行する

LiveViewをテストする際には、LiveViewのプロセスを生成する必要がある。
次のように記述することで、LiveViewのプロセスを生成することができる。

{:ok, live_view, html} = live(conn, ~p"ルート")

出力されるlive_viewLiveViewの状態であり、htmlレンダリングされたHTMLである

LiveComponentの表示は次のようにテストすることができる。

# 出力されるHTMLからテスト
assert html =~ "テキスト"
# 特定のLiveComponentからの出力に絞ってテスト
assert render_component(LiveComponentモジュール, データatom: データ) =~ "テキスト"

** (KeyError) key :myself not found

LiveConponent内でイベントの送信先をLiveComponent自身(phx-target={@myself})としている場合、次のエラーが表示される。

** (KeyError) key :myself not found 以下省略

このような場合のTestでは、render_componentでid: "LiveComponentに指定したid"を渡すことで解決する。

assert render_component(LiveComponentモジュール, id: "LiveComponentに指定したid", データatom: データ) =~ "テキスト"

結論

LiveViewのテストを定義する場合、概ね次の手順に沿って記述する。

  • LiveViewのテストモジュールをインポートする(ConnCasePhoenix.LiveViewTest)
  • setup_allマクロですべてのテストで共通の初期化を記述する。
  • セットアップ関数を定義して、各describeにまとめられたテストで実行させる。(setup [:セットアップ関数])
  • test内でLiveViewプロセスを生成する。(live(conn, ~p"ルート"))
  • assertで比較を行う。

LiveViewのテストは、処理ごとに細かくdescribeで分け、結果ごとにtestを定義したほうがよいと思った。

おまけ

テスト実行後の処理

セットアップ関数やsetup_allマクロ、テストでの実行後の処理は、
on_exitコールバックで記述することができる。

on_exit(fn ->
  # テスト後の処理
end)

例としてsetup_allマクロで、on_exitを記述すると次のようになる。

setup_all do
  # テスト実行前にディレクトリとファイルを生成した
  :ok = File.mkdir("TEST_DIR")
  :ok = File.touch("TEST/TEXT.txt")


  on_exit(fn ->
    {:ok, ["TEST_DIR", "TEST_DIR/TEXT.txt"]} = FILE.rm_ref("TEST_DIR")
  end)
end

要素をクリックした後の表示をテスト

要素をクリックしたときの動作のテストを記述する場合、render_click(要素)を使用する。

またこの際、指定した要素がイベント処理によって状態(socket内のデータ)を更新する場合、render(状態)を実行すると
状態の更新後の表示をテストすることができる。

{:ok, live_view, _html} = live(conn, ~p"/")

live_view
|> element("li",  "イベント名もしくはphx-value-*の値")
|> render_click() =~ "内容"

# 状態の更新後をテスト
assert render(live_view) =~ "内容"

要素を指定するelement/2の引数は次のものを指定する。

  • 第一引数 - タグの種類を指定する。(buttonliなど)
  • 第二引数 - phx-clickのイベント名やphx-value-*で指定した値などを指定する。

クリックした要素にphx-clickが記述されていればイベントが送信され、要素が<.link pacth={~p"ルート"}>であればパッチ処理が行われる。

つまりLiveViewのページでクリックをしたときと同じ処理が行われる。

次のものはli要素をクリックすることで、
LiveComponentの表示が更新されたことをテストするものである。

# このセットアップ関数は%{selected: nil}を返す
setup [:when_not_selected_exists]

test "Click list", %{conn: conn, selected: selected} do
  {:ok, live_view, _html} = live(conn, ~p"/")

  # <li phx-value-name="TEST" phx-click="select_li"> という要素があるものとする
  
  # "select_li"イベントは、phx-value-*で指定した値%{"name" => name}を受け取り
  # selectedの値をname(つまり"TEST")に更新するものとする

  live_view
  # すべてのliの内、"TEST"とphx-valueのnameと一致するもの
  |> element("li", "TEST")
  # この時点でtest時に指定したselectedの値は、イベント処理によって
  # nilから"TEST"となっている
  # LiveViewの要素(LiveComponent込み)内に"test.pub"というテキストが存在するかテストすることができた。
  |> render_click() =~ "test.pub" 
end

navigateとパッチの処理をテスト

要素をクリック後、navigate処理が行われたをしたことをテストする場合

assert_redirected(live_view, ~p"/new")

要素をクリック後、パッチ処理が行われたことをテストする場合

assert_patched(live_view, ~p"/import_form")

テスト名

定義例

  • Test that 要素 be 動詞ed. - 特定の要素をテストする場合(Test that selected directory file are listed.等)
  • Test 対象 when 条件. - 条件を満たすとき対象をテストする場合(Test page when selected is nil.)
13
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?