

Poltergeistを使用した場合、Capybaraのテストケースの挙動が不思議です。

まず最初に、Poltergeistを使用しない場合、Capybaraのテストケースはsuccessです。

[code]

    before { create(:user) }
    it 'test' do
      visit root_path
      expect(page).to have_content 'ユーザは1人です'
    end
    
[/code]

テスト対象のviewでは

ユーザは`<%= User.count %>`人です

のような記述です。  
JSのテストを行いたいため、

[code]

    it 'test', js: true do
    
[/code]

とすると、表示が「ユーザは0人です」のようになり、テストがfailureとなります。  
(page.save_screenshotにて確認)

どうやらbeforeで作成したユーザがうまくviewで取得できてないようです。

[code]

    expect(User.count).to eq 1
    
[/code]

はsuccessなので、DBに書き込みは行われています。

Poltergeistの代わりにcapybara-webkitでも同じ状況です。  
どうすればテストを通すことができるでしょうか？


CC BY-SA 3.0
2015-01-28T13:11:53.593
5522
2015-01-29T02:21:04.200
2015-01-29T02:21:04.200
85
7908
question
javascript ruby-on-rails rspec capybara poltergeist
CapybaraとPoltergeistを使用した場合にDBの内容がビューに反映されない


RSpecの設定で`use_transactional_fixtures`が`true`に設定されていませんか?

> What it really means in Rails is "run every test method within a
> transaction."

<https://relishapp.com/rspec/rspec-rails/docs/transactions>

この設定が`true`になっている場合、すべてのテストはトランザクション中で実行されます。  
なので、`create(:user)`もトランザクション中で実行されます。  
Capybaraで`visit
root_path`しても、`create(:user)`のトランザクションはコミットされていないため、レコードが作成されておらず、0人と表示されます。

`use_transactional_fixtures`を`false`にするとテストは通るようになると思います。

ただし、その場合はテストで作成したレコードを削除するなどの処理を自分で管理する必要があるため、  
[database_cleaner](https://github.com/DatabaseCleaner/database_cleaner)や[database_rewinder](https://github.com/amatsuda/database_rewinder)などのgemを合わせてつかい、テストで作成したレコードをロールバックさせるように設定するとよいと思います。


CC BY-SA 3.0
2015-01-28T16:00:57.057
5524
2015-01-28T16:00:57.057
2599
5522
answer


僕が翻訳した「[Everyday Rails -
RSpecによるRailsテスト入門](https://leanpub.com/everydayrailsrspec-
jp/)」という電子書籍で、サンプルアプリケーションのソースコードがGitHubに公開されています。  
使用しているのはPoltergeistではなくselenium-webdriverなのですが、考え方は同じなのでコード例を載せておきます。

<https://github.com/everydayrails/rails-4-1-rspec-3-0/blob/master/spec/rails_helper.rb>

[code]

    RSpec.configure do |config|
      # ...
    
      config.before(:suite) do
        DatabaseCleaner.strategy = :transaction
        DatabaseCleaner.clean_with :truncation
      end
    
      config.around(:each) do |example|
        DatabaseCleaner.cleaning do
          example.run
        end
      end
    
      config.after(:each) do
        DatabaseCleaner.clean
      end
    
      config.use_transactional_fixtures = true
    
      # ...
    end
    
[/code]

`use_transactional_fixtures` は `true` に設定していますが、 `false`
または設定をコメントアウト（デフォルトが`false`）に設定しても問題ありませんでした。

また、`DatabaseCleaner.cleaning`はバージョン1.3.0から導入されたので、必要に応じてDatabaseCleanerをアップデートしてください。

<https://github.com/everydayrails/rails-4-1-rspec-3-0/blob/master/Gemfile>

[code]

    group :test do
      # ...
      gem "database_cleaner", "~> 1.3.0"
      # ...
    end
    
[/code]

設定の意味は「[Everyday Rails -
RSpecによるRailsテスト入門](https://leanpub.com/everydayrailsrspec-
jp/)」に載っているので抜粋しておきます。

> これは何をやっているのでしょうか？最初にやっているのはテストデータをセットアップする際に使う
> 戦略（strategy）の指定です。それぞれのテストを独立させた状態にするため、ここでは
> トランザクション（transaction）を指定しました。ご想像の通り、これはデータベースのトランザクションを使う戦略です。続いて、データを全件削除（clean）するためにテーブルのトランケート（truncation）を指定しています。最後に、トランザクションの開始と終了を実行するタイミングと（これはテストスイート中の各exampleを実行する前後です）、全件削除を実行するタイミング（これは各exampleを実行した後です）を指定しています。

あともう一点、 `spec/support/shared_db_connection.rb`というファイルを作成し、以下の内容を記述してください。

<https://github.com/everydayrails/rails-4-1-rspec-3-0/blob/master/spec/support/shared_db_connection.rb>

[code]

    class ActiveRecord::Base
      mattr_accessor :shared_connection
      @@shared_connection = nil
    
      def self.connection
        @@shared_connection || retrieve_connection
      end
    end
    ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
    
[/code]

この設定の必要性についても書籍の中で述べられています。

>
> なぜこのような変更が必要になるのでしょうか？端的に答えるのであれば、Seleniumを使った場合、データベーストランザクションの扱い方に違いが出てくるからです。テストを実行するときはSelenium
> webサーバとテストコードの双方でデータの状態を共有しなければいけません。DatabaseCleanerと上記のパッチがないと、テスト実行後のクリーンアップが正しく行われないために、テストが時折失敗する可能性があります。

Everyday
Railsには他にもRailsのテストに関する実践的な内容が載っているので、困ったときのリファレンス本として役立ちます。もしよかったら読んでみてください。

[Everyday Rails - RSpecによるRailsテスト入門](https://leanpub.com/everydayrailsrspec-
jp/)


CC BY-SA 3.0
2015-01-28T21:07:29.537
5537
2015-01-28T21:28:25.173
2015-01-28T21:28:25.173
85
85
5522
answer