タイトルの組み合わせでE2Eテストをやったのでやり方を書いてみます。

環境


  • Ubuntu Server 16.04
  • Ruby 2.4.1
  • minitest 5.10.3
  • minitest-capybara 0.8.2
  • capybara 2.14.4
  • selenium-webdriver 3.4.4
  • Chrome 59.0.3071.115
  • chromedriver 2.31.488763

MinitestはRubyの標準テストフレームワークです。
CapybaraはSeleniumのラッパー的なものです。たぶん。

Chromeは59以上でないとヘッドレスで実行できません。また、Chromeとchromedriverのバージョンの組み合わせによっては動かないのでダウンロードページで対応バージョンを確認した方がいいです。

chromedriverは2.30までだとselenium-webdriverでフォームの入力時にエラーが出るので2.31を使用します。

環境構築


今までのもろもろの記事で個別に書いているものもあるんですけど、まとまってなかったりするので一から書きます。

bundlerのインストール

必要なgemをインストールするのにbundlerを使うので、まずbundlerをインストールします。

1
gem install bundler

Chromeのインストール

一から書くとか言っときながら、これに関してはつい最近書いたのでそっち見てください。

chromedriverのインストール

こっから環境にあわせたものをダウンロードします。前述の通り2.31以上のものをダウンロードします。現時点では2.31が最新です。curlでダウンロードしてきて解凍したものをChromeと同じディレクトリに放り込みます。Chromeはデフォルトだと/usr/bin/にインストールされるはず。

1
# ダウンロード
2
sudo curl -O https://chromedriver.storage.googleapis.com/2.31/chromedriver_linux64.zip
3
4
# 解凍
5
sudo unzip chromedriver_linux64.zip
6
7
# chromeと同じディレクトリに放り込む。
8
sudo mv chromedriver /usr/bin/chromedriver

コードを書く


今回は下記のような構成にします。./srcディレクトリにテスト用のヘルパーであるtest_helper.rbを作成し、テストコードは./src/features/blog_test.rbに記述します。

1
.
2
├── Gemfile
3
├── Gemfile.lock
4
└── src
5
    ├── features
6
    │   └── blog_test.rb
7
    └── test_helper.rb

実際にガッツリやる場合はSelenium公式推奨と言われるPageObjectパターンを採用した構成になったりすると思います。PageObejectパターンについては下記2つの記事が非常に参考になります。

Selenium2でつくるテストケースの構成について
一休.comのE2Eテスト事情 ~ギリギリ話せるところまで話します~ /cybozu_ikyu_e2e

Gemfileの作成とインストール

テストで使用するgemをインストールするためにGemfileを作成します。下記のような感じになります。

1
source 'https://rubygems.org'
2
3
gem "selenium-webdriver"
4
gem "minitest"
5
gem "minitest-capybara"
6
gem "minitest-doc_reporter"
7
gem "minitest-stub_any_instance"
8
gem "minitest-bang"
9
gem "minitest-line"

そのあと、Gemfileに記述したgemをインストールします。

1
bundle install

test_helper.rbの作成

テスト用のヘルパーであるtest_helper.rbを作成します。

1
# coding: utf-8
2
require 'selenium-webdriver'
3
require 'minitest-capybara'
4
require 'minitest/test'
5
6
chrome_options = {
7
  browser: :chrome,
8
  options: ::Selenium::WebDriver::Chrome::Options.new(
9
    binary: '/usr/bin/google-chrome-stable', args: ["--headless","--disable-gpu","--window-size=1900,1080"]
10
    )
11
}
12
13
Capybara.register_driver :headless_chrome do |app|
14
  Capybara::Selenium::Driver.new(
15
    app,
16
    chrome_options
17
  )
18
end
19
20
Capybara.configure do |config|
21
  config.default_wait_time = 8
22
  config.app_host = 'https://yoshinorin.net/'
23
end
24
25
Capybara.default_driver = :headless_chrome

インストールしたChromeのバイナリのパスとかヘッドレスで実行するオプションとかを指定して変数(chrome_options)に放り込みます。この変数をCapybara::Selenium::Driver.newのコンストラクタに放り込みます。

これは下記のサイトを参考にしていい感じに作りました。

Headless Capybara Feature Specs with Chrome

テストコード書く

テストコードを書きます。今回はこのサイトの検索ページにある文字列を入力して、その結果に「ubuntuにchromeをインストールする」という文字列が含まれていた場合は成功、そうでない場合は失敗という風にしてみます。

ないと思いますが、実際にやるときはこのサイトをテスト代わりに使用しないでください

1
# coding: utf-8
2
require '../test_helper'
3
4
class SearchTest < Minitest::Capybara::Test
5
6
  # 各テスト実行後に実行される処理
7
  def teardown
8
    if(passed?)
9
      puts "OK"
10
    elsif
11
      puts "NG"
12
    end
13
  end
14
15
  def test_search
16
    visit "https://yoshinorin.net/search/"
17
    fill_in 'local-search-input', with: 'selenium'
18
    assert_content "ubuntuにchromeをインストールする"
19
  end
20
21
  def test_search_two
22
    visit "https://yoshinorin.net/search/"
23
    fill_in 'local-search-input', with: 'ああああああ'
24
    assert_content "ubuntuにchromeをインストールする"
25
  end
26
end

requireで先に作成したtest_helperをロードします。検索ページのテキストボックスのidがlocal-search-inputなので、各テストではそれにfill_inで文字列を入力しています。その後にassert_contentで指定した文字列が含まれているかassertしています。

またteardownで成功・失敗に応じてOKNGを表示するようにしてみました。

ちなみに、chromedriverが2.30以下の場合はここのfill_inで「仮想ディスプレイの使用を検討してください」みたいなエラーが出て落ちます。

非ヘッドレスで実行した場合のイメージ

前述のテストコードを非ヘッドレスでテストした場合の図を貼り付けときます。

成功のパターンは下記のようになります。「ubuntuにchromeをインストールする」が表示されているので成功です。

逆に失敗の場合です。今回の成功の条件である「ubuntuにchromeをインストールする」が表示されていないので失敗です。

実行する


テストを実行してみます。blog_test.rbを実行します。

1
ruby blog_test.rb
2
3
OK
4
SearchTest
5
  search
6
7
NG
8
SearchTest
9
  two
10
  Expected to find text "ubuntuにchromeをインストールする" in "YoshinoriN インフラからフ...(省略)".
11
12
2 tests run in 16.310793932 seconds.
13
Errors: 0  | Failures: 1  | Skips: 0
14
15
Focus on failing tests:
16
ruby blog_test.rb -l 18

こんな感じで結果が表示されます。表示される内容はインストールしているgemに応じて変わります。表示のフォーマットについてはこちらの記事が参考になります。

参考


CapybaraからHeadless Chromeを動かす環境をDockerで構築する