cucumber で capybara-webkit を使って javascript が動くテスト

前提
$ yum list installed | grep xorg-x11-server-Xvfb
xorg-x11-server-Xvfb.i686
$ yum list installed | grep qtwebkit-devel
qtwebkit-devel.i686     2.1.1-1.el6       @epel
$ rails -v
Rails 3.2.8
とりあえずrailsプロジェクト作成
$ rails new hoge -T

  ....省略

$ cd hoge/
Gemfile 修正

Gemfile

source 'https://rubygems.org'

gem 'rails', '3.2.8'

gem 'sqlite3'

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'therubyracer', :platforms => :ruby
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'

上記に変更後、再び bundle install

$ bundle install

  ....省略
WelcomeController#index の作成
$ bundle exec rails g controller welcome index
      create  app/controllers/welcome_controller.rb
       route  get "welcome/index" 
      invoke  erb
      create    app/views/welcome
      create    app/views/welcome/index.html.erb
      invoke  helper
      create    app/helpers/welcome_helper.rb
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/welcome.js.coffee
      invoke    scss
      create      app/assets/stylesheets/welcome.css.scss

ルートへのアクセスを WelcomeController#index に振る

Hoge::Application.routes.draw do
  root :to => 'welcome#index'
end

ルーティングの確認

$ bundle exec rake routes
root  / welcome#index

index.html は削除しておく

$ rm public/index.html

サーバ起動

$ bundle exec rails s
=> Booting WEBrick
=> Rails 3.2.8 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2012-09-29 00:44:41] INFO  WEBrick 1.3.1
[2012-09-29 00:44:41] INFO  ruby 1.9.3 (2012-04-20) [i686-linux]
[2012-09-29 00:44:41] INFO  WEBrick::HTTPServer#start: pid=26071 port=3000

ブラウザで確認


javascript で p タグの文言を変更するようにする

app/assets/javascripts/welcome.js.coffee

$ ->
  $('p').text('Hello capybara world!')

変更後、ブラウザで確認(再ロード)


Gemfile 修正

cucumber-rails と database_cleaner を加える
後者は、gem 間に依存関係はないけど cucumber の既定設定だと必要になる。

Gemfile

source 'https://rubygems.org'

gem 'rails', '3.2.8'

gem 'sqlite3'

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'therubyracer', :platforms => :ruby
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'

group :test do
  gem 'cucumber-rails', require: false
  gem 'database_cleaner'
end

上記に変更後、再び bundle install

$ bundle install

  ....省略
cucumber の初期化
$ bundle exec rails g cucumber:install
      create  config/cucumber.yml
      create  script/cucumber
       chmod  script/cucumber
      create  features/step_definitions
      create  features/support
      create  features/support/env.rb
       exist  lib/tasks
      create  lib/tasks/cucumber.rake
        gsub  config/database.yml
        gsub  config/database.yml
       force  config/database.yml

試しに実行してみる

$ bundle exec rake db:migrate
$ bundle exec rake cucumber
/usr/local/bin/ruby -S bundle exec cucumber  --profile default
Using the default profile...
0 scenarios
0 steps
0m0.000s
cucumber テストを書く

features/step_definitions/steps.rb

Given 'I am on root' do
  visit '/'
end

Then 'I should see cool message' do
  page.find('p', text: 'Hello capybara world!')
end

features/nice.feature

Feature: Nice feature
  Scenario: Nice message displayed by ajax when page loaded.
    Given I am on root
    Then  I should see cool message

実行してみる

$ bundle exec rake cucumber
/usr/local/bin/ruby -S bundle exec cucumber  --profile default
Using the default profile...
Feature: Nice feature

  Scenario: Nice message displayed by ajax when page loaded. # features/nice.feature:2
    Given I am on root                                       # features/step_definitions/steps.rb:2
    Then I should see cool message                           # features/step_definitions/steps.rb:6
      Unable to find css "p" (Capybara::ElementNotFound)
      (eval):2:in `find'
      ./features/step_definitions/steps.rb:7:in `/^I\ should\ see\ cool\ message$/'
      features/nice.feature:4:in `Then I should see cool message'

Failing Scenarios:
cucumber features/nice.feature:2 # Scenario: Nice message displayed by ajax when page loaded.

1 scenario (1 failed)
2 steps (1 failed, 1 passed)
0m0.905s
rake aborted!
Command failed with status (1): [/home/sakaguchi/.rvm/rubies/ruby-1.9.3-p19...]

Tasks: TOP => cucumber => cucumber:ok
(See full trace by running task with --trace)
  • 失敗した。
    • html 描画時点では、'Hello capybara world!' とは表示されておらず、 javascript によって書き換えられるから。
    • Capybara のデフォルト javascript ドライバである rack_test は、 javascript を実行しない。javascript ドライバを webkit に変更して javascript が動作するようにしなければ、上記テストは成功しない。
capybara-webkit を使う

Gemfile 再度修正、 capybara-webkit と headless を導入する。

source 'https://rubygems.org'

gem 'rails', '3.2.8'

gem 'sqlite3'

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'therubyracer', :platforms => :ruby
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'

group :test do
  gem 'cucumber-rails', require: false
  gem 'database_cleaner'
  gem 'capybara-webkit'
  gem 'headless'
end

インストール実施、 qmake へのフルパスを QMAKE 環境変数に設定する必要がある

$ QMAKE=/usr/lib/qt4/bin/qmake bundle install

  ....省略
Installing capybara-webkit (0.12.1) with native extensions
  ....省略
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.

Capybara で javascript ドライバを webkit に差し替える旨を設定する
features/support/env.rb の末尾に以下を加える

# use capybara-webkit driver.
Capybara.default_driver = :webkit
Capybara.javascript_driver = :webkit
Headless.new(display: 99).tap do |h|
  h.start
  at_exit { h.destroy }
end
テスト実行
$ bundle exec rake cucumber
/usr/local/bin/ruby -S bundle exec cucumber  --profile default
Using the default profile...
Feature: Nice feature

  Scenario: Nice message displayed by ajax when page loaded. # features/nice.feature:2
loaded the Generic plugin
can't make "generic.orientation" because no QAccelerometer sensors exist
    Given I am on root                                       # features/step_definitions/steps.rb:2
    Then I should see cool message                           # features/step_definitions/steps.rb:6

1 scenario (1 passed)
2 steps (2 passed)
0m1.973s

成功した。(∩´∀`)∩ワーイ