capybara 2.0+中的嵌套功能

Nir*_*Nir 4 rspec capybara rspec-rails ruby-on-rails-3

我想做这样的事情:

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
Run Code Online (Sandbox Code Playgroud)

但是当我运行rspec时,我得到了

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

如果我改变它看起来像这样工作:

  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
Run Code Online (Sandbox Code Playgroud)

编辑:

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

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
Run Code Online (Sandbox Code Playgroud)

dei*_*vid 8

编辑(2014年2月23日):从2.2.1版开始提供嵌套功能.看到这里

编辑(2013年7月24日): Capybara> 2.1.0将允许嵌套功能.看到这里

你不能.这就是宝石的mantainer所说的

我想你可以称之为限制.feature不能嵌套.您可以使用其中任何一种,context或者使用它describe,但我建议不要使用它们,它往往会使测试变得难以理解.

在其他一些情况下,可能会讨论这种方便,但在这个特定的情况下,你应该使用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
Run Code Online (Sandbox Code Playgroud)

你必须删除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
Run Code Online (Sandbox Code Playgroud)

但只要规范检查它必须检查什么,你应该没事.其余的都是风格,可读性和良好实践,这些都很重要,但更容易讨论和分歧.在这种情况下,gem的作者不允许嵌套feature.也许是为了可读性或者可能不觉得它是需要的,或者可能没有想到它...如果你真的想要嵌套功能,你总是可以尝试实现它并拉取请求它.

  • 别客气.如果它有效,那本身就是一件好事.除此之外,你应该尝试坚持良好的做法,找到一种你认为可读的一致风格.例如,对一个案例使用describe而对另一个案例使用场景不一致也不可读.另一方面,我喜欢你如何在后台块中分离fill_in动作.但所有这些都是品味问题.[这里](http://betterspecs.org/)您可以找到一些推荐的rspec良好实践,您可以查看并选择您想要关注的实践. (2认同)