株式会社リクルートテクノロジーズ Advent Calendar 2014の11日目の記事です。
werckerはDocker Boxのサポートをしています。
今つくっているソフトウェアはDockerコンテナとして動作させているため、Dockerfileのテストを行うためにweckerのbox内部でdocker
コマンドを実行しています。
はじめはDockerfile内でテストコマンドを実行していたのですが、開発中に気軽にコンテナをビルドしようとするとテストに時間がかかって煩わしくなりました。
最終的に「werckerでdocker build
後にdocker run
でテスト実行する」という方針にしてみたところ、まあまあいい感じに運用できています。
Dockerfile内でテスト実行する
Dockerfileというものを知ったときには、「この中でテストも全部してしまえば、CI環境でいろいろやらなくてもDockerfile単体で完結する!」と思いつき、実際にDockerfileの中でテストを走らせていたりもしました。
# Dockerコンテナ内部で使う自作gemのインストール
ADD builder /tmp/builder
WORKDIR /tmp/builder
RUN /opt/ruby-2.1.2/bin/bundle install --path=vendor/bundle
# テスト実行
RUN /opt/ruby-2.1.2/bin/bundle exec rake spec
RUN /usr/local/bin/gem build builder.gemspec
RUN /usr/local/bin/gem install builder-0.0.1.gem
しかし、実際にDockerfileを作ってみると、必要なライブラリやソフトウェアをインストールするだけでそれなりに時間がかかります。ここにテストの実行時間も加わると、やる気を削がれます。
また、開発中にDockerfileでADDしているモジュールを修正して試しに動かしてみようとすると、毎回ビルドとテストが走って待ちの時間が入るのでリズムを崩されてしまいます。
werckerでdocker build
後にdocker run
でテスト実行する
そこでDockerfileからテスト実行コマンドを取り除き、wercker.ymlを以下のように書き換えてみました。
box: wercker-labs/docker
build:
steps:
- script:
name: docker build
code: docker build -t pool ./docker/pool
- script:
name: run system test
# 実際には他にオプションを与えているのですが、見やすくするため省略します
code: |
sudo docker run -workdir="/tmp/builder" pool /opt/ruby-2.1.2/bin/bundle exec rspec --tag system_test
1度ビルドしたイメージでコンテナを起動させ、--workdir
オプションでテスト対象ディレクトリに移動、コマンドにテスト実行コマンドを指定することでテスト実行しています。
werckerでビルドされたイメージは次のscript
コマンド実行時も保持されているため、
-
docker build -t <イメージ名>
でテスト対象イメージを作成 - イメージ作成後に
docker run <イメージ名> <テスト実行コマンド>
でテスト
とすることによって、手元でコンテナを立ち上げる分には長時間かかるテストを実行せずにすみます。
werckerはブランチをプッシュすると自動でビルドを実行してくれて、Pull Requestにも実行結果が表示されるため、レビュー時には結合テストも通っているかが確認できます。
(落ちてます。。)
結合テスト環境としてのDockerコンテナについて
werckerに限らず、ビルドパイプライン中で「docker build
後にdocker run
でテスト実行する」というやり方は結合テストを実行する場合に便利ではないかと思います。
テストを実行する際には、実行環境の状態が等しいというのが理想ですが、毎回AWSのインスタンス+プロビジョニングツールなどの組み合わせでまっさらな環境を用意しているとテスト実行に時間がかかってしまいます。
しかし、テスト実行環境をDockerイメージとしてビルドした後にrunコマンドでテスト実行コマンドを与えてあげれば、毎回同じ状態の環境に対して異なるテストを実行してあげることができます。
結合テストの自動テストをやる際には、このやり方を試してみたいなと思っています。