why
Wercker上でのspecテスト完遂に30分ほど要するが、その時間を短縮して開発効率を改善したい。
※Wercker:Oracle提供のCIツール
what
テストを並列実行する。
how
Ruby:2.2.3
Rails:5.0.0.1
RSpec:3.5.2
MYSQL2:0.4.5
local開発環境での実行
テスト並列実行用のgem "parallel_tests" を導入。
gemfile
に parallel_test を追加。
group :development, :test do
gem 'parallel_tests'
end
gemパッケージをインストール。
$ bundle install
test用DB名に テスト環境変数 を追加
test:
database: yourproject_test<%= ENV['TEST_ENV_NUMBER'] %>
テスト用DB:yourproject_testの複製
config/database.yml
の設定に応じてDBを作成。
$ bundle exec rake parallel:create RAILS_ENV=test
schemaコピー
$ bundle exec rake parallel:prepare[4]
rspec_test実行
$ bundle exec rake parallel:spec[4]
※[]
は並列実行させるプロセス数
Wercker環境での実行
WerckerのdockerコンテナにDB作成
services
The services statement allows you to start additional Docker containers and have them available (on the same Docker network) for your main container, i.e. the one that is running your pipeline.
Services may be specified at the top level, in which case they will be available to all pipelines defined in the wercker.yml, or you can define them inside a particular pipeline statement.
Each entry in the list follows the same syntax as the box statement.
DBを使う場合、 service
にDB用の docker イメージを選択。
DBの設定は env
オプションで指定。
services:
- id: mysql:<version>
env:
MYSQL_USER: *** # DBのuser名
MYSQL_PASSWORD: *** # DBのpassword
MYSQL_DATABASE: *** # DBの名前
後の rails-database-yml
コマンドは services/env
プロパティで指定した内容の database.yml
(DB名、ユーザー名、パスワードのDB)を作成。
build:
steps:
- rails-database-yml
Werckerの同一dockerコンテナでDB複製
Initializing a fresh instance
When a container is started for the first time, a new database with the specified name will be created and initialized with the provided configuration variables. Furthermore, it will execute files with extensions .sh, .sql and .sql.gz that are found in /docker-entrypoint-initdb.d. Files will be executed in alphabetical order. You can easily populate your mysql services by mounting a SQL dump into that directory and provide custom images with contributed data. SQL files will be imported by default to the database specified by the MYSQL_DATABASE variable.
コンテナーが初めて開始されると、指定された名前の新しいデータベースが作成され、提供されている構成変数で初期化されます。 さらに、/ docker-entrypoint-initdb.dにある拡張子.sh、.sql、および.sql.gzのファイルを実行します。 ファイルはアルファベット順に実行されます。
というわけで、
/docker-entrypoint-initdb.d
にSQLファイルを置いたりすればいい感じにできます。
が、SQLファイルでは、MYSQL_DATABASE
に指定したDBに対してダンプファイルを流すだけですので、他のDBを作ったりすることはできません。
services:
- id: mysql:5.7.21
env:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_USER: testuser
MYSQL_PASSWORD: testuser
MYSQL_DATABASE: testdb
volumes:
- "./mysql:/var/lib/mysql"
- "./mysql/init:/docker-entrypoint-initdb.d"
DB は 1_create_db.sql
にて作成
create database test_db1;
create database test_db2;
+ wercker.yml
+- mysql
+- init
+ 1_create_db.sql
実行結果=failed
config/database.yml already exists and will be overwritten
Auto detecting service
failed: Unable to auto detect service; please set "service" option
box
Rubyのdockerイメージを選択する。
volumes
volumes = docker run -v ./host/path:/container/path my_image
volumes で指定したホストのディレクトリがマウントされるタイミング = コンテナが起動した時
volumesのインデントを services に合わせる
services:
- id: mysql:5.7.21
env:
MYSQL_ROOT_PASSWORD: ***
MYSQL_USER: ***
MYSQL_PASSWORD: ***
MYSQL_DATABASE: ***
volumes:
- ./sql:/docker-entrypoint-initdb.d
ActiveRecord::AdapterNotSpecified: 'development' database is not configured. Available: ["test"]
このとき rails-database-yml
のレスポンスは下記
+ wercker.yml
+- sql
+ 000_create_db.sql
config/database.yml already exists and will be overwritten
Auto detecting service
Generating mysql docker template
test:
adapter: mysql2
encoding: utf8
database: <%= ENV['MYSQL_ENV_MYSQL_DATABASE'] %><%= ENV['TEST_ENV_NUMBER'] %>
username: <%= ENV['MYSQL_ENV_MYSQL_USER'] %>
password: <%= ENV['MYSQL_ENV_MYSQL_PASSWORD'] %>
host: <%= ENV['MYSQL_PORT_3306_TCP_ADDR'] %>
port: <%= ENV['MYSQL_PORT_3306_TCP_PORT'] %>
DB schema load
RAILS_ENV=test bundle exec rake db:migrate:reset
Mysql2::Error: Access denied for user 'testuser'@'%' to database '***'
multiple services
Wercker Documentation > Administration > Services を参考に修正
Services are separate containers that run alongside your Pipelines. Examples of services are testing databases and message queues. You specify service containers in your wercker.yml file through the services section:
services:
- name: testdb
id: mysql:5.7.21
env:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_USER: testuser
MYSQL_PASSWORD: testuser
MYSQL_DATABASES: testdb
- name: testdb2
id: mysql:5.7.21
env:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_USER: testuser
MYSQL_PASSWORD: testuser
MYSQL_DATABASES: testdb
- name: testdb3
id: mysql:5.7.21
env:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_USER: testuser
MYSQL_PASSWORD: testuser
MYSQL_DATABASES: testdb
- name: testdb4
id: mysql:5.7.21
env:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_USER: testuser
MYSQL_PASSWORD: testuser
MYSQL_DATABASES: testdb
failed: Unable to auto detect service; please set "service" option
参考
- docker-composeでmysql使うとき初回起動時に複数のDBを作る方法
- MySQL Docker Official Images
- wercker/docker-compose support? #63
- DockerでMySQL/PostgreSQLの初期データが生成されないときに確認すること
- github/docker-library/mysql/5.5/docker-entrypoint.sh
- Docker MySQL公式イメージを使用してDBに初期データを流し込む
- × RSpec + parallel_tests + CircleCIで並列テストする
- ユーザ権限の確認・追加
- Wercker Documentation > Administration > Services