- 更新日: 2014年8月15日
- RSpec
Serverspec で複数のホストで共通のテストを使い回す
Serverspec でホストが異なってもテストを共通して使いまわせるように、spec/ ディレクトリ構成と Rakefile, spec_helper の設定を修正しました。方法は、以下の公式ドキュメントのページに書いてあります。
Serverspec – Advanced Tips の “How to share Serverspec tests among hosts”
デフォルトの serverspec-init コマンドはホストごとにテストを書く構成になる
デフォルトでは、serverspec-init コマンドは spec ディレクトリ以下に、ホスト名(またはIPアドレス)ごとにディレクトリを持つ構成となります。
公式ドキュメントに以下の説明があるのですが…
|– Rakefile
-- spec
— www.example.jp
|-- spec_helper.rb
`– httpd_spec.rbThis directory structure forces you to write tests per host.
「このディレクトリ構成の場合、ホストごとにテストを書かなきゃいけない」と説明があります。異なるホストごとに、同じ内容のテストを書くのは避けたいので、使いまわせるように以降の設定を行います。
テストを使いまわすための spec/ ディレクトリ構成
ということで、共通するテストを異なるホストでも共有して使いまわせるようにする設定を行う。ドキュメント通りに進めれば簡単です。まずは、spec/ ディレクトリの構成を変更します。以下のような spec/ ディレクトリ構成にします。
1 2 3 4 5 6 7 8 9 |
$ tree -L 1 spec spec ├── app ├── base ├── db ├── proxy └── spec_helper.rb |
公式ドキュメント通りの構成なのですが、app, base, db, proxy はそれぞれホストの role(役割)で分ける。
Rakefile の修正
続いて、Rakefile の修正です。以下の内容に置き換えました。冒頭の hosts 配列に、name(ホスト名), roles(役割)を指定したホストを追加します。
Rakefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
require 'rake' require 'rspec/core/rake_task' hosts = [ { :name => 'vagrant.test', :roles => %w( app base db proxy ), }, { :name => 'example.com', :roles => %w( app base db proxy ), }, ] hosts = hosts.map do |host| { :name => host[:name], :short_name => host[:name].split('.')[0], :roles => host[:roles], } end desc "Run serverspec to all hosts" task :spec => 'serverspec:all' class ServerspecTask < RSpec::Core::RakeTask attr_accessor :target def spec_command cmd = super "env TARGET_HOST=#{target} #{cmd}" end end namespace :serverspec do task :all => hosts.map {|h| 'serverspec:' + h[:short_name] } hosts.each do |host| desc "Run serverspec to #{host[:name]}" ServerspecTask.new(host[:short_name].to_sym) do |t| t.target = host[:name] t.pattern = 'spec/{' + host[:roles].join(',') + '}/*_spec.rb' end end end |
公式ドキュメントにあるコードがとても分かりやすいので参考にして、全ての role(app, base, db, proxy)をサーバー1台でまかなう場合の構成です。vagrant.test が vagrant 上のテスト用VM、example.com が本番用サーバーとなります。
複数のホストで role を分割する場合は、ドキュメント通り name, roles のペアを設定したホストを、冒頭の hosts 配列に追加します。
この Rakefile により、以下の Serverspec でのテスト実行用の Rake タスク(rake コマンド)が作成される。
rake serverspec:example
rake serverspec:vagrant
rake spec(serverspec:all)
実際に rake タスクを確認すると以下の通り。
1 2 3 4 5 6 |
$ bundle exec rake -vT rake serverspec:example # Run serverspec to example.com rake serverspec:vagrant # Run serverspec to vagrant.test rake spec # Run serverspec to all hosts |
serverspec テストを実行するには、これらの rake コマンドを使います。
spec_helper.rb の修正
続いて、spec_helper.rb を修正。ドキュメントを参考にして以下のように変更しました。
spec/spec_helper.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
require 'serverspec' require 'pathname' require 'net/ssh' require 'highline/import' include Serverspec::Helper::Ssh include Serverspec::Helper::DetectOS RSpec.configure do |c| c.sudo_password = ask("Enter sudo password: ") { |q| q.echo = false } c.host = ENV['TARGET_HOST'] options = Net::SSH::Config.for(c.host) user = options[:user] || Etc.getlogin c.ssh = Net::SSH.start(c.host, user, options) c.os = backend.check_os end |
このコードも分かりやすいかと思います。デフォルトで sudo 実行のパスワード入力を求めるように設定。また後半では、ENV[‘TARGET_HOST’] でテスト対象のホストを取得して、Net::SSH.start で SSH ログインしています。
~/.ssh/config の設定
最後に、~/.ssh/config の設定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
~/.ssh/config Host vagrant.test HostName 127.0.0.1 User vagrant Port 2222 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile /Users/username/.vagrant.d/insecure_private_key IdentitiesOnly yes LogLevel FATAL Host exapmle.com HostName ***.***.***.*** User example_user IdentityFile ~/.ssh/id_rsa |
vagrant 用の SSH 接続設定は、以下のコマンドで吐き出せます。
1 2 3 |
$ vagrant ssh-config --host vagrant.test |
あと Severspec でテストを実行するユーザー、今回の本番サーバーの場合では… example.com 用の User である example_user は、以下のいずれかの条件を満たす必要があります。
1. パスワードなしで sudo 実行できるユーザー
2. パスワードありで sudo 実行できるユーザー。この場合は serverspec テスト実行時に、パスワードを入力します。
私は、パスワードなしの sudo 実行ユーザーはちょっと怖い気がするので、前述したとおり2のほうの設定を spec_helper に書きました。以上です。
- RSpec の関連記事
- FactoryGirlをSpringと共に使う時の注意
- 複数モデルのpost :createをテストするRSpecコード(Controller Spec)
- RSpec3でTime.nowをスタブ化(stub)
- RSpecでJSONによるPOSTリクエストをテスト
- RSpec & Capybara の雑感
- RSpec+Capybaraで同名の複数要素の並び順をテストする
- RSpec3ではrails_helper.rbがrequireされる
- Capybara + Launchy で RSpec テストをブラウザで確認
- CapybaraのwithinをRSpecで使う
- Serverspec(RSpec)のテスト出力に色を付けて見やすくフォーマット
Leave Your Message!