RSpec:使用Capybara测试JS:是否可以在彼此之后运行许多“it”块(不重置db等)?

时间:2014-07-30 09:03:14

标签: ruby rspec capybara

我想确保一些小型JS按预期工作。

因为Capybara在运行启用JS的示例时需要更多时间,所以我倾向于将所有需要的断言放在一个单一的规范中,因此它们可能变得非常冗长和复杂。

这是一个当前的例子:

it 'provides "select all/none" buttons for the preferred regions (and updates the badge)', js: true do
  @user.profile = create :profile, preferred_regions_switzerland: [:zh, :ag, :sh],
                                   preferred_regions_germany: [],
                                   preferred_regions_austria: [:sbg]

  visit edit_user_profile_path

  # Make sure that the script is initialised for all countries
  expect(page).to have_link 'Preferred regions in Switzerland 3'
  expect(page).to have_link 'Preferred regions in Germany 0'
  expect(page).to have_link 'Preferred regions in Austria 1'

  # Click "Select all"
  click_link 'Preferred regions in Germany 0'
  within '#preferred_regions_germany' do
    expect(all('input[type="checkbox"]:checked')).to be_empty

    click_button 'Select all'

    expect(all('input[type="checkbox"]:checked').count).to eq Profile.preferred_regions_germany.options.size
  end
  expect(page).to have_link "Preferred regions in Germany #{Profile.preferred_regions_germany.options.size}"

  # Click "Select none"
  within '#preferred_regions_germany' do
    click_button 'Select none'

    expect(all('input[type="checkbox"]:checked').count).to be 0
  end
  expect(page).to have_link "Preferred regions in Germany 0"

  # Manually select a checkbox
  within '#preferred_regions_germany' do
    check 'Bayern'
  end
  expect(page).to have_link "Preferred regions in Germany 1"

  # Manually deselect a checkbox
  within '#preferred_regions_germany' do
    uncheck 'Bayern'
  end
  expect(page).to have_link "Preferred regions in Germany 0"
end

输出:

- it provides "select all/none" buttons for the preferred regions (and updates the badge)

我想知道是否有办法将这个例子分成许多"它"顺序运行的块,因此数据库不会重置,每个都会共享当前的上下文等?

一些伪代码:

sequential_examples js: true do
  it 'initialises the badges' do
    @user.profile = create :profile, preferred_regions_switzerland: [:zh, :ag, :sh],
                                     preferred_regions_germany: [],
                                     preferred_regions_austria: [:sbg]

    visit edit_user_profile_path

    # Make sure that the script is initialised for all countries
    expect(page).to have_link 'Preferred regions in Switzerland 3'
    expect(page).to have_link 'Preferred regions in Germany 0'
    expect(page).to have_link 'Preferred regions in Austria 1'
  end

  it 'provides "select all/none" buttons for the preferred regions' do
    # Click "Select all"
    click_link 'Preferred regions in Germany 0'
    within '#preferred_regions_germany' do
      expect(all('input[type="checkbox"]:checked')).to be_empty

      click_button 'Select all'

      expect(all('input[type="checkbox"]:checked').count).to eq Profile.preferred_regions_germany.options.size
    end
    expect(page).to have_link "Preferred regions in Germany #{Profile.preferred_regions_germany.options.size}"

    # Click "Select none"
    within '#preferred_regions_germany' do
      click_button 'Select none'

      expect(all('input[type="checkbox"]:checked').count).to be 0
    end
    expect(page).to have_link "Preferred regions in Germany 0"
  end

  it 'updates the badge' do
    # Manually select a checkbox
    within '#preferred_regions_germany' do
      check 'Bayern'
    end
    expect(page).to have_link "Preferred regions in Germany 1"

    # Manually deselect a checkbox
    within '#preferred_regions_germany' do
      uncheck 'Bayern'
    end
    expect(page).to have_link "Preferred regions in Germany 0"
  end
end

输出:

- it initialises the badges
- it provides "select all/none" buttons for the preferred regions
- it updates the badge

这会产生更好的输出,但仍然会非常快。

我知道这是"反对"一些非常重要的测试原则,但明智地使用,它可以分解很长的例子,提供更好的输出甚至可维护性。

1 个答案:

答案 0 :(得分:1)

您可以通过提供示例(it块)而不想重置数据库某些标记并更改DatabaseCleaner.strategy的{​​{1}}来做您要求的确切事情。 } hook被约束到那个标签。 (The RSpec documentation shows how to constrain a hook to a tag.

然而,这种方法存在问题:

  • 在一个需要重置数据库的示例中错误地使用标记会很容易(例如,通过删除在没有重置数据库的示例之前)。

  • 你不会将你的例子彼此隔离,所以一个例子可能会留下可能使下一个例子无效的状态。

所有这些麻烦来自于使用非常繁重的工具来测试代码的所有小细节。考虑一种不同的方法:仅在少量功能规范中使用Javascript驱动程序(其中每个功能规范端到端地测试用户可见功能),并使用Javascript单元测试框架(如Jasmine)来测试您的详细信息像你在上面测试的Javascript。您可以为上面的每个交互编写单独的独立单元测试,也可以更多地测试选择和/或取消选择的序列。然后,您将进行适当的隔离测试,减少较慢的慢速测试,以及更小的快速测试。

旁注:您可以通过为每个操作/断言对提取方法来使您的长示例更容易阅读:

around

但这不会孤立测试,所以我仍然会按照上面所说的做。