rspec3系 での serverspec JUnit.xml出力対応について(CentOS 6.x + rbenv + bundler + rspec_junit_formatter)
2015/04/20 コメントを残す
先日のCIお試し環境に、serverspecによるテストもJenkins対応しようとしたところ、webでよく見かけるci_reporterの構築事例が単純に再現できなくなりました。時間が経って昔のノウハウが単純に生かせなくなっているようです。ひと手間加え、ひとまず一般ユーザでJUnit.xml出力できるまで進めたので、いまどきのserverspec JUnit.xml対応として控えておきます。
問題点
serverspec単体では、RHEL6系に標準のRuby1.8.7でもスムーズに使えるのですが、JUnit.xml出力のための環境整備をしようとすると、以下のような問題にぶつかりました。
- 2014年6月よりRSpec 3がリリースされたことで、ci_reporterがうまく動かなくなった。
- 代替となりそうなrspec_junit_formatterは、依存するBuilder gemが必要。一方で、自分の環境Cent6系にバンドルされているruby 1.8系ではgemが見つからない。
ちなみに、ruby 1.8系環境でBundlerを使ってBuilderをインストールしようとすると以下のようなエラーとなります。
Could not find gem 'Builder (>= 0) ruby' in any of the gem sources listed in your Gemfile or installed on this machine. Run `bundle install` to install missing gems.
対応方向性
あえて古い環境を生かし続けるより、いまどきの事情に合わせて動くように整理してしまおうと思い、以下のようにしています。
- rbenvとBundlerで管理
- Ruby最新系(2.2.2)を適用
- RSpec 3系で実装
- rspec_junit_formatter でJUnit.xml出力を実現
環境
用途 | 台数 | ホスト名 | IP Address |
---|---|---|---|
テスト対象サーバ | 1 | stage01 | 192.168.0.101 |
CIサーバ | 1 | ci01 | 192.168.0.99 |
テスト対象サーバは予めhttpdをインストールし、スタートアップ設定とサービス起動を済ませてあります。また、hostsファイルで名前解決させています。sshログインユーザが異なるなどの場合は~/.ssh/configに定義を書いてパスワード入力なしでログインできるようにしておきます。
手順
すべてCIサーバ側の手順になります。
rbenvとruby-buildの準備
$HOME 直下に.rbenvを、また、.rbenvのpluginとしてruby-buildをそれぞれのレポジトリから持ってきます。
終わりましたら、.bash_prifuleまたは.bashrcなどにrbenvのPATHを通します。
[ci01 ~]$ sudo yum install -y gcc openssl-devel libyaml-devel libffi-devel readline-devel zlib-devel gdbm-devel ncurses-devel [ci01 ~]$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv [ci01 ~]$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build [ci01 ~]$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile [ci01 ~]$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile [ci01 ~]$ source ~/.bash_profile
念のため、rbenvコマンドが呼び出せるか確認しておきましょう。
[ci01 ~]$ rbenv --version rbenv 0.4.0-146-g7ad01b2
rbenvによるRuby最新系(2.2.2)のインストールと環境変数への設定
[ci01 ~]$ rbenv install --list Available versions: 1.8.6-p383 1.8.6-p420 (...中略...) 2.2.1 2.2.2 2.3.0-dev (...中略...) ree-1.8.7-2012.01 ree-1.8.7-2012.02 topaz-dev [ci01 ~]$ rbenv install 2.2.2 Downloading ruby-2.2.2.tar.gz... -> http://dqw8nmjcqpjn7.cloudfront.net/5ffc0f317e429e6b29d4a98ac521c3ce65481bfd22a8cf845fa02a7b113d9b44 Installing ruby-2.2.2... Installed ruby-2.2.2 to /home/admin01/.rbenv/versions/2.2.2 [ci01 ~]$ rbenv rehash [ci01 ~]$ rbenv versions 2.2.2 [ci01 ~]$ rbenv global system [ci01 ~]$ rbenv global 2.2.2 [ci01 ~]$ rbenv global 2.2.2 [ci01 ~]$
Bundlerによるgemインストール
[ci01 ~]$ rbenv exec gem install bundler [ci01 ~]$ rbenv rehash [ci01 ~]$ rbenv exec gem install bundler Fetching: bundler-1.9.4.gem (100%) Successfully installed bundler-1.9.4 Parsing documentation for bundler-1.9.4 Installing ri documentation for bundler-1.9.4 Done installing documentation for bundler after 6 seconds 1 gem installed [ci01 ~]$ rbenv rehash [ci01 ~]$ rbenv exec gem which bundler /home/***/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/bundler-1.9.4/lib/bundler.rb [ci01 ~]$
serverspec初期化と簡易テスト
serverspecディレクトリを作成し、その配下に環境を整備することとします。
[ci01 ~]$ mkdir serverspec [ci01 ~]$ cd serverspec [ci01 serverspec]$ rbenv exec bundle init Writing new Gemfile to /home/***/serverspec/Gemfile [ci01 serverspec]$ ls -al 合計 12 drwxr-xr-x 2 *** users 4096 4月 19 23:11 2015 . drwx------ 8 *** users 4096 4月 19 23:06 2015 .. -rw-r--r-- 1 *** users 64 4月 19 23:11 2015 Gemfile [ci01 serverspec]$ cat Gemfile # A sample Gemfile source "https://rubygems.org" # gem "rails" [ci01 serverspec]$ vi Gemfile [ci01 serverspec]$ [ci01 serverspec]$ cat Gemfile source "https://rubygems.org" gem "serverspec" gem "builder" gem "rspec_junit_formatter" [ci01 serverspec]$ rbenv exec bundle install --path vendor/bundle Fetching gem metadata from https://rubygems.org/....... Fetching version metadata from https://rubygems.org/.. Resolving dependencies... Installing builder 3.2.2 Installing diff-lcs 1.2.5 Installing multi_json 1.11.0 Installing net-ssh 2.9.2 Installing net-scp 1.2.1 Installing rspec-support 3.2.2 Installing rspec-core 3.2.3 Installing rspec-expectations 3.2.1 Installing rspec-mocks 3.2.1 Installing rspec 3.2.0 Installing rspec-its 1.2.0 Installing rspec_junit_formatter 0.2.0 Installing specinfra 2.29.0 Installing serverspec 2.14.1 Using bundler 1.9.4 Bundle complete! 3 Gemfile dependencies, 15 gems now installed. Bundled gems are installed into ./vendor/bundle. [ci01 serverspec]$ ls -al 合計 24 drwxr-xr-x 4 *** users 4096 4月 19 23:13 2015 . drwx------ 8 *** users 4096 4月 19 23:06 2015 .. drwxr-xr-x 2 *** users 4096 4月 19 23:13 2015 .bundle -rw-r--r-- 1 *** users 90 4月 19 23:12 2015 Gemfile -rw-r--r-- 1 *** users 976 4月 19 23:13 2015 Gemfile.lock drwxr-xr-x 3 *** users 4096 4月 19 23:13 2015 vendor [ci01 serverspec]$
serverspecの初期化をします。一度実行するとわかりますが、”set :request_pty, true”をspec_helper.rbに書き込んであげる必要がある場合があります。
[ci01 serverspec]$ rbenv exec bundle exec serverspec-init Select OS type: 1) UN*X 2) Windows Select number: 1 Select a backend type: 1) SSH 2) Exec (local) Select number: 1 Vagrant instance y/n: n Input target host name: stage01 + spec/ + spec/stage01/ + spec/stage01/sample_spec.rb + spec/spec_helper.rb + Rakefile [ci01 serverspec]$ [ci01 serverspec]$ rbenv exec bundle exec rake spec /home/***/.rbenv/versions/2.2.2/bin/ruby -I/home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-core-3.2.3/lib:/home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-support-3.2.2/lib /home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-core-3.2.3/exe/rspec --pattern spec/stage01/\*_spec.rb Please write "set :request_pty, true" in your spec_helper.rb or other appropriate file. /home/***/.rbenv/versions/2.2.2/bin/ruby -I/home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-core-3.2.3/lib:/home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-support-3.2.2/lib /home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-core-3.2.3/exe/rspec --pattern spec/stage01/\*_spec.rb failed [ci01 serverspec]$ [ci01 serverspec]$ vi spec/spec_helper.rb [ci01 serverspec]$ cat spec/spec_helper.rb require 'serverspec' require 'net/ssh' set :backend, :ssh set :request_pty, true if ENV['ASK_SUDO_PASSWORD'] begin require 'highline/import' rescue LoadError fail "highline is not available. Try installing it." end set :sudo_password, ask("Enter sudo password: ") { |q| q.echo = false } else set :sudo_password, ENV['SUDO_PASSWORD'] end host = ENV['TARGET_HOST'] options = Net::SSH::Config.for(host) options[:user] ||= Etc.getlogin set :host, options[:host_name] || host set :ssh_options, options # Disable sudo # set :disable_sudo, true # Set environment variables # set :env, :LANG => 'C', :LC_MESSAGES => 'C' # Set PATH # set :path, '/sbin:/usr/local/sbin:$PATH' [ci01 serverspec]$ rbenv exec bundle exec rake spec /home/***/.rbenv/versions/2.2.2/bin/ruby -I/home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-core-3.2.3/lib:/home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-support-3.2.2/lib /home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-core-3.2.3/exe/rspec --pattern spec/stage01/\*_spec.rb Package "httpd" should be installed Service "httpd" should be enabled should be running Port "80" should be listening Finished in 0.12344 seconds (files took 0.51911 seconds to load) 4 examples, 0 failures [ci01 serverspec]$
応用編
html出力
[ci01 serverspec]$ rbenv exec bundle exec rake spec SPEC_OPTS="--format html" /home/***/.rbenv/versions/2.2.2/bin/ruby -I/home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-core-3.2.3/lib:/home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-support-3.2.2/lib /home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-core-3.2.3/exe/rspec --pattern spec/stage01/\*_spec.rb (...出力略...) [ci01 serverspec]$
こんなのができます。
JUnit.xml出力
[ci01 serverspec]$ rbenv exec bundle exec rake spec SPEC_OPTS="--format RspecJunitFormatter --out spec/reports/rspec.xml" /home/***/.rbenv/versions/2.2.2/bin/ruby -I/home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-core-3.2.3/lib:/home/***/serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-support-3.2.2/lib /home/*** /serverspec/vendor/bundle/ruby/2.2.0/gems/rspec-core-3.2.3/exe/rspec --pattern spec/stage01/\*_spec.rb [ci01 serverspec]$ cat spec/reports/rspec.xml <?xml version="1.0" encoding="UTF-8"?> <testsuite name="rspec" tests="4" failures="0" errors="0" time="0.115013" timestamp="2015-04-20T00:05:50+09:00"> <properties/> <testcase classname="spec.stage01.sample_spec" name="Package "httpd" should be installed" time="0.036652"/> <testcase classname="spec.stage01.sample_spec" name="Service "httpd" should be enabled" time="0.020671"/> <testcase classname="spec.stage01.sample_spec" name="Service "httpd" should be running" time="0.035370"/> <testcase classname="spec.stage01.sample_spec" name="Port "80" should be listening" time="0.021414"/> </testsuite> [ci01 serverspec]$
動きました。
今日はここまで
Jenkinsでrbenv環境呼び出すためのセットアップ方法の細かい差異とか、実際にはserverspecをロールなどで繰り返しテストさせるためのテストコードのベストプラクティスとか、この先も多少気になることはありますが、ひとまず今日はここまでとします。もっといいやり方あるよとか、これだとまずいよとかあればフィードバックいただければ嬉しいです。
参照
今回は以下のサイトを参考にさせていただきました。ありがとうございます。
GitHub:ruby-build | Suggested build environment
https://github.com/sstephenson/ruby-build/wiki#suggested-build-environment
ncstudy | ncstudy#05 ハンズオン資料 2013/07/14 #ncstudy
http://tily.github.io/ncstudy05/
Developers.IO | rbenv を利用した Ruby 環境の構築
http://dev.classmethod.jp/server-side/language/build-ruby-environment-by-rbenv/
Developers.IO | Jenkinsの使い勝手をよくするための見直し6点
http://dev.classmethod.jp/tool/jenkins/jenkins-refactoring-jobs/
Qoosky | rbenvおよびbundlerの基本的な使用方法 @qoosky_dev
https://www.qoosky.net/references/128/
@znz blog | ci_reporter から rspec_junit_formatter に移行した
http://blog.n-z.jp/blog/2014-06-13-ci-reporter-to-rspec-junit-formatter.html
Into my web | [ruby]最初に知っておけば良かったbundlerの使い方 rails編
http://kozo002.blogspot.jp/2012/01/rubybundler.html