serverspecでは、このようなテストを書くことが多いと思います。

describe file '/var/www/vhosts' do
  it { should be_directory }
  it { should be_owned_by 'root' }
  it { should be_grouped_into 'www-data' }
  it { should be_mode 775 }
end

describe file '/home/masutaka/.ssh/authorized_keys' do
  it { should be_file }
  it { should be_owned_by 'masutaka' }
  it { should be_grouped_into 'masutaka' }
  it { should be_mode 600 }
end

テストはDRYにしすぎるべきではありませんが、数が増えてくるとさすがに
冗長なのでこのように変更してみました。

describe file '/var/www/vhosts' do
  it_behaves_like 'a directory root:www-data 775'
end

describe file '/home/masutaka/.ssh/authorized_keys' do
  it_behaves_like 'a file masutaka:masutaka 600'
end

対応するshared_examples_forはspec/support/file_support.rbに書きまし
た。メソッドを作ったのは、他にもshared_examples_forがあって重複した
からです。

shared_examples_for 'a directory root:www-data 775' do
  correct_directory owner: 'root', group: 'www-data', mode: 775
end

shared_examples_for 'a file masutaka:masutaka 600' do
  correct_file owner: 'masutaka', group: 'masutaka', mode: 600
end

def correct_directory(owner:, group:, mode:)
  it { should be_directory }
  it { should be_owned_by owner }
  it { should be_grouped_into group }
  it { should be_mode mode }
end

def correct_file(owner:, group:, mode:)
  it { should be_file }
  it { should be_owned_by owner }
  it { should be_grouped_into group }
  it { should be_mode mode }
end

file_support.rbはspec/spec_helper.rbで読み込むようにしています。

Dir[File.expand_path('support/*.rb', File.dirname(__FILE__))].each do |file|
  require file
end

このような書き方も試しましたが、DRYになった感がなかったので、名前を
ベタに指定する方法にしました。

describe file '/var/www/vhosts' do
  it_behaves_like 'a directory' do
    let(:owner) { 'root' }
    let(:group) { 'root' }
    let(:mode) { 755 }
  end
end

shared_examples_for 'a directory' do
  it { should be_directory }
  it { should be_owned_by owner }
  it { should be_grouped_into group }
  it { should be_mode mode }
end

他の書き方も知りたいなあ。