Ruby on rails Rspec:后块中的测试

Ruby on rails Rspec:后块中的测试,ruby-on-rails,rspec,refactoring,capybara,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 subject { visit articles_path } it 'has a nice title' do subje

我有这样一个规范:

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

  specify do
    subject
    expect(page).to have_content(article.title)
  end
end
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
但是,当我尝试像这样重构它时,它说我有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
然后运行
之后的
钩子吗?我很确定我以前使用过这个设置

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

更新 我可以这样做,但我真的不喜欢:

subject do
  visit articles_path
  page
end

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

“after”块通常用于在执行测试示例后执行某些操作。在第二个示例中,在“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

在我看来,从您的重构尝试来看,有一点混乱

首先,您之所以看到
0个示例,0个失败
,是因为您的测试中没有主题调用。这样想:

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

  specify do
    subject
    expect(page).to have_content(article.title)
  end
end
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/specify
blocks
visit articles\u 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
您可以有不同的期望,它/指定相同上下文中的块。 使用不同的上下文指定同一功能的不同行为。

最后一步。在
块之前的
中对共享功能进行分组。在我们的例子中:

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
如您所见,这两个上下文运行主题,但只有第一个内容让用户登录以测试文章页面,而第二个上下文则没有。 我希望这是有用的


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

问题是,我有更多的上下文,它们共享相同的
let/访问共享上下文。我想我可以在{expect}之后在
上下文'other'中进行实际测试;结束
请查看我编辑的解决方案,我不知道您为什么要将验证代码放在after块中。在这种情况下,{login\u as:user}
将在{visit articles\u path}
之前执行,为了使您的示例生效,我必须在{login\u as:user;visit articles\u path}之前执行
上下文中的