5

我想做这样的事情:

feature "sign-up" do
  before {visit signup_path}
  let(:submit) {"Create my account"}

  feature "with invalid information" do
    scenario "should not create a user" do
      expect {click_button submit}.not_to change(User, :count)
    end
  end

  feature "with valid information" do
    scenario "should create a user" do
      fill_in "Name",         with: "test name"
      fill_in "Email",        with: "test@test.com"
      fill_in "Password",     with: "password"
      fill_in "Confirmation", with: "password"
      expect {click_button submit}.to change(User, :count).by(1)
    end
  end
end

但是当我运行 rspec 我得到

in `block in <top (required)>': undefined method `feature' for #<Class:0x000000039e0018> (NoMethodError)

如果我将其更改为如下所示,它可以工作:

  feature "with invalid information" do
    before {visit signup_path}
    let(:submit) {"Create my account"}

    scenario "should not create a user" do
      expect {click_button submit}.not_to change(User, :count)
    end
  end

  feature "with valid information" do
    before {visit signup_path}
    let(:submit) {"Create my account"}

    scenario "should create a user" do
      fill_in "Name",         with: "test name"
      fill_in "Email",        with: "test@test.com"
      fill_in "Password",     with: "nirnir"
      fill_in "Confirmation", with: "nirnir"
      expect {click_button submit}.to change(User, :count).by(1)
    end
  end

编辑:

另外,以下代码有效(描述嵌套内部功能) - 但它有任何错误吗?

feature "sign-up" do
  background {visit signup_path}
  given(:submit) {"Create my account"}

  scenario "with invalid information" do
    expect {click_button submit}.not_to change(User, :count)
  end

  describe "with valid information" do
    background do
      fill_in "Name",         with: "test name"
      fill_in "Email",        with: "test@test.com"
      fill_in "Password",     with: "password"
      fill_in "Confirmation", with: "password"
    end

    scenario { expect {click_button submit}.to change(User, :count).by(1) }

    scenario "after submission" do 
      click_button submit
      page.html.should have_content("Registration successful")
    end
  end
end
4

1 回答 1

8

编辑(23/01/2014):嵌套功能自 2.2.1 版起可用。看这里

编辑(24/07/2013): Capybara > 2.1.0 将允许嵌套功能。看这里

你不能。这就是宝石的管理员所说的

我想你可以称之为限制。feature不能嵌套。您可以使用其中一个contextdescribe代替,但我建议不要使用这些,它往往会使测试变得非常难以理解。

在其他一些情况下,可能会争论这样做的便利性,但在这个特定的情况下,您应该使用scenario而不是嵌套的feature.

此外,如果您想在任何地方保持一致并使用新的 DSL,请使用background代替beforegiven代替let. 像这样:

feature "sign-up" do
  background {visit signup_path}
  given(:submit) {"Create my account"}

  scenario "with invalid information" do
    expect {click_button submit}.not_to change(User, :count)
  end

  scenario "with valid information" do
    fill_in "Name",         with: "test name"
    fill_in "Email",        with: "test@test.com"
    fill_in "Password",     with: "password"
    fill_in "Confirmation", with: "password"
    expect {click_button submit}.to change(User, :count).by(1)
  end
end

您必须删除,it因为scenario它只是一个别名it,您也不​​能嵌套it

或者,如果您发现它更具可读性,您可以随时切换回旧的 DSL。在那种情况下,我会做这样的事情:

describe "sign-up" do
  before {visit signup_path}
  let(:submit) {"Create my account"}

  context "with invalid information" do
    it "does not create a user" do
      expect {click_button submit}.not_to change(User, :count)
    end
  end

  context "with valid information" do
    before
      fill_in "Name",         with: "test name"
      fill_in "Email",        with: "test@test.com"
      fill_in "Password",     with: "password"
      fill_in "Confirmation", with: "password"
    end
    it "creates a user" do
      expect {click_button submit}.to change(User, :count).by(1)
    end
  end

end

但只要规范检查它必须检查的内容,无论如何你应该没问题。其余的都是风格、可读性和良好实践的问题,这些都很重要,但更容易引起讨论和分歧。在这种情况下,gem 的作者不允许嵌套feature's。也许是为了可读性,或者可能觉得不需要它,或者可能没有考虑过......如果你真的想嵌套功能,你可以随时尝试实现它并请求它。

于 2013-03-06T17:11:15.467 回答