如何使用 Capybara & Minitest 测试多步表单?

How can I test multistep forms with Capybara & Minitest?

我有一个具有多步骤 form/wizard 界面的单页 Sinatra 应用程序。如果我想用 Capybara 测试表格,是否需要为每个测试重复所有步骤?我希望避免这样的事情:

it "visits the home page" do 
  vist "/"
  page.should have_content('foo')
end

it "clicks the first button" do 
  vist "/"
  page.should have_content('foo')
  button_click("Next")
end

it "clicks the second button" do 
  vist "/"
  page.should have_content('foo')
  button_click("Next")
  page.should_have_content('bar')
end

it "clicks the third button" do 
  vist "/"
  page.should have_content('foo')
  button_click("Next")
  page.should_have_content('bar')
  button_click("Next")
end

我找到了一篇关于 nested tests using RSpec and Capybara 的文章,但未能获得与 Minitest 一起使用的类似技术。

我已经为您做了一些调查,我将与您分享我的发现。

为此,您应该考虑 "converting" 您的 Minitest 测试到 specs。这使您可以访问类似的语法,如 RSpec 的 - describe 具有嵌套它们的能力。

我将简化代码以提供示例,但应该清楚将您的逻辑放在哪里。

让我们检查几个例子。

1).让我们对 Array:

做一些简单的测试
require "minitest/autorun"

describe Array do
  before do
    @arr = []
  end

  describe "when initialized" do
    it "is empty" do
      @arr.length.must_equal 0
    end
  end
end

这应该过去了,这里没什么特别的。

2).让我们添加另一个 describe,嵌套到我们已有的一个:

describe Array do
  before do
    @arr = []
  end

  describe "when initialized" do
    it "is empty" do
      @arr.length.must_equal 0
    end

    describe "when element added" do
      it "length reflects the change" do
        @arr << "a"
        @arr.length.must_equal 1
      end
    end
  end
end

这也有效 - 一个元素已添加到数组中,其 length 表示正确。

3).让我们尝试嵌套另一个块。我们希望 @arr << "a" 将被保留,所以如果我们添加另一个元素,@arr.length 将为 2。让我们看看:

describe Array do
  before do
    @arr = []
  end

  describe "when initialized" do
    it "is empty" do
      @arr.length.must_equal 0
    end

    describe "when element added" do
      it "length reflects the change" do
        @arr << "a"
        @arr.length.must_equal 1
      end

      describe "when another element added" do
        it "length also reflects the change" do
          @arr << "b"
          p @arr
          @arr.length.must_equal 2
        end
      end
    end
  end
end

describe 嵌套在另一个 describe - 中,就像我们对 RSpec 所做的那样,但不幸的是,结果似乎是@arr << "a"不保留,嵌套describe@arr.length也是1.

我在代码中留下了 p @arr,因此您可以在控制台中轻松查看当前存储在 @arr 中的内容。

绝对不是我们所期望的...让我们尝试一些疯狂 然后...

4).让我们将 describe 嵌套在... it:

describe Array do
  before do
    @arr = []
  end

  describe "when initialized" do
    it "is empty" do
      @arr.length.must_equal 0
    end

    describe "when element added" do
      it "length reflects the change" do
        @arr << "a"
        @arr.length.must_equal 1

        describe "when another element added" do
          it "length also reflects the change" do
            @arr << "b"
            p @arr
            @arr.length.must_equal 2
          end
        end
      end
    end
  end
end

好吧,事实证明,这是完全有效的,而且它的行为完全符合我们的预期! (同样,p @arr 留在此处,以便您在控制台中检查当前存储在 @arr 中的内容)。

老实说 - 我没有用 Capybara 检查,但这个简单的例子很有前途。尝试相应地修改您的代码,以便在您的规范中实现 Capybara 交互。

让我明确提供的解决方案:我再次强烈建议这种方法:

  • 像这样的规范很难阅读,因此也很难维护。
  • 这被认为是错误的模式。 下一步 步骤不应 依赖于先前 步骤的结果。

如果你想正确地测试你的控制器,你应该尝试类似的东西(这是伪代码只是为了说明想法):

测试步骤 1

post "/url-to-my-form", { params_step_1: { ... } }

测试步骤 2

post "/url-to-my-form", { params_step_1: { ... }, params_step_2: { ... } }

使用这种方法很容易看出 params 是什么 posted,因此更容易针对 eg 进行测试。违反任何规则(空值、无效电子邮件等)。

希望对您有所帮助!祝你好运!