ChefSpec覚え

#ChefSpecとは

Chef Cookbookの検証

- あるChefリソースが、あるactionで、あるプロパティで、実行される様になっているかを確認する
- RSpecペース
- ChefDK, Chef Workstationに含まれる
- chef generate cookbook <cookbookname>時にテストのテンプレートが作成される




#テストの記述

RSpec基本的なフォーマットは以下が大変解りやすかった。

- [使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」](https://qiita.com/jnchito/items/42193d066bd61c740612)

cookbook作成時に同時に作成されるChefSpecテストのテンプレート

```
$ chef generate cookbook <cookbook名> 
$ vi spec/unit/recipes/default_spec.rb
$ cat spec/unit/recipes/default_spec.rb
```

```ruby:spec/unit/recipes/default_spec.rb
#
# Cookbook:: <cookbook名>
# Spec:: default
#
# Copyright:: 2019, The Authors, All Rights Reserved.

require 'spec_helper'

describe 'test01::default' do
  context 'When all attributes are default, on Ubuntu 16.04' do
    let(:chef_run) do
      # for a complete list of available platforms and versions see:
      # https://github.com/customink/fauxhai/blob/master/PLATFORMS.md
      runner = ChefSpec::ServerRunner.new(platform: 'ubuntu', version: '16.04')
      runner.converge(described_recipe)
    end

    it 'converges successfully' do
      expect { chef_run }.to_not raise_error
    end

# ここまで自動的に作成される。ubuntu環境用のセクション。以下にユーザー定義のテストを書く

    it 'ユーザー作成' do
      expect(chef_run).to create_user('create user foo')
        .with(username: 'foo')
    end

# ここから自動的に作成される。

  end

  context 'When all attributes are default, on CentOS 7.4.1708' do
    let(:chef_run) do
      # for a complete list of available platforms and versions see:
      # https://github.com/customink/fauxhai/blob/master/PLATFORMS.md
      runner = ChefSpec::ServerRunner.new(platform: 'centos', version: '7.4.1708')
      runner.converge(described_recipe)
    end

    it 'converges successfully' do
      expect { chef_run }.to_not raise_error
    end

# ここまで自動的に作成される。ここはcentos環境用のセクション。以下にユーザー定義のテストを書く

    it 'ユーザー作成' do
      expect(chef_run).to create_user('create user foo')
        .with(username: 'foo')
    end

# ここから自動的に作成される。

  end
end

```

itで始まる節がテスト
上ではデフォルトの2つに加えて2つ追加した

```
expect(chef_run).to 部分は基本的に固定
否定の場合には .to を .to_not とする

create_user('create user foo')
  .with(username: 'foo')

は、recipeに以下の様なリソースがあることを検証

user 'create user foo' do
  username 'foo'
  action :create # これはデフォルトアクションなのでrecipeにて明示指定は不要
end
```


#使用可能なMatcher
create_user部分はMatcherと呼ばれ、どの様なものが使用可能かは以下を確認

https://www.rubydoc.info/github/sethvargo/chefspec/ChefSpec/API

Modules: AptPackageMatchers, BatchMatchers, ChefGemMatchers, CookbookFileMatchers, CronMatchers, DeployMatchers, DirectoryMatchers, DoNothingMatchers, DpkgPackageMatchers, EasyInstallPackageMatchers, EnvMatchers, ErlCallMatchers, ExecuteMatchers, FileMatchers, FreebsdPackageMatchers, GemPackageMatchers, GitMatchers, GroupMatchers, HttpRequestMatchers, IfconfigMatchers, IncludeRecipeMatchers, IpsPackageMatchers, LinkMatchers, LogMatchers, MacportsPackageMatchers, MdadmMatchers, MountMatchers, NotificationsMatchers, OhaiMatchers, PackageMatchers, PacmanPackageMatchers, PortagePackageMatchers, PowershellScriptMatchers, RebootMatchers, RegistryKeyMatchers, RemoteDirectoryMatchers, RemoteFileMatchers, RenderFileMatchers, RouteMatchers, RpmPackageMatchers, RubyBlockMatchers, ScriptMatchers, ServiceMatchers, SmartosPackageMatchers, SolarisPackageMatchers, StateAttrsMatcher, SubscriptionsMatchers, SubversionMatchers, TemplateMatchers, UserMatchers, YumPackageMatchers

見た感じ、Chefの \<action名>_<リソース名> に対応している様子。

例えばPackageMatchersの場合

https://www.rubydoc.info/github/sethvargo/chefspec/ChefSpec/API/PackageMatchers

Instance Method Summary

- __install_package__(resource_name) ⇒ ChefSpec::Matchers::ResourceMatcher
    - Assert that an __package__ resource exists in the Chef run with the action __:install__.
- __purge_package__(resource_name) ⇒ ChefSpec::Matchers::ResourceMatcher
    - Assert that an __package__ resource exists in the Chef run with the action __:purge__.
- reconfig_package(resource_name) ⇒ ChefSpec::Matchers::ResourceMatcher
    - Assert that an package resource exists in the Chef run with the action :reconfig.
- remove_package(resource_name) ⇒ ChefSpec::Matchers::ResourceMatcher
    - Assert that an package resource exists in the Chef run with the action :remove.
- upgrade_package(resource_name) ⇒ ChefSpec::Matchers::ResourceMatcher
    - Assert that an package resource exists in the Chef run with the action :upgrade.

__install_package__の例

Examples:

- Assert that an package was installed
    - expect(chef_run).to install_package('apache2')
- Assert that an package was installed with predicate matchers
    - expect(chef_run).to install_package('apache2').with_version('1.2.3')
- Assert that an package was installed with attributes
    - expect(chef_run).to install_package('apache2').with(version: '1.2.3')
- Assert that an package was installed using a regex
    - expect(chef_run).to install_package('apache2').with(version: /(\d+\.){2}\.\d+/)
- Assert that an package was not installed
    - expect(chef_run).to_not install_package('apache2')



#テストの実行

```
$ rspec
....

Finished in 1.2 seconds (files took 6.51 seconds to load)
4 examples, 0 failures
```

#トラブル

作成されていた spec/spec_helper.rb において、以下が含まれているとエラーとなった。
require 'chefspec/berkshelf'

cookbook間の依存関係の無い状態でのテストであったので、コメントアウトにて対応。



#参照
https://docs.chef.io/chefspec.html
https://github.com/chefspec/chefspec