serverspecを使ってみた

# とりあえず使ってみる
インストールしてみて、テストが１つ通るところを目標に使ってみます。

## インストール
とにかくインストールしてみましょう。Gemfileを作成します。

```ruby:Gemfile
source 'https://rubygems.org'
gem "rake", "~> 10.1.0"
gem "serverspec", "~> 0.11.5"
```

ローカルディレクトリにインストールしてみます。さて、準備は完了です。

```shell-session
$ bundle install --path=vendor/bundle
```

## テストのひな形を作成
早速テストを書いてみましょう。ひな形を用意してくれるコマンドがあるのでまずは実行してみます。
今回はlocalのPCに対してのテストを行ってみます。

```shell-session
$ 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: 2

 + spec/
 + spec/localhost/
 + spec/localhost/httpd_spec.rb
 + spec/spec_helper.rb
 + Rakefile
```

作られたファイルをみてみましょう。

```ruby:Rakefile
require 'rake'
require 'rspec/core/rake_task'

RSpec::Core::RakeTask.new(:spec) do |t|
  t.pattern = 'spec/*/*_spec.rb'
end
```

```ruby:spec/spec_helper.rb
require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end                                                                                                                        

describe service('httpd') do
  it { should be_enabled   }
  it { should be_running   }
end

describe port(80) do
  it { should be_listening }
end
                                                                                                                           
describe file('/etc/httpd/conf/httpd.conf') do
  it { should be_file }
  it { should contain "ServerName localhost" }
end
```

```ruby:spec/localhost/httpd_spec.rb
require 'serverspec'
require 'pathname'

include Serverspec::Helper::Exec
include Serverspec::Helper::DetectOS

RSpec.configure do |c|
  if ENV['ASK_SUDO_PASSWORD']
    require 'highline/import'
    c.sudo_password = ask("Enter sudo password: ") { |q| q.echo = false }
  else
    c.sudo_password = ENV['SUDO_PASSWORD']
  end
end
```

## テストしてみる
テストが失敗するのは分かっていますが、まずは実行してみましょう。

```shell-session
$ bundle exec rake spec
/usr/local/Cellar/ruby/2.0.0-p247/bin/ruby -S rspec spec/localhost/httpd_spec.rb
FFFFFgrep: /etc/httpd/conf/httpd.conf: No such file or directory
F

Failures:

  1) Package "httpd" should be installed
     Failure/Error: it { should be_installed }
     Serverspec::Commands::Base::NotImplementedError: 
       
       Serverspec::Commands::Base::NotImplementedError
     # ./spec/localhost/httpd_spec.rb:4:in `block (2 levels) in <top (required)>'

  2) Service "httpd" should be enabled
     Failure/Error: it { should be_enabled   }
     Serverspec::Commands::Base::NotImplementedError: 
       
       Serverspec::Commands::Base::NotImplementedError
     # ./spec/localhost/httpd_spec.rb:8:in `block (2 levels) in <top (required)>'

  3) Service "httpd" should be running
     Failure/Error: it { should be_running   }
       service httpd status
       sh: service: command not found
       expected Service "httpd" to be running
     # ./spec/localhost/httpd_spec.rb:9:in `block (2 levels) in <top (required)>'

  4) Port "80" should be listening
     Failure/Error: it { should be_listening }
       netstat -tunl | grep -- :80\ 
       expected Port "80" to be listening
     # ./spec/localhost/httpd_spec.rb:13:in `block (2 levels) in <top (required)>'

  5) File "/etc/httpd/conf/httpd.conf" should be file
     Failure/Error: it { should be_file }
       test -f /etc/httpd/conf/httpd.conf
       expected file? to return true, got false
     # ./spec/localhost/httpd_spec.rb:17:in `block (2 levels) in <top (required)>'

  6) File "/etc/httpd/conf/httpd.conf" should contain "ServerName localhost"
     Failure/Error: it { should contain "ServerName localhost" }
       grep -q -- ServerName\ localhost /etc/httpd/conf/httpd.conf || grep -qF -- ServerName\ localhost /etc/httpd/conf/ht
tpd.conf
       grep: /etc/httpd/conf/httpd.conf: No such file or directory
       expected File "/etc/httpd/conf/httpd.conf" to contain "ServerName localhost"
     # ./spec/localhost/httpd_spec.rb:18:in `block (2 levels) in <top (required)>'

Finished in 0.18825 seconds
6 examples, 6 failures

Failed examples:

rspec ./spec/localhost/httpd_spec.rb:4 # Package "httpd" should be installed
rspec ./spec/localhost/httpd_spec.rb:8 # Service "httpd" should be enabled
rspec ./spec/localhost/httpd_spec.rb:9 # Service "httpd" should be running
rspec ./spec/localhost/httpd_spec.rb:13 # Port "80" should be listening
rspec ./spec/localhost/httpd_spec.rb:17 # File "/etc/httpd/conf/httpd.conf" should be file
rspec ./spec/localhost/httpd_spec.rb:18 # File "/etc/httpd/conf/httpd.conf" should contain "ServerName localhost"
/usr/local/Cellar/ruby/2.0.0-p247/bin/ruby -S rspec spec/localhost/httpd_spec.rb failed
```

なるほど、結構泥臭いチェックを行っているんですね。
例えば、`it { should be_running   }`は`service httpd status`というコマンドの戻り値をみて判断しているみたいですね。
今回はMacBookAirで実行させているのでそもそも、serviceコマンドがないよ！！って怒られてテスト失敗してます。

## redisをインストールしてテストしてみる
`brew`コマンドで`redis`をインストールしてみましょう。
テスト項目はちょっと、簡単にして以下の物にしてみます。

* redis.confがあるか?


ひな形で作成された、httpd_rspec.rbをリネームして書き換えます。

```shell-session
$ mv spec/localhost/httpd_spec.rb spec/localhost/redis_spec.rb
```

```ruby:spec/localhost/redis_spec.rb
require 'spec_helper'

describe file('/usr/local/etc/redis.conf') do
  it { should be_file }
end
```

serverspecさんに怒られるの覚悟で実行してみます。

```shell-session
$bundle exec rake spec
/usr/local/Cellar/ruby/2.0.0-p247/bin/ruby -S rspec spec/localhost/redis_spec.rb
F

Failures:

  1) File "/usr/local/etc/redis.conf" should be file
     Failure/Error: it { should be_file }
       test -f /usr/local/etc/redis.conf
       expected file? to return true, got false
     # ./spec/localhost/redis_spec.rb:4:in `block (2 levels) in <top (required)>'

Finished in 0.12718 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/localhost/redis_spec.rb:4 # File "/usr/local/etc/redis.conf" should be file
/usr/local/Cellar/ruby/2.0.0-p247/bin/ruby -S rspec spec/localhost/redis_spec.rb failed
```

ふむふむ、redis.confがなくて怒っていますねw
あとはインストールしてredisを起動したら、テストが通ることを確認します。

```shell-session
$ brew install redis
$ bundle exec rake spec
/usr/local/Cellar/ruby/2.0.0-p247/bin/ruby -S rspec spec/localhost/redis_spec.rb
.

Finished in 0.1287 seconds
1 example, 0 failures
```

次回は、リモート環境について試験していきます。