6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Shellで構築、Shellでテストする Test-Kitchen

Last updated at Posted at 2015-04-03

Test-Kitchenを手っ取り早くはじめるには、シェルスクリプトを使うのがいい :fork_and_knife:
シェルで構築シェルでテストする例を作ってみた。

Test-Kitchen環境の準備

手元に必要なものはこの通り。

  • Ruby
    • Gem: Bundler
  • Vagrant

Gemfileには2つのGemを書こう。

Gemfile
source "https://rubygems.org"

gem 'test-kitchen'
gem 'kitchen-vagrant'

bundleでは(とりあえず)--binstubs./binに各種コマンドが入るようにしておくとこのチュートリアルでは楽。

$ bundle install --binstubs --path=vendor/bundle
Fetching gem metadata from https://rubygems.org/..........
Fetching version metadata from https://rubygems.org/..
Resolving dependencies...
Installing safe_yaml 1.0.4
Installing net-ssh 2.9.2
Using bundler 1.9.2
Installing mixlib-shellout 2.0.1
Installing net-scp 1.2.1
Installing thor 0.19.1
Installing test-kitchen 1.3.1
Installing kitchen-vagrant 0.16.0
Bundle complete! 2 Gemfile dependencies, 8 gems now installed.
Bundled gems are installed into ./vendor/bundle.

※ direnvでlayout rubyをしていればコマンドはbundleだけでもOK。このへんは各自のスタイルで。

./bin/kitchenとしてコマンドが叩けるようになっているはず。

$ ./bin/kitchen -v
Test Kitchen version 1.3.1

次はkitchen initでひな形を作成しよう。

 $ ./bin/kitchen init
      create  .kitchen.yml
      create  test/integration/default

.kitchen.ymlとdiagnose

とりあえず試したいならこの項は無視して、VMにShellを流してみようまで飛んでOK。

初期の.kitchen.ymlはこうなっている、Shell用に書き換えよう。

---
driver:
  name: vagrant

provisioner:
  name: chef_solo

platforms:
  - name: ubuntu-12.04
  - name: centos-6.4

suites:
  - name: default
    run_list:
    attributes:

書き換え対象は2箇所、次の通り。

---
driver:
  name: vagrant

provisioner:
  name: shell    ## Shellに変更

platforms:
  - name: ubuntu-14.04  ## ubuntu-14.04のみに変更

suites:
  - name: default
    run_list:
    attributes:

kitchen listではテストに使うVMの一覧が表示される。次のように出力されないならもう一度.kitchen.ymlを見直そう。

$ ./bin/kitchen list
Instance             Driver   Provisioner  Last Action
default-ubuntu-1404  Vagrant  Shell        <Not Created>

Diagnose

Test-Kitchenは設定の記述場所によって色々な要素が上書きされたりマージされたりする(まるでChefのAttributesだ! :knife: )。
幸い各種設定がどのように反映されているか確認するためのkitchen diagnoseコマンドが用意されているので、設定の重なり具合をいつでも確認できる。

さっきの.kitchen.ymlでdiagnoseを表示してみよう。

$ ./bin/kitchen diagnose default-ubuntu-1404
---
timestamp: 2015-04-03 04:06:20 UTC
kitchen_version: 1.3.1
instances:
  default-ubuntu-1404:
    state_file: {}
    driver:
      box: opscode-ubuntu-14.04
      box_check_update: 
      box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-14.04_chef-provisionerless.box
      box_version: 
      customize: {}
      gui: 
      kitchen_root: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen"
      log_level: :info
      name: vagrant
      network: []
      port: 22
      pre_create_command: 
      provider: virtualbox
      provision: false
      ssh: {}
      sudo: true
      synced_folders: []
      test_base_path: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen/test/integration"
      vagrantfile_erb: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen/vendor/bundle/ruby/2.2.0/gems/kitchen-vagrant-0.16.0/templates/Vagrantfile.erb"
      vagrantfiles: []
      vm_hostname: default-ubuntu-1404
    provisioner:
      data_path: 
      kitchen_root: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen"
      log_level: :info
      name: shell
      root_path: "/tmp/kitchen"
      script: 
      sudo: true
      test_base_path: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen/test/integration"
    busser:
      busser_bin: "/tmp/busser/bin/busser"
      kitchen_root: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen"
      root_path: "/tmp/busser"
      ruby_bindir: "/opt/chef/embedded/bin"
      sudo: true
      suite_name: default
      test_base_path: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen/test/integration"
      version: busser

