subtitle

RaiseTechの各種コースをはじめとしたイロイロな学習の記録

Serverspecでテストコードを書いてみる

前回の記事(構築したAWS環境をServerspecを使って自動テストする)では、Serverspecを使って、自動テストを実施できる環境を整えた。


今回は、前回Failedだった項目をPassにするようにテストコードを変更してみる。

Serverspecの公式ドキュメントでResource Typeを確認できる。


試したテストコードはこちら。前回test2フォルダを作成して、そこにServerspecを初期設定したので、以下のファイルに#1~6までのテストコードがデフォルトで記載されている。(#7~13は手動で追記している)

test2\spec\localhost\sample_spec.rb

require 'spec_helper'
# 1
describe package('httpd'), :if => os[:family] == 'redhat' do
  it { should be_installed }
end
# 2
describe package('apache2'), :if => os[:family] == 'ubuntu' do
  it { should be_installed }
end
# 3
describe service('httpd'), :if => os[:family] == 'redhat' do
  it { should be_enabled }
  it { should be_running }
end
# 4
describe service('apache2'), :if => os[:family] == 'ubuntu' do
  it { should be_enabled }
  it { should be_running }
end
# 5
describe service('org.apache.httpd'), :if => os[:family] == 'darwin' do
  it { should be_enabled }
  it { should be_running }
end
# 6
describe port(3000) do
  it { should be_listening }
end
# 7
describe package('rails') do
  it { should be_installed.by('gem') }
end
# 8
describe package('rbenv') do
  it { should be_installed }
end
# 9
describe package('git') do
  it { should be_installed }
end
# 10
describe package('nodejs') do
  it { should be_installed }
end
# 11
describe package('yarn') do
  it { should be_installed }
end
# 12
describe package('mysql') do
  it { should be_installed }
end
# 13
describe service('mysql') do
  it { should be_enabled }
  it { should be_running }
end


rake specで実行した結果

Port "3000"
  is expected to be listening (FAILED - 1)

Package "rails"
  is expected to be installed by "gem"

Package "rbenv"
  is expected to be installed (FAILED - 2)

Package "git"
  is expected to be installed

Package "nodejs"
  is expected to be installed

Package "yarn"
  is expected to be installed

Package "mysql"
  is expected to be installed (FAILED - 3)

Service "mysql"
  is expected to be enabled (FAILED - 4)
  is expected to be running (FAILED - 5)

Failures:

  1) Port "3000" is expected to be listening
     On host `localhost'
     Failure/Error: it { should be_listening }
       expected Port "3000" to be listening
       /bin/sh -c ss\ -tunl\ \|\ grep\ -E\ --\ :3000\\\

     # ./spec/localhost/sample_spec.rb:27:in `block (2 levels) in <top (required)>'

  2) Package "rbenv" is expected to be installed
     On host `localhost'
     Failure/Error: it { should be_installed }
       expected Package "rbenv" to be installed
       /bin/sh -c rpm\ -q\ rbenv
       package rbenv is not installed

     # ./spec/localhost/sample_spec.rb:35:in `block (2 levels) in <top (required)>'

  3) Package "mysql" is expected to be installed
     On host `localhost'
     Failure/Error: it { should be_installed }
       expected Package "mysql" to be installed
       /bin/sh -c rpm\ -q\ mysql
       package mysql is not installed

     # ./spec/localhost/sample_spec.rb:52:in `block (2 levels) in <top (required)>'

  4) Service "mysql" is expected to be enabled
     On host `localhost'
     Failure/Error: it { should be_enabled }
       expected Service "mysql" to be enabled
       /bin/sh -c systemctl\ --quiet\ is-enabled\ mysql

     # ./spec/localhost/sample_spec.rb:56:in `block (2 levels) in <top (required)>'

  5) Service "mysql" is expected to be running
     On host `localhost'
     Failure/Error: it { should be_running }
       expected Service "mysql" to be running
       /bin/sh -c systemctl\ is-active\ mysql
       unknown

     # ./spec/localhost/sample_spec.rb:57:in `block (2 levels) in <top (required)>'

Finished in 0.52377 seconds (files took 0.4318 seconds to load)
9 examples, 5 failures

Failed examples:


#1~5

自分の環境は、OSがAmazon linuxなので、条件文は「os[:family] == 'amazon'」となるはずだから、そもそも#1~5はテストされない。


#6

3000番ポートがListen状態になっているか?

やや?!Railsは3000番ポートが待ち受けポートではなかったか?

EC2インスタンスに紐づくセキュリティグループのインバウンドルールで3000番ポートを許可する事と思っていたが、別物なのか~。

先生に質問してみたら、「リッスンというのは実際に対象のポート番号が通信可能な状況になっているかどうかなのですよね。 なので、セキュリティグループでで許可していても対象のポート番号が通信可能な状態になっていなければテストは失敗してしまいます。」とのこと!!

マジか!(後でリベンジしてみなければ!!)


#7~12

各種ライブラリがパッケージとしてインストールされているか?

これも、最初は理解できてなくて、先生に聞いて分かったことなのだが、Passするためには、ただインストールされているだけではなく「パッケージとして」対象ライブラリがインストールされていることが必要。

つまり、yumやrpmコマンドでインストールしたものは、Passするということ。

だから、今回の例で行くと、yumでインストールした gitやnodejsはPassしているが、git cloneしただけのrbenvはFailedとなる。


#13

サービス(mysql)が稼働しているか?

今回の環境は、AWSのEC2インスタンス上のRailsアプリから、RDSデータベースに接続するという構成。

EC2からRDSにアクセスできるから、サービスは稼働しているのではないかと思って、このようなテストコードを書いてみたのだが、どうやら間違っているらしい。

