Androidのエンドツーエンドテストの自動化も Cucumber から Turnip へ
以前はAndroidのATDDにはCabash-Androidを入れてたのだけど、やっぱ時代はCucumberからTurnipだよねってことで、AndroidなTurnip環境を作ったので構築メモ。
ちなみに出来たものはこちらへ。
github - koduki/turnip_with_android_example
インストール
まずはこの辺参考にGenymotionを入れる。 別にGenymotionじゃなくて実機とかでも問題無いと思うけど、開発とかCIとかにはGenymotionが速くて便利。
インストールしたらデバックモードを有効にする。
Android 4.2以上はデフォルトでは開発者向けオプションがないらしいので
- 「設定」=>「端末情報」=>「ビルド番号」を7回タップすると「設定」に開発者向けオプションが表示される
- 「デバッグモード」をonにする
続いてappiumをnpm経由で入れる。
sudo npm install -g appium sudo npm install wd
これで、実行環境の準備は完了。最後にTurnipの環境を作る。
まずはインストール用のディレクトリを作成.
% mkdir turnip_with_android_example/ % cd turnip_with_android_example % mkdir spec/ % mkdir spec/acceptance/ % mkdir spec/steps/
続いて
% $EDITOR Gemfile
中身は下記の通り。
source "https://www.rubygems.org" gem 'rspec' gem 'selenium-webdriver' gem 'turnip
Turnip用にfeatureを取り込めるように.rspecに下記を記載
% $EDITOR .rspec
中身は下記の通り。
-r turnip
% $EDITOR spec/spec_helper.rb
require 'bundler/setup' require 'selenium-webdriver' Dir.glob("spec/steps/**/*steps.rb") { |f| load f, true }
これで必要なファイルが出来たので、Bundlerで依存ライブラリをインストールする
% bundle install --path vendor/bundle
シナリオの作成
さて、ようやく準備が整ったところでシナリオの作成。
開発中のアプリとかをテストするのが本来だけど、サンプルとしてのポータビリティを加味して、デフォルトで入っている[Settting]を対象にテストを書いてみる。
まずはfeatureファイルを作成。
% $EDITOR spec/acceptance/settings.feature
Feature: 設定画面 Scenario: 端末情報を表示する Given テスト対象は "android" 端末 When "About phone" をタップする Then Android Version は "4.2.2" が表示されていること
一旦この時点で実行してみる。bundlerで環境作ってるのでbundler経由でrspecを実行するのがポイント
% bundle exec rspec
stepファイルが無いので下記のようなエラーが出るはずです。
設定画面 端末情報を表示する テスト対象は "android" 端末 -> "About phone" をタップする -> Android Version は "4.2.2" が表示されていること (PENDING: No such step: 'テスト対象は "android" 端末') Pending: 設定画面 端末情報を表示する テスト対象は "android" 端末 -> "About phone" をタップする -> Android Version は "4.2.2" が表示されていること # No such step: 'テスト対象は "android" 端末' # ./spec/acceptance/settings.feature:3
続いてstepファイルを記述。中身は下記の通り。
# coding: utf-8 module SettingsStep step 'テスト対象は :device 端末' do |device| @device = device end step ':target をタップする' do |target| about = find_first_element('//text[@text="' + target + '"]') about.click end step 'Android Version は :expected が表示されていること' do |expected| version_setting = find_first_element('//list/linear[4]/relative') version_value = version_setting.find_element(:xpath, '//text[2]') expect(version_value.text).to eq(expected) end def find_first_element xpath #flick the screen until find the target item while driver.find_elements(:xpath, xpath).count == 0 begin driver.execute_script 'mobile: flick', :startY => 0.9, :endY => 0.1 rescue end end driver.find_elements(:xpath, xpath).first end def driver case @device when 'android' desired_caps = { 'browserName' => 'android', 'platform' => 'linux', 'version' => '4.1', 'app-activity'=> '.Settings', 'app-package'=> 'com.android.settings' } server_url = "http://127.0.0.1:4723/wd/hub" @driver ||= Selenium::WebDriver.for(:remote, :desired_capabilities => desired_caps, :url => server_url) @driver.manage.timeouts.implicit_wait = 3 end @driver end def cleanup if @driver driver.quit @driver = nil end end end RSpec.configure do |conf| conf.include SettingsStep conf.after(:each) do cleanup end end
基本的にはただのrsepcですね。1点注意としてはfind_first_elementの中でやってるみたいに画面上に表示されてない項目を出すためにスクロールする必要があります。 これ分からなくて、最初嵌った...
これを実行すると、下記の用にGreenな結果になる。
% bundle exec rspec 設定画面 端末情報を表示する テスト対象は "android" 端末 -> "About phone" をタップする -> Android Version は "4.2.2" が表示されていること Finished in 9.14 seconds 1 example, 0 failures
まとめ
とりあえずAndroidでturnipな環境が完成。割と便利そう。 ただ、構築が少し面倒なところも。npmとgem使うので、そっち系の親和性があってかつAnrdoidでJavaも書くぜーってエンジニアが居ないと、使うのはともかく導入に手間取るかなーという印象でした。国内情報少ないしね><
あと、cucumberの時もそうだったけど、Firebugとかに相当するDOMインスペクタが無いとstep書くのがちとしんどいのよね。 でも動画でそれっぽいものがappiumある的なことを言ってたので、調べてみようかな。
なんにしても後はテストをひたすら書くだけじゃー!! それではHappy Hacking!