とりあえず今はprovisioner:に注目してみよう。
Test-Kitchenのコマンドや対象は正規表現で解釈されるので、kitchen diagnose default-ubuntu-1404kitchen diag ubuなりと省略できる。

$ ./bin/kitchen diag ubu | grep 'provisioner:' -A 8
    provisioner:
      data_path: 
      kitchen_root: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen"
      log_level: :info
      name: shell
      root_path: "/tmp/kitchen"
      script: 
      sudo: true
      test_base_path: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen/test/integration"

script:が実行対象っぽさを醸し出しているね。
ここにはbootstrap.sh(プラットフォームによってはbootstrap.ps1)というファイルがあれば自動でそれが使われるようになっている。
もちろん.kitchen.ymlで指定してもいい。

VMにShellを流してみよう - kitchen converge

.kitchen.ymlを次のように編集してある状態から。前項を飛ばした人は編集してね。

.kitchen.yml(再掲)
---
driver:
  name: vagrant

provisioner:
  name: shell

platforms:
  - name: ubuntu-14.04

suites:
  - name: default
    run_list:
    attributes:

bootstrap.shという名前でファイルを作成すると、VM内で実行する対象として勝手に選択される。

$ touch bootstrap.sh

$ ./bin/kitchen diag ubu | grep 'provisioner:' -A 8
    provisioner:
      data_path: 
      kitchen_root: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen"
      log_level: :info
      name: shell
      root_path: "/tmp/kitchen"
>>> 検出された。
      script: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen/bootstrap.sh"   
<<<
      sudo: true
      test_base_path: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen/test/integration"

bootstrap.shに書いた内容は実行時にちょっとラップされる、次のように。

sh -c '

bootstrap.shに書いた内容がここに入る

'

'(シングルクォート)でくくられているけど、数さえ合っていればスクリプト内で'を使う分には問題ない。

bootstrap.shに処理を書いて実行する

とりあえずNginxでもいれとくか。

bootstrap.sh
sudo apt-get update
sudo apt-get -y install nginx

準備ができたらkitchen converge ubuで。

 $ ./bin/kitchen converge ubu
-----> Starting Kitchen (v1.3.1)
-----> Creating <default-ubuntu-1404>...
       Bringing machine 'default' up with 'virtualbox' provider...
       ==> default: Importing base box 'opscode-ubuntu-14.04'...

(略) apt-get updateが始まる
-----> Converging <default-ubuntu-1404>...
       Preparing files for transfer
       Preparing script
       Transferring files to <default-ubuntu-1404>
Ign http://us.archive.ubuntu.com trusty InRelease                           
Ign http://security.ubuntu.com trusty-security InRelease
Ign http://us.archive.ubuntu.com trusty-updates InRelease
Get:1 http://security.ubuntu.com trusty-security Release.gpg [933 B]
Ign http://us.archive.ubuntu.com trusty-backports InRelease                    
Get:2 http://us.archive.ubuntu.com trusty Release.gpg [933 B]                  
Get:3 http://security.ubuntu.com trusty-security Release [63.5 kB]             
Get:4 http://us.archive.ubuntu.com trusty-updates Release.gpg [933 B]          
Get:5 http://us.archive.ubuntu.com trusty-backports Release.gpg [933 B]        
Get:6 http://us.archive.ubuntu.com trusty Release [58.5 kB]                    
Get:7 http://security.ubuntu.com trusty-security/main Sources [76.1 kB]        
(略)

       Processing triggers for ureadahead (0.100.0-16) ...
       Setting up nginx-core (1.4.6-1ubuntu3.2) ...
       Setting up nginx (1.4.6-1ubuntu3.2) ...
       Processing triggers for libc-bin (2.19-0ubuntu6) ...
       Finished converging <default-ubuntu-1404> (1m19.28s).
-----> Kitchen is finished. (1m19.50s)

Nginx入ったね。

batsでVMをテストしてみよう - kitchen verify

テスト用の環境はTest-Kitchen関連プロダクトのbusserを使って用意される。

kitchen diagで軽くbusser周りを確認してみよう。

$ ./bin/kitchen diag ubu | grep busser: -A 8
    busser:
      busser_bin: "/tmp/busser/bin/busser"
      kitchen_root: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen"
      root_path: "/tmp/busser"
      ruby_bindir: "/opt/chef/embedded/bin"
      sudo: true
      suite_name: default
      test_base_path: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen/test/integration"
      version: busser

