テストコードによるインフラのテスト
serverspecはインフラの構築状況に対してテストコードによるテストを行うgemだ。
packageのインストール状況、serviceの起動状況、ポートの開放状況などの各種設定状況を、
rspecの文法でテストできる。
このserverspecと、サーバー構築自動化ツール(itamaeとか)を組み合わせて
環境構築をテストファーストで行う
TDI( = Test Driven Infrastructure = テスト駆動インフラ)などのコンセプトが登場しており大変興味深い。
個人の開発環境整備に使えないか
もちろんserverspecを使って個人の開発環境をテストする事が可能なようだ。
今回は、実現したい明確な目的があるわけでは無いが、 とりあえずこんな事に役立つかどうか知るために試しに触ってみた。
自身の開発環境構築
- 自分の開発環境をコマンド1つで、0から自動で構築できたら便利そう。
- まずは、
正しく構築できたか?をserverspecでテストしてみたい。
チームメンバーの開発環境構築
- チームで開発を行う時、新たに入ったメンバーが正しく環境を構築出来ているかチェックできたら便利そう。
- 「
rails/bin/setupした後に、serverspecでテストしてOKなら環境構築終了!」みたいな感じに出来たら良さそう。
インストール
gem install serverspec
init
serverspec-initを実行するとテンプレートファイルを生成してくれる。
$ serverspec-init Select OS type: 1) UN*X 2) Windows Select number: 1 Select a backend type: 1) SSH 2) Exec (local) Select number: 2 + spec/ + spec/localhost/ + spec/localhost/sample_spec.rb + spec/spec_helper.rb + Rakefile + .rspec
sshを選ぶとリモートホストに対してテストが行えるんだろう。今回はlocalを選択。
テストコード
- 書く。
# spec/localhost/sample_spec.rb require 'spec_helper' # middleware describe package("mysql") do it { should be_installed } end describe package("redis") do it { should be_installed } end describe package('rbenv') do it { should be_installed } end describe package('rails') do it { should be_installed.by('gem') } end # VCS describe package('git') do it { should be_installed } end describe package('tig') do it { should be_installed } end # development tools describe package('pry') do it { should be_installed.by('gem') } end describe command "ls /Applications | grep -q Atom" do its(:exit_status) { should eq 0 } end describe command "ls /Applications | grep -q Xcode" do its(:exit_status) { should eq 0 } end
実行
$ rake /Users/nagai_shinya/.rbenv/versions/2.1.0/bin/ruby -I/Users/nagai_shinya/.rbenv/versions/2.1.0/lib/ruby/gems/2.1.0/gems/rspec-support-3.2.1/lib:/Users/nagai_shinya/.rbenv/versions/2.1.0/lib/ruby/gems/2.1.0/gems/rspec-core-3.2.0/lib /Users/nagai_shinya/.rbenv/versions/2.1.0/lib/ruby/gems/2.1.0/gems/rspec-core-3.2.0/exe/rspec --pattern spec/localhost/\*_spec.rb Package "mysql" should be installed Package "redis" should be installed Package "rbenv" should be installed Package "rails" should be installed Package "git" should be installed Package "tig" should be installed Package "pry" should be installed Command "ls /Applications | grep -q Atom" exit_status should eq 0 Command "ls /Applications | grep -q Xcode" exit_status should eq 0 Finished in 2.47 seconds (files took 1.06 seconds to load) 9 examples, 0 failures
感想
- 便利そう。
- とりあえず各種packageのインストールが簡単にテスト出来た。
- インフラはアプリケーションに比べて内部状態が少ないし、
外部APIが絡むケースも少ないので、シンプルなテストコードだけで済む場合が多い印象。
MockとかStubとか使わなくて良さそう。#setupすらあまり使わないかも。- テストファーストの入門としては、
TDDよりTDIの方が入りやすいかもしれない。
あとで調べる
- インストールされた
packageのバージョンをテストする方法。 Applicationsへのインストールをテストする方法。custom matcherを書けば良さそう。
実際どういうコマンドが実行されているのか気になる。
- 失敗するテストを書けば分かるという気付きがあった。
例:
存在しないpackage名を指定してみる
describe package('pryyyyyyy') do it { should be_installed.by('gem') } end
結果:
Failures:
1) Package "pryyyyyyy" should be installed
On host `localhost'
Failure/Error: it { should be_installed.by('gem') }
expected Package "pryyyyyyy" to be installed
/bin/sh -c gem\ list\ --local\ \|\ grep\ -iw\ --\ \\\^pryyyyyyy
# ./spec/localhost/sample_spec.rb:31:in `block (2 levels) in <top (required)>'
/bin/sh -c gem\ list\ --local\ \|\ grep\ -iw\ --\ \\\^pryyyyyyy
というコードでテストを行っている事が分かる。
今日はここまで。