はじめに
CircleCI で JavaScript を扱えるように設定しました。
今まで問題なく動作していた CircleCI
のテストでしたが、あることをしてから通らなくなったので対処方法を記していきます。
今までの設定ファイルはこちらです。
目次
-
環境
-
問題
-
原因
- RSpecで
js: true
を使用 - 今回 ローカル環境と CircleCI環境 をあわせるために行った変更
- RSpecで
-
解決策
-
spec/support/capybara.rb
- 変更前
- 変更後
spec/rails_helper.rb
Dockerfile
.circleci/config.yml
.circleci/config.yml 全体
config/database.yml.ci
-
-
まとめ
-
おわりに
-
参考文献
環境
- Ruby: 2.6.6
- Bundler: 2.0.2
- MySQL: 8.0
- CircleCI: 2.0
- yarnでjQuery( JavaScript )を使用。( ※ gemとyarnでの使用方法の違いでテストの結果に影響でることが考えられるため。 )
問題
SocketError:
Failed to open TCP connection to chrome:4444
(getaddrinfo: No address associated with hostname)
# chrome:4444へのTCP接続のオープンに失敗
SocketError: getaddrinfo: No address associated with hostname
# ホスト名に関連付けられたアドレスはありません
原因
RSpecでjs: trueを使用
RSpecで JavaScriptのテストを実装 したところローカル環境で通っていたテストがCircleCIの自動テストでは通りませんでした。
結論として、ローカル環境とCircleCIの環境の差異が原因かと思います。
ローカルではchromeコンテナを立ち上げて System Spec
を通していましたが、 CircleCI の設定ファイル
でも設定が必要なのでエラーが起きていました。
今回ローカル環境とCircleCI環境をあわせるために行った変更
- chromeコンテナ から Dockerfileで chrome を追加するようにしたこと
- Chrome使用時のURLを指定していたので削除したこと
-
CircleCI の設定ファイル
で Chrome の追加と background で使用するようにしたこと
解決策
spec/support/capybara.rb
大幅に変更したように見えますが、url
を指定していないというのがポイントです。
require 'capybara/rspec'
require 'selenium-webdriver'
module CapybaraSupport
Capybara.javascript_driver = :selenium_chrome_headless
Capybara.default_driver = :selenium_chrome_headless
Capybara.register_driver :selenium_chrome_headless do |app|
url = 'http://chrome:4444/wd/hub'
caps = ::Selenium::WebDriver::Remote::Capabilities.chrome(
'goog:chromeOptions' => {
'args' => [
'no-sandbox',
'headless',
'disable-gpu',
'window-size=1680,1050'
]
}
)
Capybara::Selenium::Driver.new(app, browser: :chrome, url: url, desired_capabilities: caps)
end
require 'capybara/rspec'
require 'selenium-webdriver'
Capybara.register_driver :selenium_chrome_headless do |app|
options = ::Selenium::WebDriver::Chrome::Options.new
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--window-size=1400,1400')
driver = Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end
Capybara.javascript_driver = :selenium_chrome_headless
spec/rails_helper.rb
RSpec.configure do |config|
config.before(:each, type: :system) do
driven_by :rack_test
end
config.before(:each, type: :system, js: true) do
driven_by :selenium_chrome_headless
end
end
Dockerfile
ローカル環境のテストで Chrome を使用したいので Dockerfile
で Chromeの追加 をしています。
この記述を RUN mkdir /myapp
の前に書きました。
RUN apt-get update && apt-get install -y unzip && \
CHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` && \
wget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P ~/ && \
unzip ~/chromedriver_linux64.zip -d ~/ && \
rm ~/chromedriver_linux64.zip && \
chown root:root ~/chromedriver && \
chmod 755 ~/chromedriver && \
mv ~/chromedriver /usr/bin/chromedriver && \
sh -c 'wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -' && \
sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' && \
apt-get update && apt-get install -y google-chrome-stable
# ルート直下にmyappという名前で作業ディレクトリを作成(コンテナ内のアプリケーションディレクトリ)
RUN mkdir /myapp
WORKDIR /myapp
.circleci/config.yml
CircleCIの設定ファイル。Chromeを追加 することで ローカル環境との差異 をなくすようにしました。
steps:
- run:
name: Chrome Driver Install
command: |
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update && sudo apt-get install -y unzip
wget -N http://chromedriver.storage.googleapis.com/87.0.4280.88/chromedriver_linux64.zip -P ~/
unzip ~/chromedriver_linux64.zip -d ~/
rm ~/chromedriver_linux64.zip
sudo chown root:root ~/chromedriver
sudo chmod 755 ~/chromedriver
sudo mv ~/chromedriver /usr/bin/chromedriver
sh -c 'wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -'
sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
sudo apt-get update && sudo apt-get install -y google-chrome-stable
background: true
2021/11/25追記
@tomoya128 さんからのコメントよりこの部分は以下のように記述できるとお聞きしました。
steps:
- run:
command: chromedriver
background: true
また、Ruby 2.5
以上を使用している場合は、webdrivers(gem)
を利用すると簡単に設定できるようです。
試してみてはどうでしょうか。
.circleci/config.yml 全体
RSpecを動かすところで no_output_timeout: 15m
と記述しています。
こちらはなくともテストには直接関係ないので削除しても大丈夫です。
なにも設定しなければ標準で10分の制限時間があり、それを過ぎるとタイムアウトエラーになってしまうので念の為付けております。テストの数とかにもよると思いますが、実際にはほんの数分で終わるので不要です。
version: 2
jobs:
build:
docker:
- image: circleci/ruby:2.6.6-node-browsers
environment:
- BUNDLER_VERSION: 2.0.2
- RAILS_ENV: 'test'
- image: circleci/mysql:8.0
command: [--default-authentication-plugin=mysql_native_password]
environment:
- MYSQL_USER: root
- MYSQL_DB: ci_test
- MYSQL_ROOT_HOST: "127.0.0.1"
working_directory: ~/myapp
steps:
- run:
name: Chrome Driver Install
command: |
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update && sudo apt-get install -y unzip
wget -N http://chromedriver.storage.googleapis.com/87.0.4280.88/chromedriver_linux64.zip -P ~/
unzip ~/chromedriver_linux64.zip -d ~/
rm ~/chromedriver_linux64.zip
sudo chown root:root ~/chromedriver
sudo chmod 755 ~/chromedriver
sudo mv ~/chromedriver /usr/bin/chromedriver
sh -c 'wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -'
sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
sudo apt-get update && sudo apt-get install -y google-chrome-stable
background: true
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
- v1-dependencies-
- run:
name: install dependencies
command: |
gem install bundler -v 2.0.2
bundle install --jobs=4 --retry=3 --path vendor/bundle
- save_cache:
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
paths:
- ./vendor/bundle
- run: mv config/database.yml.ci config/database.yml
- run: yarn install
- run: bundle exec rake db:create
- run: bundle exec rake db:schema:load
- run:
name: run tests
command: |
mkdir /tmp/test-results
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \
circleci tests split --split-by=timings)"
bundle exec rspec \
--format RspecJunitFormatter \
--out /tmp/test-results/rspec.xml \
--format progress \
$TEST_FILES
no_output_timeout: 15m
- store_test_results:
path: /tmp/test-results
- store_artifacts:
path: /tmp/test-results
destination: test-results
config/database.yml.ci
test:
adapter: mysql2
encoding: utf8
pool: 5
username: 'root'
port: 3306
host: '127.0.0.1'
database: ci_test
まとめ
-
Dockerfile
とCircleCIの設定ファイル
で Chromeを追加 - ローカルで通用してもCircleCI上で失敗することがある。
- ありがたいことに記事(情報)がたくさんあるので、その中で自分がどの問題に直面しているのかを理解することが大事。
おわりに
前回の記事に変更前の CircleCIの設定ファイル
があります。(厳密に言えば少しリファクタなどしています)
JavaScript適用前 ですが、 CircleCI
についてまとめていますのでよろしければご覧ください。