Showing posts with label Capybara. Show all posts
Showing posts with label Capybara. Show all posts

Monday, March 7, 2011

use transactional_fixtures with capybara akephalos driver

You may turn on transactional fixtures with Capybara akephalos driver (it may work with selenium driver too) having the monkey-patch below in spec_helper.rb or somewhere else.
akephalos driver を使っている場合でも以下のコードを spec_helper.rb にでも書いておくと transactional_fixtures を有効にできそうです。 (たぶん selenium などでも同様)



ActiveRecord::ConnectionAdapters::ConnectionPool.class_eval do
def current_connection_id
# Thread.current.object_id
Thread.main.object_id
end
end

かなり無茶苦茶な変更なので ActiveRecord を非同期に使うコードがあるとアウトなので要注意。

以下は簡単な説明です。

Capybara はデフォルトではサーバーも仮想ブラウザもテストを実行している ruby のプロセス内で同期的に処理するので ActiveRecord の connection をテストとサーバーで共有でき、 transactional_fixtures が使えます。

しかし、 Selenium driver の場合ブラウザは本物、 Akephalos は HtmlUnit という Java の仮想ブラウザを別プロセスで実行しています。
そのため、テストのサーバーも実際の http リクエストを処理する必要があるので、 Capybara は thin や webrick を別スレッドで実行することにより対処しています。

一方、 ActiveRecord の ConnectionPool は connection のレースコンデションを避けるためにスレッド毎に異なる connection を返すため、 fixtures ロードを含むテストとサーバーは同一トランザクションにはなりません。

そこで、無理矢理に異なるスレッドでも ConnectionPool が同じ connection を返すように変更。真面目にこの問題に対応するためには、別スレッドでサーバーを起動せずにリクエストをブロックして rack-test で処理すればできそうな気も。

Sunday, December 19, 2010

my first impression of using capybara + akephalos

thoughtbot and the Holy Grail - GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS
を見て、 capybara + akephalos を試してみた。

結論から言うと、 jquery-ujs ajax リクエストのテストができたんですけど、補足事項がいくつかあります。

1. javascript_driver でなく default_driver を変更する必要があった
2. selenium でテストするときのように、サーバープロセスを起動してアクセスするので transactional_fixtures = false にしてテスト毎に DBの cleanup が必要

具体的には
# spec/spec_helper.rb
require 'akephalos'
#Capybara.javascript_driver = :akephalos
Capybara.default_driver = :akephalos


あと DB の cleanup は database_cleanupが便利でした。以下の例は transactional_fixtures を無効にして、全ての example が実行される前に一度 cleanup して、あとは example が終わると cleanup します。(truncate なので DatabaseCleaner.start はたぶん何もしないんですけど、 transaction strategy に変えたときには意味があるのでお約束です)

# spec/spec_helper.rb
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before(:suite) do
#DatabaseCleaner.strategy = :transaction
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation)
end

config.before(:each) do
DatabaseCleaner.start
end

config.after(:each) do
DatabaseCleaner.clean
end
end


元記事のコメントには「selenium より遅い」という意見があります。たしかに最初の akephalos サーバーの起動には時間かかるので、rspec コマンドで単体の example もしくは example group を実行しているときにはオーバーヘッドが大きいですね。しかし、 rake spec などで全部実行するときには akephalos サーバーの起動は一度で済むので、リクエスト自体は意外とサクサクと動いて僕の selenium のツライ経験からすると全然いいですね。

その他の注意事項としては、
1. 現状の akephalos (0.2.4) では capybara 0.4.0 に対応できてないので 0.3.9 を使うのですが、
within "#item_1"
はダメで、
within :css, "#item_1"
のように書く必要あり
2. webrat -> capybara 移行に際して、 capybara は rails の integration test のしくみを使ってないので、
get "/"
response.should contain("hoge")
が使えないので各、
visit "/"
,
page.should have_content("hoge")
などに書き換えが必要