Ruby製アプリじゃなくてもTurnipで自動受け入れテストがしたい
Python製のWebアプリケーションの自動受け入れテストをしたくて、調べてみました。
Ruby界隈だと、最近ではCucumberに代わってTurnipというツールが流行っているみたいなので試してみました。
自動受け入れテスト用のライブラリ
Rubyで自動受け入れテストをしようとすると、以下の3つの選択肢があるようです。
- Cucumber
- テストケースを自然文で書けるため、非プログラマでも読みやすい。
- Turnip
- RSpecのfeature spec
Cucumberは以前にも使ったことがあるので、今回はTurnipを選択してみました。詳しい説明は以下のページに譲ります。
- Rubyist Magazine - エンドツーエンドテストの自動化は Cucumber から Turnip へ
- Rspec/Capybara/Turnipの入門記事を全力でまとめてみた - 酒と泪とRubyとRailsと
Webページを自動操作するライブラリ
Webページの自動操作にはCapybaraを使います。デフォルトではRackTestというドライバが使われますが、これはHTTP通信を行わないドライバでありRackアプリケーションでしか使えません。
このためHTTP通信を行う他のドライバを使います。ヘッドレスでJavaScriptを利用できるドライバとして、以下の2種類があるようです。
- capybara-webkit
- Qtを利用したWebKitドライバー
- Poltergeist
- PhantomJSを利用したWebKitドライバー
最近ではPoltergeistのほうがインストールが簡単かつ高速で人気らしいので、今回はPoltergeistを使いました。
前提
前提として、Ruby 2.1*1 およびBundlerがインストールされているものとします。
PoltergeistのインストールにはPhantomJSが必要なので、 PoltergeistのREADMEに従ってインストールします。
Macならば brew install phantomjs
で簡単にインストール出来ました。
準備
適当なフォルダを作ります。
$ mkdir bus-spec $ cd bus-spec
以下のコマンドでGemfile
を作ります。
$ bundle init
Gemfile
を以下のように編集します。
source "https://rubygems.org" gem 'turnip' gem 'capybara' gem 'poltergeist'
以下のコマンドでGemをインストールします。
$ bundle install --path=vendor/bundle
TurnipのREADMEを参考に、テストに必要なファイル・フォルダを作成します。
$ mkdir -p spec/{features,steps}
.rspec
を以下の内容で作成します。
-r turnip/rspec
spec/spec_helper.rb
を以下の内容で作成します。
Dir.glob('spec/steps/*steps.rb') { |f| load f, true } require 'capybara/rspec' require 'capybara/poltergeist' Capybara.default_driver = :poltergeist # 以下の関数はGeolocation APIをシミュレートするヘルパー関数です。 def simulate_location(latitude, longitude, accuracy=0) Capybara.current_session.execute_script <<-EOS window.navigator.geolocation = { getCurrentPosition: function(success) { var position = {coords: {latitude: #{latitude}, longitude: #{longitude}, accuracy: #{accuracy}}}; success(position); } }; EOS end
rspec
を実行して以下のように表示されれば準備完了です。
$ bundle exec rspec No examples found. Finished in 0.00005 seconds 0 examples, 0 failures
Turnipによる受け入れテスト
それではTurnipによる自動受け入れテストを書いていきます。
spec/features/search.feature
には、プログラムに詳しくない人が読んでもわかる書式(Gherkin形式)で機能を記述します。
# encoding: utf-8 # language: ja 機能:PCまたはスマートフォンでバス停を検索 シナリオ:トップページにアクセスして検索する 前提ポケドスにアクセスする 前提"京都市役所"に居る もしトップページを表示する ならば画面に"近くのバス停を探す"ボタンが表示されていること もし"近くのバス停を探す"ボタンをクリックする ならば画面に"この近くのバス停"と表示されていること かつ画面に"京都市役所前: 91m"と表示されていること
プレースホルダーに日本語を使う場合は、""
で囲うなど少し工夫が必要です。参考:Ruby - Turnip で placeholder のマッチングを柔軟にする - Qiita
spec/steps/bus_steps.rb
には、上で書いたGherkin形式のステップ(「前提」「もし」「ならば」など)に対応するプログラムを書きます。
# encoding: utf-8 step 'ポケドスにアクセスする' do Capybara.app_host = 'http://bus.capybala.com/' end step ':placeに居る' do |place| case place when '京都市役所' @place = {lat: 35.01129870069897, lng: 135.76807713296512} else raise "Unknown place" end end step 'トップページを表示する' do visit '/' simulate_location(@place[:lat], @place[:lng]) if @place end step '画面に:labelボタンが表示されていること' do |label| expect(page).to have_link(label) end step ':labelボタンをクリックする' do |label| click_link label end step '画面に:textと表示されていること' do |text| expect(page).to have_content(text) end
再度rspec
を実行して以下のように表示されれば成功です。
$ bundle exec rspec . Finished in 2.92 seconds 1 example, 0 failures
まとめ
Turnipはこのように、テストする機能を自然文で書けるテストライブラリであり、Capybaraと組み合わせることでWebサービスの自動受け入れテストを行えます。
2012年に書いた記事と比べると、Cucumber → Turnip、capybara-mechanize/capybara-webkit → Poltergeistと変化しました。
正直Rubyをゴリゴリ書いていない身としては、TurnipのCucumberに対する利点として挙げられる、RSpecが使える点とプレースホルダーが簡単に書ける点が、それほど嬉しいことなのかよくわかりませんでした。
また、CucumberやTurnipのGherkin書式は、普通のテストを書くのに比べてコストがかかる割に、どの程度受け入れられるの?という考えもあります。 参考:RSpecで、Cucumberのような結合試験のspecを記述する - 高尾宏治日記 on はてな
うまく使えば強力なツールですが、使いドコロをよく考えて使う必要があるでしょう。
ここで説明したものをもう少し複雑にしたコードをGitHubで公開しています。
参考サイト・書籍
- Rubyist Magazine - エンドツーエンドテストの自動化は Cucumber から Turnip へ
- Turnip について (1) / まずは動かす - Thanks Driven Life
- Everyday Rails… Aaron Sumnerによる et al. [Leanpub PDF/iPad/Kindle]
*1:今回は2.1を使いましたが、1.9.3以上ぐらいで動くと思います。