2

will_paginateが正常に機能していることをテストするために、リクエストスペックを作成していますが、いくつか問題があります。まず、これが私の仕様の剪定バージョンです。

require 'spec_helper'

describe "Articles" do

  subject { page }

  describe "index page" do

    let(:user) { FactoryGirl.create(:user) }

    before { visit news_path }

    describe "pagination" do

      before(:all) { 31.times { FactoryGirl.create(:article, user: user) } }
      after(:all) { Article.delete_all; User.delete_all }

      let(:first_page)  { Article.paginate(page: 1) }
      let(:second_page) { Article.paginate(page: 2) }

      it "should not list the second page of articles" do
        second_page.each do |article|
          page.should_not have_selector('li', text: article.title)
        end
      end
    end
  end
end

ご覧のとおり、ユーザーが記事のインデックスページにアクセスしたときに、記事の2ページ目が表示されないことを確認するテストがあります。このテストは失敗します:

1) Articles index page pagination should not list the second page of articles
   Failure/Error: page.should_not have_selector('li', text: article.title)
   expected css "li" with text "Article number 1" not to return anything

なぜこれが失敗しているのか理解できません。開発環境で31の記事を手動で作成し、ブラウザーで表示すると、ページネーションは正常に機能しますが、テスト環境に切り替えると、仕様が失敗します。

記事モデル:

class Article < ActiveRecord::Base
  attr_accessible :body, :title
  belongs_to :user

  validates :user_id, presence: true

  default_scope order: 'created_at DESC'
end

記事ファクトリーは次のようになります。

FactoryGirl.define do
  factory :article do
    sequence(:title)  { |n| "Article number #{n}" }
    body "This is the body"
    user
  end
end
4

1 に答える 1

4

非常に信じられないことに、これに対する解決策は次のことを行うことでした。

変化する:

before(:all) { 31.times { FactoryGirl.create(:article, user: user) } }

に:

before do
  31.times { FactoryGirl.create(:article, user: user) }
  visit news_path
end

ここで学んだ2つのこと:

  1. beforeブロックはターゲットにしないでください。ターゲットにしないと(:all)、テストが失敗します
  2. ファクトリの作成後visit news_path、beforeブロック内を明示的に実行する必要があります。そうしないと、capybaraのページオブジェクトが期待どおりになりません。

だから、説明するために:

これは機能しません:

# fails because it targets (:all)
before(:all) do
  31.times { FactoryGirl.create(:article, user: user) }
  visit news_path
end

そして、これもそうはなりません:

# fails because we are visiting the news path before the objects exist
before do
  visit news_path
  31.times { FactoryGirl.create(:article, user: user) }
end

これである必要があります:

# not targeting (:all) and only visiting news path after creation of the objects
before do
  31.times { FactoryGirl.create(:article, user: user) }
  visit news_path
end

これを理解するために20時間以上、少なくとも私はいくつかの新しいことなどを学びました。

于 2012-06-06T18:41:42.653 に答える