Vagrant 環境で serverspec のサンプルテストが実行されるまでの流れをメモ


[Vagrant インストールから、仮想マシンの起動〜停止まで]( http://qiita.com/kasei-san/items/60fdda1e75e5d5b69be6) のつづき


## serverspec ってなあに?

- あるサーバの環境をテストするためのフレームワーク
- rspec 準拠の実装が可能
- 内部的には、コマンドを叩いているだけなので、chef 等の特定のプロビジョニングツールに依存していない
- プロビジョニングツールと組み合わせることで、TDDライクにサーバ環境の構築が可能

## CentOS6.5 の box を 取得

```shell-session
# 作業している回線が細かったので最小構成のやつを取得
$ wget https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box
```

## box を vagrant に追加

```shell-session
$ vagrant box add centos6.5 centos65-x86_64-20140116.box
==> box: Adding box 'centos6.5' (v0) for provider:
    box: Downloading: file:///Users/kasei_san/disk/centos65-x86_64-20140116.box
==> box: Successfully added box 'centos6.5' (v0) for 'virtualbox'!

$ vagrant box list
centos6.5 (virtualbox)
```

## 作業ディレクトリの用意

```shell-session
$ mkdir vagrant
```
git init しておく

```shell-session
$ git init
Initialized empty Git repository in /Users/kasei_san/vagrant/.git/
```

## vagrant 初期化

```shell-session
$ vagrant init
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

$ vim Vagrantfile
config.vm.box = "centos6.5"  # 使用するboxを定義
```

## 起動確認

```shell-session
$ vagrant up

Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'centos6.5'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: vagrant_default_1395543270228_23583
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 => 2222 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Error: Connection timeout. Retrying...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
    default: The guest additions on this VM do not match the installed version of
    default: VirtualBox! In most cases this is fine, but in rare cases it can
    default: prevent things such as shared folders from working properly. If you see
    default: shared folder errors, please make sure the guest additions within the
    default: virtual machine match the version of VirtualBox you have installed on
    default: your host and reload your VM.
    default:
    default: Guest Additions Version: 4.3.6
    default: VirtualBox Version: 4.1
==> default: Mounting shared folders...
    default: /vagrant => /Users/kasei_san/vagrant
```

## 停止

```shell-session
$ vagrant halt
```

1度 commit

```shell-session
$ git commit -m "add Vagrantfile"
```

## serverspec 導入

bundler を使ってインストール

```shell-session
$ bundle init
Writing new Gemfile to /Users/kasei_san/vagrant/Gemfile

$ cat Gemfile
source "http://rubygems.org"
gem "serverspec"

$ bundle install --path vendor/bundle
Fetching source index for http://rubygems.org/
Installing diff-lcs (1.2.5)
Installing highline (1.6.21)
Installing net-ssh (2.8.0)
Installing rspec-core (2.14.8)
Installing rspec-expectations (2.14.5)
Installing rspec-mocks (2.14.6)
Installing rspec (2.14.1)
Installing specinfra (0.8.0)
Installing serverspec (0.15.5)
Using bundler (1.0.15)
Your bundle is complete! It was installed into ./vendor/bundle
```

vendor/bundle を、.gitignore で無視

```shell-session
$ cat .gitignore
vendor/bundle
.bundle
```

Gemfile, Gemfile.lock はリポジトリに入れとく

```shell-session
$ git add .gitignore
$ git add Gemfile Gemfile.lock
$ git commit -m "add serverspec gem"
```

## serverspec 初期化

```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: 1

Vagrant instance y/n: y
Auto-configure Vagrant from Vagrantfile? y/n: y
 + spec/
 + spec/default/
 + spec/default/httpd_spec.rb
 + spec/spec_helper.rb
 + Rakefile
````

spec_helper と、サンプルっぽい spec が格納される

```shell-session
$ tree spec/
spec/
├── default
│   └── httpd_spec.rb
└── spec_helper.rb

1 directory, 2 files
```

```shell-session
$ cat spec/default/httpd_spec.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 }
  its(:content) { should match /ServerName default/ }
