Rspec:在块之后进行测试

时间:2014-10-18 11:12:04

标签: ruby-on-rails rspec refactoring capybara

我有这样的规格:

context 'index' do
  let!(:article) { create :article }
  subject { visit articles_path }

  specify do
    subject
    expect(page).to have_content(article.title)
  end
end

然而,当我尝试像这样重构它时,它说我有0个例子:

context 'index' do
  let!(:article) { create :article }
  subject { visit articles_path }

  context do
    after { expect(page).to have_content(article.title) }
  end

  context do
    before { login_as :user }
    after { expect(page).to have_content(article.comment) }
  end

  context do
    after {}
  end

end

它不应该运行subject然后运行after挂钩吗?我很确定我之前使用过此设置。

请告诉我如何正确地重构这个。谢谢。

更新 可以这样做,但我不是很喜欢它:

subject do
  visit articles_path
  page
end

specify do
  expect(subject).to have_content(article.title)
end

2 个答案:

答案 0 :(得分:0)

在执行测试示例后,'block'通常用于执行某些操作。在第二个示例中,您没有在'after'块之前执行测试

我会像这样重构你的代码

context 'index' do
  let!(:article) { create :article }
  visit articles_path
  expect(page).to_not have_content(category.title)
end

修改

context 'index' do
  let!(:article) { create :article }

  before do
    visit articles_path 
  end

  context do
    it "displays article's title" do
      expect(page).to have_content(article.title)
    end
  end

  context do
    before { login_as :user }
    it "displays article's comments" do
      expect(page).to have_content(article.comment)
    end
  end

  context do
    #another test
  end
end

答案 1 :(得分:0)

在我看来,重构尝试会让您感到有些困惑。

首先,您看到0 examples, 0 failures的原因是因为您的测试中没有主题调用。想想这样:

subject { visit articles_path }

it 'has a nice title' do
  subject
  expect(page).to have_content(article.title)
end

it 'has a nice comment' do
  subject
  expect(page).to have_content(article.comment)
end

为了满足您的期望,您需要致电主题。事实上,您甚至可以通过明确写入it/specifyvisit articles_path

来避免使用主题
it 'has a nice title' do
  visit articles_path
  expect(page).to have_content(article.title)
end

it 'has a nice comment' do
  visit articles_path
  expect(page).to have_content(article.comment)
end

使用subject { ... }可以消除共享同一主题的测试。

其次,不要将context块与specify/it块混淆(请记住它们有别名)。 context是一种通过分离测试的不同结果来使测试更容易理解的方法。

subject { visit articles_path }

context 'user is logged in' do
  it 'displays article's title' do
    login_as :user
    subject

    expect(page).to have_content(article.title)
  end

  it 'displays article's title' do
    login_as :user
    subject

    expect(page).to have_content(article.comment)
  end
end

context 'user not logged in' do
  it 'displays article's comments' do
    subject

    expect(page).to have_content('Log in')
  end
end

您可以有不同的期望,它/在同一个上下文中指定块。 使用不同的上下文指定相同功能的不同行为。

最后一步。在before块中分组共享功能。在我们的例子中:

subject { visit articles_path }

before do
  subject
end

context 'user is logged in' do

  before do
    login_as :user
  end

  it 'displays article's title' do
    expect(page).to have_content(article.title)
  end

  it 'displays article's title' do
    expect(page).to have_content(article.comment)
  end
end

context 'user not logged in' do
  it 'displays article's comments' do
    expect(page).to have_content('Log in')
  end
end

正如您所看到的,这两个上下文运行主题,但只有第一个内容记录用户来测试文章页面而第二个上下文不是。 我希望这很有用。

继续测试,很快就会成为一个习惯问题,你将很容易编写测试。