LoginSignup
20
16

More than 5 years have passed since last update.

Docker 上で実行した feature spec をデバッグする方法

Last updated at Posted at 2018-02-28

概要

Docker + Selenium + Headless Chrome な環境で feature spec を実行する時に、ブラウザの開発者ツールを使ってデバッグしたかったので調べた。

こんな感じで使える↓

Screen Shot 2018-02-28 at 1.19.56.png

サンプルコードはこちら
https://github.com/yszk0123/selenium-docker-rails-example

今回の例では Chrome を使ったが、Firefox も可能なはず。

検証環境

やり方

ブラウザ・Selenium サーバー・VNC サーバーなどが同梱されたselenium/standalone-chrome-debug という docker イメージを使う1
Docker for Mac には
VNC クライアントが同梱されているので2、特別な設定なしにコンテナの外からブラウザを操作できる。

今回は次の2つのコンテナに分ける。

  1. テストを実行するコンテナ app
  2. Selenium サーバー用のコンテナ chrome

また、テスト用に以下のホスト・ポートを使用する (docker-compose のネットワーク機能を活用)。

  • アプリケーションサーバー http://app.com:3000
  • Selenium サーバー http://chrome.com:4444
  • VNC サーバー http://localhost:5900 (ホストマシンからアクセス)

docker-compose の設定

docker-compose.yml
version: "2"
services:
  # テストを実行する Rails サーバー。Dockerfile は以下のリンク
  # https://github.com/yszk0123/selenium-docker-rails-example/blob/master/Dockerfile
  app:
    container_name: app
    build: .
    ports:
      - 3000:3000
    volumes:
      - .:/app
    networks:
      test-network:
        aliases:
          - app.com
  chrome:
    container_name: chrome
    image: selenium/standalone-chrome-debug:3.9.1-actinium
    ports:
      - 4444:4444
      - 5900:5900
    networks:
      test-network:
        aliases:
          - chrome.com
networks:
  test-network:

RSpec (Capybara) の設定

spec/rails_helper.rb
require 'rspec/rails'
require "capybara/rails"
require "selenium/webdriver"

if ENV["LAUNCH_BROWSER"]
  Capybara.configure do |config|
    # docker-compose で設定した alias を使い
    # chrome コンテナ側から app コンテナ内のサーバーを参照
    config.server_host = "app.com"
    # ポートはデフォルトではランダムに割り当てられるが、設定を簡単にするため固定
    config.server_port = 3000
    config.javascript_driver = :selenium_chrome_headless
  end

  Capybara.register_driver :selenium_chrome_headless do |app|
    Capybara::Selenium::Driver.new(
      app,
      # 別コンテナで動かしている Selenium のリモートサーバーを操作
      browser: :remote,
      # Chrome 以外は適宜設定を変える
      desired_capabilities: Selenium::WebDriver::Remote::Capabilities.chrome(
        chromeOptions: {
          args: [
            "window-size=1024,512",
          ]
        }
      ),
      url: "http://chrome.com:4444/wd/hub",
    )
  end
end

実行方法

$ docker-compose up -d
# VNC クライアントを起動
$ open vnc://localhost:5900
# ここでパスワードを求められるので secret と入力
# テストを実行
$ docker exec -it app sh -c 'LAUNCH_BROWSER=true bundle exec rspec'

後は止めたいところに pry.binding などを仕込めばOK。

spec/features/sample_spec.rb
require "rails_helper"

RSpec.feature "Sample", js: true do
  scenario "sample" do
    visit sample_path

    binding.pry

    expect(page).to have_content("Hello, world")
  end
end

おまけ (JavaScript でテストを書く場合)

サーバーサイドは Rails だけど JavaScript でテストを書くケースもありそうだったので軽く調べた。
以下は selenium-webdriver を使った例。

$ docker-compose run --rm app sh -c 'bin/rails s'
$ docker-compose run --rm chrome
$ docker-compose run --rm node
docker-compose.yml
+  node:
+    container_name: node-test
+    image: node:9.6.1-alpine
+    command: sh -c 'cd /app && yarn init -y && yarn add selenium-webdriver && node test.js'
+    volumes:
+      - ./test.js:/app/test.js
+    networks:
+      test-network:
   chrome:
     container_name: chrome
test.js
const { Builder } = require('selenium-webdriver');

function wait(delay) {
  return new Promise(resolve => setTimeout(resolve, delay));
}

(async () => {
  const driver = new Builder()
    .forBrowser('chrome')
    .usingServer('http://chrome.com:4444/wd/hub')
    .build();

  try {
    await driver.get('http://app.com:3000/sample');
    await wait(3000);
  } finally {
    await driver.quit();
  }
})();

おわりに

Rails と Selenium にはあまり詳しくないため、間違いがあればご指摘いただけると助かります。

参考

20
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
16