DockerでCucumberのQuickstart環境を作ってみた
はじめに
BDDなe2eテストと言えばやはりCucumberですよね。
Gherkinを使って自然言語のようにテストケースが書け、具体的なステップをRubyやJavaで書けるので非常に便利です。
今回、久方ぶりにCucumberを使う必要がありそうなので便利そうな設定をいくつか入れてDocker化しておきました。これでRubyとかが入ってない環境でも問題なく利用できます。
今回実施してる設定は以下の通り
- ChromeのHeadlessモードを使ったテスト
- デバッグ用にオプションで指定したらChromeをGUIモードで起動するように設定
- テストに失敗したら自動的にスクリーンショットをとってテストレポートに含めるように設定
- Dockerコマンドのラッパースクリプトとして
qcmb
コマンドの作成
以下のGitHubリポジトリに置いてあるのでCloneすれば使えます。Chromeを使ってるのでJSやCSSを実際と違う形で解釈したりレンダリングしないので安心感がありますよね。
使い方
テストの実行
とりあえずcucumberを実行するなら以下のコマンド。features
ディレクトリ配下のテストを実行.
qcmdは単にDockerのラッパーコマンドで実際はdocker run -it --rm -v
pwd:/usr/src/app koduki/cucumber cucumber
を実行しています。
$ ./qcmb
標準出力ではなくHTMLでレポートが欲しい時は下記のようにCucumberのコマンドを実行。出力先はreport
を前提にいくつかの設定がされているので注意。
$ ./qcmb --format html --out report/index.html
テストが失敗した時のスクリーンショットも上記のreport
ディレクトリに出力されます。
ディレクトリを削除したい時はclean
を実行
$ ./qcmb clean
GUI mode で起動
CI/CDで利用することを考えるとヘッドレスモードがベストなのですが、たまにデバッグでGUIモードでChromeを立ち上げたい事もあります。
DockerはCLIベースの環境ではありますが、LinuxなのでX11をホスト側に飛ばすのは簡単にできます。
Macでの準備
$ brew install socat $ brew cask install xquartz
Xquartzを起動してXteam
を xquartz上で開きます。
open -a XQuartz
パーミッションを許可してProxyをXteam
上で起動します。
$ xhost + $ socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:/tmp/.X11-unix/X0
qcmb
コマンドの--Xheadless=false
オプションを指定して起動します。スクリプトの中で環境変数DISPLAYにホストマシンのIPアドレスなどを連携しています。
$ qcmb --Xheadless=false
設定の解説
support/env.rb
Docker内だとChromeを実行しようとするとDevToolsActivePort file doesn't exist
が出ます。そのため--no-sandbox
を有効にする必要があります。
また、環境変数に応じてHEADLESSモードとGUIモードのそれぞれが選べるようにしています。
require 'capybara/cucumber' require 'webdrivers' Capybara.register_driver :docker_chrome_headless do |app| browser_options = ::Selenium::WebDriver::Chrome::Options.new browser_options.args << '--headless' browser_options.args << '--no-sandbox' browser_options.args << '--disable-gpu' browser_options.args << '--window-size=1920,1080' Capybara::Selenium::Driver.new( app, browser: :chrome, options: browser_options ) end Capybara.register_driver :docker_chrome do |app| browser_options = ::Selenium::WebDriver::Chrome::Options.new browser_options.args << '--no-sandbox' browser_options.args << '--disable-gpu' browser_options.args << '--window-size=1920,1080' Capybara::Selenium::Driver.new( app, browser: :chrome, options: browser_options ) end def driver is_no_headless = ENV["CHROME_NO_HEADLESS"] if is_no_headless then :docker_chrome else :docker_chrome_headless end end Capybara.configure do |config| config.default_driver = driver() config.javascript_driver = driver() config.app = nil config.run_server = false end
support/screenshot.rb
Cucumberのテストが失敗したときに自動でスクリーンショットをとってテストレポートに埋め込むようにしています。
そもそもsupport配下にあるRubyスクリプトは名前に関係なく読み込まれます。これを利用してこの中にフックポイントであるAfter
を追加してシナリオ終了後の動作を記述します。
あとは見た通りですがシナリオが失敗したときに、スクリーンショットをとってレポートに埋め込んでいます。
After do |scenario| if scenario.failed? path = "report/#{scenario.__id__}.html" page.driver.browser.save_screenshot(path) embed(path, "image/png") end end%
例: テストレポートとスクリーンショット
まとめ
かなり久しぶりのCucumberだったので結構調べながら作りました。
Cucumberは10年経ってもやはり現役で多少は競合はあるものの圧倒的なシェアは流石ですね。Gherkinは仕様記述言語とまでは言えないもののログイン
とかの動作の意味が厳密に定義されるので自動テストをしなくてすら有用な文法だと思います。この手のツールを使ってテストケースと実際の自動テストの実行の解離が小さくなることがやはり良いですよね。
それではHappy Hacking!