Dockerで始めるRSpec
モチベーション
"Effective Testing with RSpec 3"というRSpecの本を読み、RSpecをインストールしようとしたら、以下のようなエラーが発生した。
diff-lcs's executable "htmldiff" conflicts with /Users/mine/.rbenv/versions/2.7.2/bin/htmldiff Overwrite the executable? [yN] n
既存の環境を汚すのは嫌なので、Dockerで環境を作ってしまおうというのが記事のモチベーションとなっている。
また本が書かれたのが2017年とずいぶん昔なので、昔の環境を再現する手段としてもDockerは良いと考えた。
環境
- MacBook Pro(macOS Catalina)
- Ruby 2.5
- RSpec 3.6
書籍ではRuby 2.4となっていたが、docker hubのサポートバージョンで一番古いものが2.5だったので、とりあえず2.5にした。
ディレクトリ構成
% tree . ├── Dockerfile ├── Gemfile ├── Gemfile.lock ├── README.md └── apps
Dockerfile
FROM ruby:2.5.8 WORKDIR /apps COPY Gemfile Gemfile.lock ./ COPY ./apps /apps RUN bundle install
Gemfile
source 'https://rubygems.org' ruby '2.5.8' gem "rspec-rails", "3.6.0"
Gemfile.lock
は中身は空で、ファイルだけ作成する。
使い方
Dockerfileからイメージをビルドする。
% docker build -t rubyapp .
イメージができたことを確認する。
% docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
rubyapp latest bb1bec6a36e0 2 hours ago 888MB
イメージを利用する。 上で作成したrubyappというイメージから、rubyappというコンテナを作成する。
% docker run -dit --name rubyapp -v $PWD/apps:/apps rubyapp
docker run
というコマンドは
- docker pull
- docker create
- docker start
という3つの一連のコマンドをまとめて実行するコマンド。
Dockerのプロセスを確認する。
% docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ae232a4e65e4 rubyapp "irb" 8 minutes ago Up 8 minutes rubyapp
コンテナに入る。
% docker exec -it rubyapp bash
exec
はコンテナ内でコマンドを実行するという意味。
コンテナ内でRSpecのバージョンを確認する。
/apps# ruby -v ruby 2.5.8p224 (2020-03-31 revision 67882) [x86_64-linux] # rspec -v RSpec 3.6 - rspec-core 3.6.0 - rspec-expectations 3.6.0 - rspec-mocks 3.6.0 - rspec-rails 3.6.0 - rspec-support 3.6.0
コンテナを停止する。
% docker stop rubyapp_docker rubyapp_docker
最初のRSpecを書いてみる
以下のようなディレクトリ構成とする。
└── apps └── ch1 └── spec └── sandwich_spec.rb
上記のRubyファイルはホストコンピュータ(コンテナの外)から編集可能で、自分はRubyMineで編集している。
コンテナとファイルを共有するためにdocker run
するときに-v
でバインドするボリュームを指定したためである。
sandwich_spec.rb
は以下の通り。
Sandwich = Struct.new(:taste, :toppings) RSpec.describe 'An ideal sandwich' do it 'is delicious' do sandwich = Sandwich.new('delicious', []) taste = sandwich.taste expect(taste).to eq('delicious') end end
rspec
を実行するとテストの結果を見ることができる。
/apps/ch1# rspec . Finished in 0.00516 seconds (files took 0.09017 seconds to load) 1 example, 0 failures