end
```

- ちなみに、spec_helper.rb を見ると、テスト実行時に、vagrant up して、ログインしているのが判る


## テスト実行

```shell-session
$ bundle exec rake spec
```


rake が無いと怒られたので、Gemfileに追加

```shell-session
$ git diff Gemfile
diff --git a/Gemfile b/Gemfile
index ef39b32..a4b5f3f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,2 +1,3 @@
 source "http://rubygems.org"
 gem "serverspec"
+gem "rake"
```

```shell-session
$ bundle install --path vendor/bundle
$ git add Gemfile Gemfile.lock
$ git commit -m "add rake gem"
```

## もっかいテスト

```shell-session
$ bundle exec rake spec
/Users/kasei_san/.rvm/rubies/ruby-1.9.2-p290/bin/ruby -S rspec spec/default/httpd_spec.rb
FFFFFF

Failures:

  1) Package "httpd" should be installed
     Failure/Error: it { should be_installed }
       sudo rpm -q httpd
       package httpd is not installed
       expected Package "httpd" to be installed
     # ./spec/default/httpd_spec.rb:4:in `block (2 levels) in <top (required)>'

  2) Service "httpd" should be enabled
     Failure/Error: it { should be_enabled   }
       sudo chkconfig --list httpd | grep 3:on
       expected Service "httpd" to be enabled
     # ./spec/default/httpd_spec.rb:8:in `block (2 levels) in <top (required)>'

  3) Service "httpd" should be running
     Failure/Error: it { should be_running   }
       sudo ps aux | grep -w -- httpd | grep -qv grep
       expected Service "httpd" to be running
     # ./spec/default/httpd_spec.rb:9:in `block (2 levels) in <top (required)>'

  4) Port "80" should be listening
     Failure/Error: it { should be_listening }
       sudo netstat -tunl | grep -- :80\ 
       expected Port "80" to be listening
     # ./spec/default/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 }
       sudo test -f /etc/httpd/conf/httpd.conf
       expected file? to return true, got false
     # ./spec/default/httpd_spec.rb:17:in `block (2 levels) in <top (required)>'

  6) File "/etc/httpd/conf/httpd.conf" content should match /ServerName default/
     Failure/Error: its(:content) { should match /ServerName default/ }
       sudo cat /etc/httpd/conf/httpd.conf 2> /dev/null || sudo echo -n
       expected "" to match /ServerName default/
       Diff:
       @@ -1,2 +1,2 @@
       -/ServerName default/
       +""
     # ./spec/default/httpd_spec.rb:18:in `block (2 levels) in <top (required)>'

Finished in 3.86 seconds
6 examples, 6 failures

Failed examples:

rspec ./spec/default/httpd_spec.rb:4 # Package "httpd" should be installed
rspec ./spec/default/httpd_spec.rb:8 # Service "httpd" should be enabled
rspec ./spec/default/httpd_spec.rb:9 # Service "httpd" should be running
rspec ./spec/default/httpd_spec.rb:13 # Port "80" should be listening
rspec ./spec/default/httpd_spec.rb:17 # File "/etc/httpd/conf/httpd.conf" should be file
rspec ./spec/default/httpd_spec.rb:18 # File "/etc/httpd/conf/httpd.conf" content should match /ServerName default/
```

予想通り失敗

## 見づらいので色をつける

```shell-session
$cat .rspec
--color
```

まずはここまで

## 参考

- [serverspecでサーバ環境のテストを書いてみよう](http://www.slideshare.net/ikedai/serverspec)
- [Ruby - serverspecの使い方 - Qiita](http://qiita.com/ando-masaki/items/b03342b465b7159ffe1f)

## 続き

- [Vagrant の provisioning を使って、ruby をコードからインストールしてみる](http://qiita.com/kasei-san/items/f06b689a02672f153632)