アプリケーションエンジニアが初めてserverspecに触ってみた
テストコードによるインフラのテスト
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
というコードでテストを行っている事が分かる。
今日はここまで。