Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
rspec+;水豚:功能测试每个测试只有一个期望?_Rspec_Tdd_Capybara_Integration Testing - Fatal编程技术网

rspec+;水豚:功能测试每个测试只有一个期望?

rspec+;水豚:功能测试每个测试只有一个期望?,rspec,tdd,capybara,integration-testing,Rspec,Tdd,Capybara,Integration Testing,我正在使用rspec和capybara为我的Rails 4应用程序编写一些功能测试。我让它正常工作,但我正在努力理解这种测试方式的某些方面 我一直在读,每个测试(它“应该…”块)应该只测试一件事。好的,听起来不错,但当我把它付诸实践时,我最终为简单的事情编写了大量的测试 比如说,我有一个标准的注册表单,它包含电子邮件、密码和信用卡 所以,为我的注册写一个功能测试,我需要写3个单独的测试来测试这个功能吗 describe "Signup" do it "informs user of an i

我正在使用rspec和capybara为我的Rails 4应用程序编写一些功能测试。我让它正常工作,但我正在努力理解这种测试方式的某些方面

我一直在读,每个测试(它“应该…”块)应该只测试一件事。好的,听起来不错,但当我把它付诸实践时,我最终为简单的事情编写了大量的测试

比如说,我有一个标准的注册表单,它包含电子邮件、密码和信用卡

所以,为我的注册写一个功能测试,我需要写3个单独的测试来测试这个功能吗

describe "Signup" do
  it "informs user of an invalid email" do
    visit signups_path
    fill_in "Email", with: ""
    click_button "Signup"
    expect(page).to have_text("Email can't be blank")
  end
  it "informs user of an invalid password" do
    visit signups_path
    fill_in "Email", with: "test@test.com"
    fill_in "Password", with: ""
    click_button "Signup"
    expect(page).to have_text("Password can't be blank")
  end
  it "informs user of an invalid credit card" do
    visit signups_path
    fill_in "Email", with: "test@test.com"
    fill_in "Password", with: "valid-password"
    fill_in "Card", with: "bogus"
    click_button "Signup"
    expect(page).to have_text("Card is invalid")
  end
end

在一次测试中测试所有这些似乎更简单。我正在努力寻找合适的功能测试方法。我不想开始随机编写测试,这些测试(1)实际上没有覆盖/测试我的代码,或者(2)因为我写得不称职而变得臃肿和缓慢。我理解测试的必要性,只是不确定如何最好地进行上述功能测试。

您应该使代码干涸,以尽量减少重复。您可以将在每个测试开始时调用的指令移动到之前的,并提取重复代码的帮助器方法:

describe "Signup" do
  before do
    visit signups_path
  end

  def fill_form(fields = {})
    fields.each do |field_name, field_value|
      fill_in field_name.to_s.capitalize, with: field_value
    end
    click_button "Signup"
  end

  it "informs user of an invalid email" do
    fill_form email: ""

    expect(page).to have_text("Email can't be blank")
  end
  it "informs user of an invalid password" do
    fill_form email: "test@test.com", password: ""

    expect(page).to have_text("Password can't be blank")
  end
  it "informs user of an invalid credit card" do
    fill_form email: "test@test.com", 
              password: "valid-password",
              card: "bogus"

    expect(page).to have_text("Card is invalid")
  end
end

编写集成测试时,重要的是要避免

下面是一个例子:

RSpec.feature'Signup',测试助手:[:Signup\u-ups]do
在{访问注册路径}之前
它会“通知用户一封无效的电子邮件”
注册。使用(电子邮件:'')注册
注册。应该。有错误(“电子邮件不能为空”)
结束
它会“通知用户密码无效”吗
注册。注册(电子邮件:'test@test.com')
注册应该有错误(“密码不能为空”)
结束
它“通知用户一张无效的信用卡”
注册。注册(电子邮件:'test@test.com,密码:“有效密码”,卡片:“伪造”)
注册错误('卡无效')
结束
结束
您可以使用以下工具或库实现:

classsignupstesthelper
这就是说,有时不需要完全隔离,并且结合这些场景应该会使测试套件大大加快:

RSpec.feature'Signup',测试助手:[:Signup\u-ups]do
在{访问注册路径}之前
它“通知用户无效信息”是否执行
注册。使用(电子邮件:'')注册
注册。应该。有错误(“电子邮件不能为空”)
注册。注册(电子邮件:'test@test.com')
注册应该有错误(“密码不能为空”)
注册。注册(电子邮件:'test@test.com,密码:“有效密码”,卡片:“伪造”)
注册错误('卡无效')
结束
结束

请注意,现在测试代码已经很好地封装,在压缩版本中仍然很容易遵循。

为什么您觉得编写一个测试会更简单?@JustinKo,我认为这会更简单,因为对于每个测试,我都处于相同的“场景”,每个测试都有大量重复的代码。但是,经过一段时间的研究,我得出结论,在
块之前清除
中的重复代码会有很大帮助,真正的测试应该只有1个
expect/assert
,才能真正帮助解决钉点问题。我想我说的“更简单”是指“更短”。但有时短并不总是好的。经过一段时间的研究,这是解决这个问题最干净、最传统的方法。严格地说,为了真正成为一个单元测试,每个测试应该只期望/断言一件事情。这使得每个单独的测试更小,更容易维护。确实会导致运行测试套件的时间稍长,但这是一个折衷方案。我只遇到过一种情况,即我决定在一个测试中放入多个
expect(…)
,这是因为我调用了一个外部API,进行多个调用的时间非常昂贵。