Test-KitchenでShell-VerifierとDockerCli-Driverで高速にServerspecテストを回す

# 経緯
こちらの[Test-KitchenでServerspecやInfratasterをShell-Verifierから実行](http://qiita.com/sawanoboly/items/4898bb4f277e5cacfb6c)の最後の方で以下のように書かれていました。

> さて、verifyステップが早くなったので、Vagrantドライバーではインスタンス作成に要する時間が目立ちます。
コーヒーのおかわりを汲みに行ってもいいんですが、ここでさらにkitchen-docker_cliなどと併用すると、kitchen testが休憩を取る間もなく終わるようになりますね。

振りかな？って思ってやってみます。

たしかに、インスタンスの作成とbusserによる諸々のインストールの時間がほとんど無くなるので、かなり速くなりそうですね。

ちなみにDockerCli-Driverってなんだという方は[この辺](http://qiita.com/Marcy/items/5814a2ae647a6e25a44d#%E6%A7%8B%E6%88%90%E6%96%B9%E6%B3%95)をば。

# 準備
こんな感じで。

```rb:Gemfile
source "https://rubygems.org"

gem 'kitchen-verifier-shell'
gem 'kitchen-docker_cli'
gem 'kitchen-vagrant'
gem 'serverspec'
gem 'docker-api'
```

`.kitchen.yml`はsuite毎にDriverを替えたりは普通はあまりしないので、ちょっと変則気味です。[^1]

```yaml:.kitchen.yml
---
provisioner:
  name: chef_zero

platforms:
  - name: ubuntu-14.04

suites:
  - name: vagrant
    driver:
      name: vagrant
    run_list:
      - recipe[example::default]
      # デフォルトのbusserでServerspec実行
  - name: docker_cli
    driver:
      name: docker_cli
    transport:
      name: docker_cli
    run_list:
      - recipe[example::default]
    verifier:
      name: shell
      command: ./bin/rspec test/integration/docker_cli/serverspec/example_spec.rb
      # ローカルからshell-verifierでServerspec実行
```

プロビジョンに使うbootstrap.shを、[参考元記事](http://qiita.com/sawanoboly/items/4898bb4f277e5cacfb6c)と同じで適当に・・・と思ったんですがbusserはChef(omnibus)で使ってるRubyで動くのでrecipeを用意します。

```rb:recipes/default.rb
execute 'apt-get update -y' do
  user 'root'
end

package 'nginx'
````

`Vagrant-Driver`×`Busser-Verifier`のServerspecの内容は特筆すべき点はありませんが、こんな感じ。

```rb:test/integration/vagrant/serverspec/example_spec.rb
require 'serverspec'

set :backend, :exec

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

`DockerCli-Driver`×`Shell-Verifier`のServerspecの内容におけるポイントは一点。
Shell-Verifierは`KITCHEN_XXX`という環境変数でDriverからインスタンスのstate情報を受け取る仕様（2015.07.03現在）ですので、Serverspec(Specinfra)のDocker Backendで使用するコンテナIDを`KITCHEN_CONTAINER_ID`という環境変数を使って指定します。

```rb:test/integration/docker_cli/serverspec/example_spec.rb
require 'serverspec'

set :backend, :docker
set :docker_container, ENV['KITCHEN_CONTAINER_ID']

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

# 比べてみよう

```shell-session:Vagrant-Driver
$ time ./bin/kitchen test vagrant -l warn

real	4m14.127s
user	0m11.521s
sys 	0m3.548s
```

```shell-session:DockerCli-Driver
$ time ./bin/kitchen test docker-cli -l warn

.

Finished in 4.27 seconds (files took 0.54292 seconds to load)
1 example, 0 failures


real	1m57.060s
user	0m4.537s
sys 	0m0.932s
```

**4分強→2分弱で半分以下**になりました。コーヒーを入れる時間があるかはコーヒーメーカーまでの距離次第って感じですが、かなり違いますね。

ちなみに、Verifier方式の差異を除いてDriver間の違いを見るために`converge`を流すとこんな感じ。

```shell-session:Vagrant-Driver
$ time ./bin/kitchen converge vagrant -l warn

real	2m46.553s
user	0m6.068s
sys 	0m2.041s
```

```shell-session:DockerCli-Driver
$ time ./bin/kitchen converge docker-cli -l warn

real	1m27.959s
user	0m3.111s
sys 	0m0.603s
```

これも**半分くらい**でしたね。

**4分強**のうち**１分強はChefのインストールとプロビジョニングが占めている**ので、私の環境（MBA2013mid特盛り）では**Vagrant-Driver→DockerCli-Driver、Busser-Verifier→Shell-Verifierの変更でそれぞれ１分強の短縮という感じ**かと思います。

[^1]: 普段やるとしたら、ファイルシステムに触るとかでDockerコンテナ上じゃ実行できないやつがたまにあるので、その時だけ切り替えるとかくらい