ruby_bindirがあることから分かる通り、Test-Kitchenではテストの実行にはVMの中にRubyが必要なんだ。

RubyとBusser

Ruby入れたくない? そうだよね。

でもテスト用のVMにくらい入れたっていいじゃない。初期構築のbootstrap.shにちょっと分岐を作らせてよ。

bootstrap.sh
sudo apt-get update
sudo apt-get -y install nginx


## For busser
if [ "vagrant" = "$SUDO_USER" ];then
  sudo apt-get -y install ruby2.0
fi

bootstrap.shを更新したら、もう一度kitchen conv ubuして、Rubyのインストールを済ませておきましょう。

Rubyのインストールに問題がなければ、.kitchen.ymlにBusserのruby_bindirを上書きするよう仕向けます。

.kitchen.yml
---
driver:
  name: vagrant

provisioner:
  name: shell

platforms:
  - name: ubuntu-14.04
    busser:
      ruby_bindir: /usr/bin     ## さっきのRubyへのパス

suites:
  - name: default
    run_list:
    attributes:

kitchen diag ubuでもかくにん。

 $ ./bin/kitchen diag ubu | grep busser: -A 8
    busser:
      busser_bin: "/tmp/busser/bin/busser"
      kitchen_root: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen"
      root_path: "/tmp/busser"
      ruby_bindir: "/usr/bin"  ## .kitchen.ymlに書いた値で上書き
      sudo: true
      suite_name: default
      test_base_path: "/Users/sawanoboriyu/github/higanworks/shell-test-kitchen/test/integration"
      version: busser

これでテスト実施の環境は整いました。

Batsのテストを書く

今日テストで使うBatsは別にRubyが必要ってわけではなく、Shellで書かれたShellの実行結果をテストするためのライブラリだ。

batsディレクトリを作成しよう。

$ mkdir test/integration/default/bats

ではBatsによるコマンド実行&出力チェックのテストをtest/integration/default/bats/nginx.batsに書いていこう。
@testの直後に何をテストするかの注釈、そしてブレスでテストを囲めばいい。

test/integration/default/bats/nginx.bats
@test "it should exists nginx bin with supports TLS SNI" {
  run nginx -V
  [ "$status" -eq 0 ]   ## ExitStatusが0か
  [ "${lines[2]}" = "TLS SNI support enabled" ]  ## 出力の2行目をチェック
}

@test "it should exists nginx process" {
  run pgrep nginx
  [ "$status" -eq 0 ]
}

ファイルを保存したらkitchen verify ubuでBatsのテストが実行される。

$ ./bin/kitchen verify ubu
-----> Starting Kitchen (v1.3.1)
-----> Setting up <default-ubuntu-1404>...
Fetching: thor-0.19.0.gem (100%)
Fetching: busser-0.7.0.gem (100%)
       Successfully installed thor-0.19.0
       Successfully installed busser-0.7.0
       2 gems installed
-----> Setting up Busser
       Creating BUSSER_ROOT in /tmp/busser
       Creating busser binstub
       Plugin bats installed (version 0.3.0)
-----> Running postinstall for bats plugin
       Installed Bats to /tmp/busser/vendor/bats/bin/bats
       Finished setting up <default-ubuntu-1404> (1m1.08s).
-----> Verifying <default-ubuntu-1404>...
       Suite path directory /tmp/busser/suites does not exist, skipping.
       Uploading /tmp/busser/suites/bats/nginx.bats (mode=0644)



>>> ここからテスト

-----> Running bats test suite
 ✓ it should exists nginx bin with supports TLS SNI
 ✓ it should exists nginx process
       
       2 tests, 0 failures
       Finished verifying <default-ubuntu-1404> (0m1.09s).

された!

おわりに

ここまで出来たらkitchen testを実行して、眺めるかコーヒーでも汲みに行こう :coffee:

$ ./bin/kitchen test
-----> Starting Kitchen (v1.3.1)
-----> Cleaning up any prior instances of <default-ubuntu-1404>
-----> Destroying <default-ubuntu-1404>...
       ==> default: Forcing shutdown of VM...
       ==> default: Destroying VM and associated drives...
       Vagrant instance <default-ubuntu-1404> destroyed.
       Finished destroying <default-ubuntu-1404> (0m4.06s).
-----> Testing <default-ubuntu-1404>
-----> Creating <default-ubuntu-1404>...

...

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?