これについては、試してみたいことがあるので、次のテストコードの記事で触れる。


#6の3000番ポートListenについて、リベンジする

Railsサーバーを立ち上げて初めてポートが通信可能な状態になる、という推測のもと、別のTeraTermを立ち上げて該当EC2にSSHでアクセスして、Railsサーバーを立ち上げた後、Serverspecのテストをしてみることにする


rake specで実行した結果

Port "3000"
  is expected to be listening

Package "rails"
  is expected to be installed by "gem"

Package "rbenv"
  is expected to be installed (FAILED - 1)

Package "git"
  is expected to be installed

Package "nodejs"
  is expected to be installed

Package "yarn"
  is expected to be installed

Package "mysql"
  is expected to be installed (FAILED - 2)

Service "mysql"
  is expected to be enabled (FAILED - 3)
  is expected to be running (FAILED - 4)

Failures:

  1) Package "rbenv" is expected to be installed
     On host `localhost'
     Failure/Error: it { should be_installed }
       expected Package "rbenv" to be installed
       /bin/sh -c rpm\ -q\ rbenv
       package rbenv is not installed

     # ./spec/localhost/sample_spec.rb:35:in `block (2 levels) in <top (required)>'

  2) Package "mysql" is expected to be installed
     On host `localhost'
     Failure/Error: it { should be_installed }
       expected Package "mysql" to be installed
       /bin/sh -c rpm\ -q\ mysql
       package mysql is not installed

     # ./spec/localhost/sample_spec.rb:52:in `block (2 levels) in <top (required)>'

  3) Service "mysql" is expected to be enabled
     On host `localhost'
     Failure/Error: it { should be_enabled }
       expected Service "mysql" to be enabled
       /bin/sh -c systemctl\ --quiet\ is-enabled\ mysql

     # ./spec/localhost/sample_spec.rb:56:in `block (2 levels) in <top (required)>'

  4) Service "mysql" is expected to be running
     On host `localhost'
     Failure/Error: it { should be_running }
       expected Service "mysql" to be running
       /bin/sh -c systemctl\ is-active\ mysql
       unknown

     # ./spec/localhost/sample_spec.rb:57:in `block (2 levels) in <top (required)>'

Finished in 0.53863 seconds (files took 0.46527 seconds to load)
9 examples, 4 failures

お見事!Passできました♪

セキュリティグループはあくまでもフィルタで、Listen状態になっているかどうかはRailsサーバーが起動しているかどうかにかかっている、ということか。なるほど。


#8のrbenvのテストコードについて、リベンジする

rbenvはパッケージとしてインストールしたわけではないので、下記のテストコードではFailedになってしまう

# 8
describe package('rbenv') do
  it { should be_installed }
end


代わりに何かテストできる方法はないか??

ServerspecのResourceTypeを眺めていると、Commandのcontainというのが使えそうだ

これを使って、rbenvのバージョンをテストしてみるのはどうか?

現状インストールされているバージョンは、「rbenv 1.1.2-44-gd604acb」だから、バージョンに1.1.2が含まれているかどうかを確認するテストコードを書いてみる

# 8
describe command('rbenv -v') do
  its(:stdout) { should contain('1.1.2') }
end


rake specで実行した結果

Port "3000"
  is expected to be listening

Command "rbenv -v"
  stdout
    is expected to contain "1.1.2"

Package "rails"
  is expected to be installed by "gem"

Package "git"
  is expected to be installed

Package "nodejs"
  is expected to be installed

Package "yarn"
  is expected to be installed

Package "mysql"
  is expected to be installed (FAILED - 1)

Service "mysql"
  is expected to be enabled (FAILED - 2)
  is expected to be running (FAILED - 3)

Failures:

  1) Package "mysql" is expected to be installed
     On host `localhost'
     Failure/Error: it { should be_installed }
       expected Package "mysql" to be installed
       /bin/sh -c rpm\ -q\ mysql
       package mysql is not installed

     # ./spec/localhost/sample_spec.rb:51:in `block (2 levels) in <top (required)>'

  2) Service "mysql" is expected to be enabled
     On host `localhost'
     Failure/Error: it { should be_enabled }
       expected Service "mysql" to be enabled
       /bin/sh -c systemctl\ --quiet\ is-enabled\ mysql

     # ./spec/localhost/sample_spec.rb:55:in `block (2 levels) in <top (required)>'

  3) Service "mysql" is expected to be running
     On host `localhost'
     Failure/Error: it { should be_running }
       expected Service "mysql" to be running
       /bin/sh -c systemctl\ is-active\ mysql
       unknown

     # ./spec/localhost/sample_spec.rb:56:in `block (2 levels) in <top (required)>'

Finished in 0.50432 seconds (files took 0.4372 seconds to load)
9 examples, 3 failures


こちらも無事Passできた

テストコードとして、今インストールされているライブラリなどのバージョンを確認するというものアリかもしれない


今回のテストコードのまとめ

require 'spec_helper'

describe package('httpd'), :if => os[:family] == 'redhat' do
  it { should be_installed }
end

describe package('apache2'), :if => os[:family] == 'ubuntu' do
  it { should be_installed }
end

describe service('httpd'), :if => os[:family] == 'redhat' do
  it { should be_enabled }
  it { should be_running }
end

describe service('apache2'), :if => os[:family] == 'ubuntu' do
  it { should be_enabled }
  it { should be_running }
end

describe service('org.apache.httpd'), :if => os[:family] == 'darwin' do
  it { should be_enabled }
  it { should be_running }
end

describe port(3000) do
  it { should be_listening }
end

describe command('rbenv -v') do
  its(:stdout) { should contain('1.1.2') }
end

describe package('rails') do
  it { should be_installed.by('gem') }
end

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

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

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

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

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