添加设置以测试elixir

时间:2017-01-03 17:55:36

标签: elixir phoenix-framework

看起来Exunit为设置块https://hexdocs.pm/ex_unit/ExUnit.Callbacks.html提供了回调。我很好奇如何使用小袋鼠功能测试。在测试集成测试时,我基本上是在每个场景中创建用户。我基本上想要提取样板代码并将其用于我编写的每个测试。这是我目前的集成测试设置。

    test "a user can create a location", %{session: session} do
    assert session
      |> visit("/users")
      |> click_link("Create new account")
      |> fill_in("Name", with: "Billy Joel")
      |> fill_in("Email", with: "billy@example.com")
      |> fill_in("Password", with: "password")
      |> click_on("Create new user")
      |> click_link("New Project")
      |> fill_in("Name", with: "Senior Class Air Quality")
      |> click_on("Submit")
      |> click_link("Senior Class Air Quality")
      |> click_link("New Location")
      |> click_on("Submit")
      |> find(".alert-danger p")
      |> text == "Oops, something went wrong! Please check the errors below."

    assert session
      |> fill_in("Name", with: "A new location")
      |> select("Type", option: "office")
      |> click_on("Submit")
      |> find(".alert-info")
      |> text == "Location created successfully."

    assert session
      |> find("td", count: 3)
      |> List.first
      |> text == "A new location"
  end

  test "a user can edit a location", %{session: session} do
    project = Factory.project()
    Factory.location(%{project_id: project.id})

    assert session
      |> visit("/users")
      |> click_link("Create new account")
      |> fill_in("Name", with: "Billy Joel")
      |> fill_in("Email", with: "billy@example.com")
      |> fill_in("Password", with: "password")
      |> click_on("Create new user")
      |> click_link("New Project")
      |> fill_in("Name", with: "Senior Class Air Quality")
      |> click_on("Submit")
      |> click_link("Senior Class Air Quality")
      |> click_link("New Location")
      |> fill_in("Name", with: "A new location")
      |> select("Type", option: "office")
      |> click_on("Submit")
      |> click_link("Edit location")
      |> fill_in("Name", with: "different name")
      |> select("Type", option: "home")
      |> click_on("Submit")
      |> find(".alert-info")
      |> text == "Location updated successfully."

那里有很多重复。如何使用设置块来合并部分代码?

1 个答案:

答案 0 :(得分:1)

setupsetup_all函数为模块中的所有测试运行完全相同的设置代码,如果您需要为所有测试执行完全相同的设置,它们是最有用的。这方面的一个例子是设置应用程序所依赖的模拟服务。

在您的情况下,您似乎有一些相同的步骤,但是当您添加更多测试时,并不一定会为所有测试添加常见设置。但是,您可以将测试组成的各个概念步骤重构为一个单独的模块,您将在所有集成测试中使用该模块:

defmodule TestHelpers do
  # wallaby imports here

  def create_user(session, name, email, password) do
    session
      |> visit("/users")
      |> click_link("Create new account")
      |> fill_in("Name", with: name)
      |> fill_in("Email", with: email)
      |> fill_in("Password", with: password)
      |> click_on("Create new user")
  end

  def create_project(session, name) do
    session
      |> click_link("New Project")
      |> fill_in("Name", with: name)
      |> click_on("Submit")
  end

  def create_location(session, type), do: _modify_location("New Location", session, type, name)

  def edit_location(session, type), do: _modify_location("Edit location", session, type, name)

  defp _modify_location(link_text, session, location_type, location_name) do
    session = session
      |> click_link(link_text)

    session = case location_name do
      nil -> session
      x when is_binary(x) -> fill_in(session, "Name", with: location_name)
    end

    session = case location_type do
      nil -> session
      x when is_binary(x) -> select(session, "Type", option: location_type)
    end

    session
      |> click_on("Submit")
  end
end

现在测试只包含TestHelpers中定义的助手和断言:

defmodule Test do
  import TestHelpers

  @project_name "Senior Class Air Quality"

  # aliases, uses, imports here
  test "a user can create a location", %{session: session} do
    session = session
      |> create_user("Billy Joel", "billy@example.com", "password")
      |> create_project(@project_name)
      |> click_link(@project_name)
      |> create_location(nil, nil)

    assert session
      |> find(".alert-danger p")
      |> text == "Oops, something went wrong! Please check the errors below."

    session = session
      |> create_location("A new location", "office")

    assert session
      |> find(".alert-info")
      |> text == "Location created successfully."

    assert session
      |> find("td", count: 3)
      |> List.first
      |> text == "A new location"
  end

  test "a user can edit a location", %{session: session} do
    project = Factory.project()
    Factory.location(%{project_id: project.id})

    session = session
      |> create_user("Billy Joel", "billy@example.com", "password")
      |> create_project(@project_name)
      |> click_link(@project_name)
      |> create_location("office", "A new location")
      |> modify_location("home", "different_name")

    assert session
      |> find(".alert-info")
      |> text == "Location updated successfully."
  end
end

您也可以类似地提取警报消息断言,将它们转换为单行,这应该使每个测试都具有可读性和健壮性,例如,如果链接文本或div类发生更改 - 您只会帮助改变帮助。

当然,如果你发现自己在测试中有重复的多步骤设置,你可以将它作为辅助函数直接使用它:

def standard_setup(session) do
  session
    |> create_user("Billy Joel", "billy@example.com", "password"
    |> create_project(@project_name)
    |> click_link(@project_name)
    |> create_location("office", "A new location")
end