chef-umami 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 332bd1c06e4c1ef37879026cb156036d17c0ab9f
4
- data.tar.gz: 0af958230fbe4ba6ee6ad8bc548a4cd724b6b23f
3
+ metadata.gz: 782fcbb03ba84bce326bfc8d8c3e51b4a36f4c1e
4
+ data.tar.gz: c7fa44a081c7462509665637bcf1414249f35975
5
5
  SHA512:
6
- metadata.gz: 9bb516181d9d2fc958e79827fe1cf9fc60c8b122aacaa03404239d6b4bd2e97a1f6cd3a22f9f7cc175297ae815d0428a42bcdd56b2636b3014c8155b43860fa1
7
- data.tar.gz: 38ef2f48e5172497dd44c76dbab69fe437dc6dc54db8420e16fed2ca1b497ae1aa14157371d38533d90549f03d7499d81a9482db1e1f8efd93b474fcac798eba
6
+ metadata.gz: f6f76421bb97b53f93b3fedac539aa4d805d556cde66a36d78fb0acc3e55299df479d7285e696cdeca4597a0aabd7e95eac098d0c41539820cb78478a93d17ff
7
+ data.tar.gz: f17e6d3eaf84166fbb2a96578ec5274b97bfeedc815b2db512a6bce12b3e7edb17a9852319be574325d51c009eb53980f53f92dc64ce672cf372dd37567754d9
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.5]
4
+ - Adds support for parsing options.
5
+ - Minor typo fixes.
6
+
3
7
  ## [0.0.4]
4
8
  - Fixes a bug where two methods have the same name. Thanks @HarryYC.
5
9
  - Adds `spec_helper.rb` for unit tests, cutting down on boilerplate in each unit test.
data/README.md CHANGED
@@ -7,6 +7,26 @@ Let's see it in action!
7
7
 
8
8
  [![asciicast](https://asciinema.org/a/138816.png)](https://asciinema.org/a/138816)
9
9
 
10
+ ## Running `umami`
11
+
12
+ A number of options maybe specified on the command line:
13
+
14
+ ```bash
15
+ Usage: umami [options]
16
+
17
+ A taste you won't forget!
18
+
19
+ -h, --help Prints this help message
20
+ -i, --[no-]integration-tests Write integration tests (DEFAULT: true)
21
+ -p, --policyfile POLICYFILE_PATH Specify the path to a policy (DEFAULT: Policyfile.rb)
22
+ -r, --recipes RECIPE1,RECIPE2 Specify one or more recipes for which we'll write tests (DEFAULT: All recipes)
23
+ -t, --test-root TEST_ROOT_PATH Specify the path into which we'll write tests (DEFAULT: spec)
24
+ -u, --[no-]unit-tests Write unit tests (DEFAULT: true)
25
+ -v, --version Show version and exit
26
+ ```
27
+
28
+ If not options are specified, a reasonable set of defaults are defined.
29
+
10
30
  ## How does it Work?
11
31
 
12
32
  `umami` loads up one or more cookbooks in a `chef-zero` instance, executes the
@@ -160,11 +180,11 @@ can build on. **Do NOT depend solely on `umami` to provide test coverage!**
160
180
 
161
181
  This project came to be largely out of fear of having to write a lot of test
162
182
  code from scratch where none had previously existed. The idea of starting from
163
- nothing seemed so daunting that it's likely no on would ever get started. I
183
+ nothing seemed so daunting that it's likely no one would ever get started. I
164
184
  wanted to give Chef developers a means to expedite writing tests. After all,
165
185
  it's much easier to modify code than it is to write it in the first place.
166
186
 
167
- `umami` is the product of reearch into various projects' code, such as
187
+ `umami` is the product of research into various projects' code, such as
168
188
  Chef, ChefDK, and Test Kitchen. I am grateful to everyone that has contributed
169
189
  to those projects. `umami` borrows some patterns from those projects and, in
170
190
  some cases, bits of code.
data/bin/umami CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/opt/chefdk/embedded/bin/ruby
2
2
 
3
- chef_umami_lib = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
4
- $:.unshift(chef_umami_lib)
5
- require "chef-umami/runner"
3
+ chef_umami_lib = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ $LOAD_PATH.unshift(chef_umami_lib)
5
+ require 'chef-umami/runner'
6
6
 
7
7
  Umami::Runner.new.run
@@ -16,8 +16,6 @@ require 'chef'
16
16
 
17
17
  module Umami
18
18
  class Client
19
-
20
- attr_reader :client
21
19
  def initialize
22
20
  @client = client
23
21
  end
@@ -45,6 +43,5 @@ module Umami
45
43
  def resource_collection
46
44
  client.run_status.run_context.resource_collection
47
45
  end
48
-
49
46
  end
50
47
  end
@@ -13,8 +13,6 @@
13
13
  # limitations under the License.
14
14
 
15
15
  module Umami
16
-
17
16
  class InvalidPolicyfileLockFilename < StandardError
18
17
  end
19
-
20
18
  end
@@ -15,32 +15,30 @@
15
15
  module Umami
16
16
  module Helper
17
17
  module FileTools
18
+ require 'fileutils'
19
+ require 'rubocop'
18
20
 
19
- require 'fileutils'
20
- require 'rubocop'
21
-
22
- def write_file(path = nil, content = '')
23
- parent_dir = File.dirname(path)
24
- FileUtils.mkdir_p(parent_dir) unless ::File.exist?(parent_dir)
25
- f = File.open(path, 'w') # Write with prejudice.
26
- f.write(content)
27
- f.close
28
- end
29
-
30
- # Call Rubocop to ensure proper indentation and thus legibility.
31
- def enforce_styling(path = 'spec/umami/')
32
- puts "Running Rubocop over '#{path}' to enforce styling..."
33
- r = RuboCop::CLI.new
34
- # Don't output to STDOUT.
35
- args = [
36
- '--only', 'Style/IndentationWidth,Style/IndentationConsistency',
37
- '--auto-correct',
38
- '--out', '/dev/null',
39
- path
40
- ]
41
- r.run(args)
42
- end
21
+ def write_file(path = nil, content = '')
22
+ parent_dir = File.dirname(path)
23
+ FileUtils.mkdir_p(parent_dir) unless ::File.exist?(parent_dir)
24
+ f = File.open(path, 'w') # Write with prejudice.
25
+ f.write(content)
26
+ f.close
27
+ end
43
28
 
29
+ # Call Rubocop to ensure proper indentation and thus legibility.
30
+ def enforce_styling(path = 'spec/umami/')
31
+ puts "Running Rubocop over '#{path}' to enforce styling..."
32
+ r = RuboCop::CLI.new
33
+ # Don't output to STDOUT.
34
+ args = [
35
+ '--only', 'Style/IndentationWidth,Style/IndentationConsistency',
36
+ '--auto-correct',
37
+ '--out', '/dev/null',
38
+ path
39
+ ]
40
+ r.run(args)
41
+ end
44
42
  end
45
43
  end
46
44
  end
@@ -15,14 +15,14 @@
15
15
  module Umami
16
16
  module Helper
17
17
  module InSpec
18
-
19
18
  # Call on a resource's #identity method to help describe the resource.
20
19
  # This saves us from having to know/code the identity attribute for each
21
20
  # resource (i.e. File is :path, User is :username, etc).
22
21
  def desciption(resource)
23
- identity = resource.identity
24
22
  if identity.is_a? Hash # #identity could return a Hash. Take the first value.
25
23
  identity = identity.values.first
24
+ else
25
+ identity = resource.identity
26
26
  end
27
27
  "describe #{resource.declared_type}('#{identity}') do"
28
28
  end
@@ -34,17 +34,17 @@ module Umami
34
34
  # (i.e. testing a directory resource requires defining a file test).
35
35
  # 2. The method should should return a string joined by newlines.
36
36
  #
37
- #def test_wutang(resource)
38
- # test = [desciption(resource)]
39
- # test << "it { should be_financially_sound }"
40
- # test << "it { should be_diverisified }"
41
- # test.join("\n")
42
- #end
37
+ # def test_wutang(resource)
38
+ # test = [desciption(resource)]
39
+ # test << "it { should be_financially_sound }"
40
+ # test << "it { should be_diverisified }"
41
+ # test.join("\n")
42
+ # end
43
43
 
44
44
  # InSpec can evaluate if a gem is installed via the system `gem` (default)
45
45
  # or via some other `gem` binary, defined by either the path to the gem
46
46
  # binary of a symbol representing that context.
47
- def test_gem_package(resource, gem_binary=nil)
47
+ def test_gem_package(resource, gem_binary = nil)
48
48
  package_name = resource.package_name
49
49
  if gem_binary
50
50
  if gem_binary.is_a? Symbol
@@ -76,35 +76,35 @@ module Umami
76
76
  "#{resource.weekday} " \
77
77
  "#{resource.command}"
78
78
  test << "it { should have_entry('#{cron_entry}').with_user('#{resource.user}') }"
79
- test << "end"
79
+ test << 'end'
80
80
  test.join("\n")
81
81
  end
82
82
 
83
83
  def test_file(resource)
84
84
  test = ["describe file('#{resource.path}') do"]
85
85
  if resource.declared_type =~ /directory/
86
- test << "it { should be_directory }"
86
+ test << 'it { should be_directory }'
87
87
  else
88
- test << "it { should be_file }"
88
+ test << 'it { should be_file }'
89
89
  end
90
90
  # Sometimes we see GIDs instead of group names.
91
- if !resource.group.nil?
91
+ unless resource.group.nil?
92
92
  unless resource.group.is_a?(String) && resource.group.empty?
93
93
  test << "it { should be_grouped_into '#{resource.group}' }"
94
94
  end
95
95
  end
96
96
  # Guard for UIDs versus usernames as well.
97
- if !resource.owner.nil?
97
+ unless resource.owner.nil?
98
98
  unless resource.owner.is_a?(String) && resource.owner.empty?
99
99
  test << "it { should be_owned_by '#{resource.owner}' }"
100
100
  end
101
101
  end
102
- if !resource.mode.nil?
102
+ unless resource.mode.nil?
103
103
  unless resource.mode.is_a?(String) && !resource.mode.empty?
104
104
  test << "it { should be_mode '#{resource.mode}' }"
105
105
  end
106
106
  end
107
- test << "end"
107
+ test << 'end'
108
108
  test.join("\n")
109
109
  end
110
110
  alias_method :test_cookbook_file, :test_file
@@ -115,8 +115,8 @@ module Umami
115
115
 
116
116
  def test_group(resource)
117
117
  test = [desciption(resource)]
118
- test << "it { should exist }"
119
- test << "end"
118
+ test << 'it { should exist }'
119
+ test << 'end'
120
120
  test.join("\n")
121
121
  end
122
122
 
@@ -125,18 +125,18 @@ module Umami
125
125
  if !resource.version.nil? && !resource.version.empty?
126
126
  test << "it { should be_installed.with_version('#{resource.version}') }"
127
127
  else
128
- test << "it { should be_installed }"
128
+ test << 'it { should be_installed }'
129
129
  end
130
- test << "end"
130
+ test << 'end'
131
131
  test.join("\n")
132
132
  end
133
133
 
134
134
  def test_user(resource)
135
135
  test = [desciption(resource)]
136
- test << "it { should exist }"
136
+ test << 'it { should exist }'
137
137
  # Guard for GIDs rather than strings. Chef aliases the #group method
138
138
  # to the #gid method.
139
- if !resource.gid.nil?
139
+ unless resource.gid.nil?
140
140
  unless resource.gid.is_a?(String) && !resource.gid.empty?
141
141
  test << "it { should belong_to_primary_group '#{resource.gid}' }"
142
142
  end
@@ -144,10 +144,9 @@ module Umami
144
144
  if !resource.home.nil? && !resource.home.empty?
145
145
  test << "it { should have_home_directory '#{resource.home}' }"
146
146
  end
147
- test << "end"
147
+ test << 'end'
148
148
  test.join("\n")
149
149
  end
150
-
151
150
  end
152
151
  end
153
152
  end
@@ -27,27 +27,27 @@ module Umami
27
27
  when /aix/
28
28
  # `oslevel` => '7.1.0.0'
29
29
  version = `oslevel`[0..2]
30
- {platform: 'aix', version: version}
30
+ { platform: 'aix', version: version }
31
31
  when /darwin|mac os/
32
32
  version = `sw_vers -productVersion`.chomp
33
- {platform: 'mac_os_x', version: version}
33
+ { platform: 'mac_os_x', version: version }
34
34
  when /linux/
35
35
  # Perform very basic tests to determine distribution.
36
36
  if File.exist?('/etc/centos-release')
37
37
  version = File.read('/etc/redhat-release').split[2]
38
- {platform: 'centos', version: version}
38
+ { platform: 'centos', version: version }
39
39
  elsif File.exist?('/etc/redhat-release') # True for CentOS too...
40
40
  version = File.read('/etc/redhat-release').split[6]
41
- {platform: 'redhat', version: version}
41
+ { platform: 'redhat', version: version }
42
42
  else
43
- {platform: 'centos', version: '7.3.1611'} # Default to something reasonably sane.
43
+ { platform: 'centos', version: '7.3.1611' } # Default to something reasonably sane.
44
44
  end
45
45
  when /solaris/
46
46
  version = `uname -r`.chomp # Release level (i.e. 5.11).
47
- {platform: 'solaris', version: version}
47
+ { platform: 'solaris', version: version }
48
48
  when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
49
49
  # Refer to https://en.wikipedia.org/wiki/Ver_(command)
50
- win_version = `ver`.chomp.split("Version ")[1].gsub(/]/, '')
50
+ win_version = `ver`.chomp.split('Version ')[1].gsub(/]/, '')
51
51
  case win_version
52
52
  when /^6.1.7/
53
53
  version = '2008R2' # Also Win 7
@@ -58,14 +58,13 @@ module Umami
58
58
  when /^(6.4|10)/
59
59
  version = '10'
60
60
  end
61
- {platform: 'windows', version: version}
61
+ { platform: 'windows', version: version }
62
62
  else
63
63
  # Default to something reasonably sane.
64
- {platform: 'centos', version: '7.3.1611'}
64
+ { platform: 'centos', version: '7.3.1611' }
65
65
  end
66
66
  )
67
67
  end
68
-
69
68
  end
70
69
  end
71
70
  end
@@ -14,7 +14,6 @@
14
14
 
15
15
  module Umami
16
16
  module Logger
17
-
18
17
  # Print messages.
19
18
  # TODO: Flesh this out so it supports different levels (i.e. info, warn).
20
19
  def log(msg = '', level = nil)
@@ -0,0 +1,72 @@
1
+ # Copyright 2017 Bloomberg Finance, L.P.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'chef-umami/version'
16
+
17
+ module Umami
18
+ module Options
19
+ # Parse command line options. Returns hash of options.
20
+ def parse_options
21
+ options = {}
22
+ # Default options
23
+ options[:integration_tests] = true
24
+ options[:policyfile] = 'Policyfile.rb'
25
+ options[:test_root] = 'spec'
26
+ options[:unit_tests] = true
27
+
28
+ parser = OptionParser.new do |opts|
29
+ opts.banner = opts.banner + "\n\nA taste you won't forget!\n\n"
30
+ opts.on('-h', '--help', 'Prints this help message') {
31
+ puts opts
32
+ exit
33
+ }
34
+ opts.on('-i', '--[no-]integration-tests', 'Write integration tests' \
35
+ " (DEFAULT: #{options[:integration_tests]})") do |integration_tests|
36
+ options[:integration_tests] = integration_tests
37
+ end
38
+ opts.on('-p', '--policyfile POLICYFILE_PATH', 'Specify the path to a policy' \
39
+ " (DEFAULT: #{options[:policyfile]})") do |policyfile|
40
+ options[:policyfile] = policyfile
41
+ end
42
+ opts.on('-r', '--recipes RECIPE1,RECIPE2', Array,
43
+ "Specify one or more recipes for which we'll write tests" \
44
+ ' (DEFAULT: All recipes)') do |recipes|
45
+ options[:recipes] = recipes
46
+ end
47
+ opts.on('-t', '--test-root TEST_ROOT_PATH', "Specify the path into which we'll write tests" \
48
+ " (DEFAULT: #{options[:test_root]})") do |test_root|
49
+ options[:test_root] = test_root
50
+ end
51
+ opts.on('-u', '--[no-]unit-tests', 'Write unit tests' \
52
+ " (DEFAULT: #{options[:unit_tests]})") do |unit_tests|
53
+ options[:unit_tests] = unit_tests
54
+ end
55
+ opts.on('-v', '--version', 'Show version and exit') {
56
+ puts "chef-umami v#{Umami::VERSION}"
57
+ exit
58
+ }
59
+ end
60
+ begin
61
+ parser.parse!
62
+ rescue OptionParser::InvalidOption => e
63
+ puts "Warning: #{e.message}"
64
+ if e.message =~ /--pattern/
65
+ puts 'Ah, this is likely parsed from `rspec` options. We can safely ignore this.'
66
+ end
67
+ puts 'Ignoring the option.'
68
+ end
69
+ options
70
+ end
71
+ end
72
+ end
@@ -20,13 +20,12 @@ require 'tmpdir' # Extends Dir
20
20
  module Umami
21
21
  class Policyfile
22
22
  class Exporter
23
-
24
23
  attr_reader :chef_config_file
25
24
  attr_reader :cookbook_dir
26
25
  attr_reader :export_root
27
26
  attr_reader :export_path
28
- attr_accessor :policyfile_lock_file
29
27
  attr_reader :policyfile
28
+ attr_accessor :policyfile_lock_file
30
29
 
31
30
  def initialize(policyfile_lock_file = nil, cookbook_dir = nil, policyfile = nil)
32
31
  @policyfile = policyfile
@@ -39,10 +38,6 @@ module Umami
39
38
  @chef_config_file = "#{export_path}/.chef/config.rb"
40
39
  end
41
40
 
42
- def policyfile
43
- @policyfile
44
- end
45
-
46
41
  def ui
47
42
  @ui ||= ChefDK::UI.new
48
43
  end
@@ -92,7 +87,7 @@ module Umami
92
87
  rescue ChefDK::PolicyfileExportRepoError => e
93
88
  puts "\nFAILED TO EXPORT POLICYFILE: #{e.message} (#{e.class})"
94
89
  puts "CAUSE: #{e.cause}"
95
- puts "BACKTRACE:"
90
+ puts 'BACKTRACE:'
96
91
  e.backtrace.each do |line|
97
92
  puts "\t#{line}"
98
93
  end
@@ -101,7 +96,6 @@ module Umami
101
96
  cp_fake_client_key
102
97
  update_chef_config
103
98
  end
104
-
105
99
  end
106
100
  end
107
101
  end
@@ -21,21 +21,15 @@ require 'chef-dk/ui'
21
21
  module Umami
22
22
  class Policyfile
23
23
  class Uploader
24
-
25
- attr_reader :http_client
26
- attr_reader :policyfile_lock
27
24
  attr_reader :policyfile_lock_file
28
- attr_reader :policyfile_uploader
29
- attr_reader :storage_config
30
- attr_reader :ui
31
- def initialize(policyfile_lock_file = nil)
25
+ def initialize(policyfile_lock_file = nil)
32
26
  @http_client = http_client
33
27
  @policyfile_lock_file = policyfile_lock_file
34
28
  @policyfile_lock = policyfile_lock
35
29
  @policyfile_uploader = policyfile_uploader
36
30
  @storage_config = storage_config
37
31
  @ui = ui
38
- end
32
+ end
39
33
 
40
34
  def storage_config
41
35
  @storage_config ||= ChefDK::Policyfile::StorageConfig.new.use_policyfile(policyfile_lock_file)
@@ -86,7 +80,6 @@ module Umami
86
80
  def upload
87
81
  policyfile_uploader.upload
88
82
  end
89
-
90
83
  end
91
84
  end
92
85
  end
@@ -16,6 +16,7 @@ require 'chef'
16
16
  require 'chef-umami/exceptions'
17
17
  require 'chef-umami/client'
18
18
  require 'chef-umami/logger'
19
+ require 'chef-umami/options'
19
20
  require 'chef-umami/server'
20
21
  require 'chef-umami/policyfile/exporter'
21
22
  require 'chef-umami/policyfile/uploader'
@@ -24,17 +25,13 @@ require 'chef-umami/test/integration'
24
25
 
25
26
  module Umami
26
27
  class Runner
27
-
28
28
  include Umami::Logger
29
+ include Umami::Options
29
30
 
30
31
  attr_reader :cookbook_dir
31
- attr_reader :policyfile_lock_file
32
- attr_reader :policyfile
33
- # TODO: Build the ability to specify a custom policy lock file name.
34
- def initialize(policyfile_lock_file = nil, policyfile = nil)
32
+ def initialize
33
+ @config = config
35
34
  @cookbook_dir = Dir.pwd
36
- @policyfile_lock_file = 'Policyfile.lock.json'
37
- @policyfile = policyfile || 'Policyfile.rb'
38
35
  @exporter = exporter
39
36
  @chef_zero_server = chef_zero_server
40
37
  # If we load the uploader or client now, they won't see the updated
@@ -43,8 +40,23 @@ module Umami
43
40
  @chef_client = nil
44
41
  end
45
42
 
43
+ # A hash of values describing the config. Comprised of command line
44
+ # options. May (in the future) contain options read from a config file.
45
+ def config
46
+ @config ||= parse_options
47
+ end
48
+
49
+ def policyfile
50
+ config[:policyfile]
51
+ end
52
+
53
+ # Return the computed policyfile lock name.
54
+ def policyfile_lock_file
55
+ policyfile.gsub(/\.rb$/, '.lock.json')
56
+ end
57
+
46
58
  def validate_lock_file!
47
- unless policyfile_lock_file.end_with?("lock.json")
59
+ unless policyfile_lock_file.end_with?('lock.json')
48
60
  raise InvalidPolicyfileLockFilename, "Policyfile lock files must end in '.lock.json'. I received '#{policyfile_lock_file}'."
49
61
  end
50
62
 
@@ -73,7 +85,7 @@ module Umami
73
85
  validate_lock_file!
74
86
  puts "\nExporting the policy, related cookbooks, and a valid client configuration..."
75
87
  exporter.export
76
- Chef::Config.from_file("#{exporter.chef_config_file}")
88
+ Chef::Config.from_file(exporter.chef_config_file)
77
89
  chef_zero_server.start
78
90
  puts "\nUploading the policy and related cookbooks..."
79
91
  uploader.upload
@@ -86,6 +98,12 @@ module Umami
86
98
  recipe_resources = {}
87
99
  chef_client.resource_collection.each do |resource|
88
100
  canonical_recipe = "#{resource.cookbook_name}::#{resource.recipe_name}"
101
+ unless config[:recipes].empty?
102
+ # The user has explicitly requested that one or more recipes have
103
+ # tests written, to the exclusion of others.
104
+ # ONLY include the recipe if it matches the list.
105
+ next unless config[:recipes].include?(canonical_recipe)
106
+ end
89
107
  if recipe_resources.key?(canonical_recipe)
90
108
  recipe_resources[canonical_recipe] << resource
91
109
  else
@@ -98,15 +116,17 @@ module Umami
98
116
  re_export_path = Regexp.new('/tmp/umami')
99
117
  FileUtils.rm_rf(exporter.export_root) if exporter.export_root.match(re_export_path)
100
118
 
101
- puts "\nGenerating a set of unit tests..."
102
- unit_tester = Umami::Test::Unit.new
103
- unit_tester.generate(recipe_resources)
104
-
105
- puts "\nGenerating a set of integration tests..."
106
- integration_tester = Umami::Test::Integration.new
107
- integration_tester.generate(recipe_resources)
119
+ if config[:unit_tests]
120
+ puts "\nGenerating a set of unit tests..."
121
+ unit_tester = Umami::Test::Unit.new(config[:test_root])
122
+ unit_tester.generate(recipe_resources)
123
+ end
108
124
 
125
+ if config[:integration_tests]
126
+ puts "\nGenerating a set of integration tests..."
127
+ integration_tester = Umami::Test::Integration.new(config[:test_root])
128
+ integration_tester.generate(recipe_resources)
129
+ end
109
130
  end
110
-
111
131
  end
112
132
  end
@@ -31,6 +31,5 @@ module Umami
31
31
  def stop
32
32
  server.stop
33
33
  end
34
-
35
34
  end
36
35
  end
@@ -14,10 +14,9 @@
14
14
 
15
15
  module Umami
16
16
  class Test
17
-
18
17
  attr_reader :root_dir
19
- def initialize
20
- @root_dir = 'spec'
18
+ def initialize(root_dir)
19
+ @root_dir = root_dir
21
20
  end
22
21
 
23
22
  # All subclasses should implement the following methods.
@@ -58,6 +57,5 @@ module Umami
58
57
  def generate
59
58
  raise NoMethodError, "#{self.class} needs to implement the ##{__method__} method! Refer to Umami::Test."
60
59
  end
61
-
62
60
  end
63
61
  end
@@ -19,12 +19,11 @@ require 'chef-umami/helpers/filetools'
19
19
  module Umami
20
20
  class Test
21
21
  class Integration < Umami::Test
22
-
23
22
  include Umami::Helper::InSpec
24
23
  include Umami::Helper::FileTools
25
24
 
26
25
  attr_reader :test_root
27
- def initialize
26
+ def initialize(root_dir)
28
27
  super
29
28
  @test_root = File.join(self.root_dir, 'umami', 'integration')
30
29
  end
@@ -32,7 +31,7 @@ module Umami
32
31
  # InSpec doesn't need a require statement to use its tests.
33
32
  # We define #framework here for completeness.
34
33
  def framework
35
- "inspec"
34
+ 'inspec'
36
35
  end
37
36
 
38
37
  def test_file_path(cookbook = '', recipe = '')
@@ -58,10 +57,10 @@ module Umami
58
57
  # Raise NoMethodError for any other failed calls.
59
58
  def method_missing(m, *args, &block)
60
59
  case m
61
- when /^test_/
62
- "# #{m} is not currently defined. Stay tuned for updates."
63
- else
64
- raise NoMethodError
60
+ when /^test_/
61
+ "# #{m} is not currently defined. Stay tuned for updates."
62
+ else
63
+ raise NoMethodError
65
64
  end
66
65
  end
67
66
 
@@ -82,14 +81,12 @@ module Umami
82
81
  enforce_styling(test_root)
83
82
 
84
83
  unless test_files_written.empty?
85
- puts "Wrote the following integration tests:"
84
+ puts 'Wrote the following integration tests:'
86
85
  test_files_written.each do |f|
87
86
  puts "\t#{f}"
88
87
  end
89
88
  end
90
-
91
89
  end
92
-
93
90
  end
94
91
  end
95
92
  end
@@ -19,20 +19,19 @@ require 'chef-umami/helpers/filetools'
19
19
  module Umami
20
20
  class Test
21
21
  class Unit < Umami::Test
22
-
23
22
  include Umami::Helper::OS
24
23
  include Umami::Helper::FileTools
25
24
 
26
25
  attr_reader :test_root
27
26
  attr_reader :tested_cookbook # This cookbook.
28
- def initialize
27
+ def initialize(root_dir)
29
28
  super
30
29
  @test_root = File.join(self.root_dir, 'umami', 'unit', 'recipes')
31
30
  @tested_cookbook = File.basename(Dir.pwd)
32
31
  end
33
32
 
34
33
  def framework
35
- "chefspec"
34
+ 'chefspec'
36
35
  end
37
36
 
38
37
  def test_file(recipe = '')
@@ -62,7 +61,7 @@ module Umami
62
61
  def write_test(resource = nil)
63
62
  state_attrs = [] # Attribute hash to be used with #with()
64
63
  resource.state.each do |attr, value|
65
- next if value.nil? or (value.respond_to?(:empty) and value.empty?)
64
+ next if value.nil? || (value.respond_to?(:empty) && value.empty?)
66
65
  if value.is_a? String
67
66
  value = value.gsub("'", "\\\\'") # Escape any single quotes in the value.
68
67
  end
@@ -95,7 +94,7 @@ module Umami
95
94
  resources.each do |resource|
96
95
  content << write_test(resource)
97
96
  end
98
- content << "end"
97
+ content << 'end'
99
98
  test_file_name = test_file(recipe)
100
99
  test_file_content = content.join("\n") + "\n"
101
100
  write_file(test_file_name, test_file_content)
@@ -107,14 +106,12 @@ module Umami
107
106
  test_files_written << spec_helper_path
108
107
 
109
108
  unless test_files_written.empty?
110
- puts "Wrote the following unit test files:"
109
+ puts 'Wrote the following unit test files:'
111
110
  test_files_written.each do |f|
112
111
  puts "\t#{f}"
113
112
  end
114
113
  end
115
-
116
114
  end
117
-
118
115
  end
119
116
  end
120
117
  end
@@ -13,5 +13,5 @@
13
13
  # limitations under the License.
14
14
 
15
15
  module Umami
16
- VERSION = '0.0.4'
16
+ VERSION = '0.0.5'.freeze
17
17
  end
@@ -12,10 +12,10 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require "chef-umami/runner"
15
+ require 'chef-umami/runner'
16
16
 
17
17
  RSpec.describe Umami::Runner do
18
- it "initiates a Umami::Runner object" do
18
+ it 'initiates a Umami::Runner object' do
19
19
  runner = Umami::Runner.new
20
20
  expect(runner).to be_an_instance_of(Umami::Runner)
21
21
  end
@@ -1,103 +0,0 @@
1
- # This file was generated by the `rspec --init` command. Conventionally, all
2
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
- # The generated `.rspec` file contains `--require spec_helper` which will cause
4
- # this file to always be loaded, without a need to explicitly require it in any
5
- # files.
6
- #
7
- # Given that it is always loaded, you are encouraged to keep this file as
8
- # light-weight as possible. Requiring heavyweight dependencies from this file
9
- # will add to the boot time of your test suite on EVERY test run, even for an
10
- # individual file that may not need all of that loaded. Instead, consider making
11
- # a separate helper file that requires the additional dependencies and performs
12
- # the additional setup, and require it from the spec files that actually need
13
- # it.
14
- #
15
- # The `.rspec` file also contains a few flags that are not defaults but that
16
- # users commonly want.
17
- #
18
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
- RSpec.configure do |config|
20
- # rspec-expectations config goes here. You can use an alternate
21
- # assertion/expectation library such as wrong or the stdlib/minitest
22
- # assertions if you prefer.
23
- config.expect_with :rspec do |expectations|
24
- # This option will default to `true` in RSpec 4. It makes the `description`
25
- # and `failure_message` of custom matchers include text for helper methods
26
- # defined using `chain`, e.g.:
27
- # be_bigger_than(2).and_smaller_than(4).description
28
- # # => "be bigger than 2 and smaller than 4"
29
- # ...rather than:
30
- # # => "be bigger than 2"
31
- expectations.include_chain_clauses_in_custom_matcher_descriptions = true
32
- end
33
-
34
- # rspec-mocks config goes here. You can use an alternate test double
35
- # library (such as bogus or mocha) by changing the `mock_with` option here.
36
- config.mock_with :rspec do |mocks|
37
- # Prevents you from mocking or stubbing a method that does not exist on
38
- # a real object. This is generally recommended, and will default to
39
- # `true` in RSpec 4.
40
- mocks.verify_partial_doubles = true
41
- end
42
-
43
- # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
44
- # have no way to turn it off -- the option exists only for backwards
45
- # compatibility in RSpec 3). It causes shared context metadata to be
46
- # inherited by the metadata hash of host groups and examples, rather than
47
- # triggering implicit auto-inclusion in groups with matching metadata.
48
- config.shared_context_metadata_behavior = :apply_to_host_groups
49
-
50
- # The settings below are suggested to provide a good initial experience
51
- # with RSpec, but feel free to customize to your heart's content.
52
- =begin
53
- # This allows you to limit a spec run to individual examples or groups
54
- # you care about by tagging them with `:focus` metadata. When nothing
55
- # is tagged with `:focus`, all examples get run. RSpec also provides
56
- # aliases for `it`, `describe`, and `context` that include `:focus`
57
- # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
58
- config.filter_run_when_matching :focus
59
-
60
- # Allows RSpec to persist some state between runs in order to support
61
- # the `--only-failures` and `--next-failure` CLI options. We recommend
62
- # you configure your source control system to ignore this file.
63
- config.example_status_persistence_file_path = "spec/examples.txt"
64
-
65
- # Limits the available syntax to the non-monkey patched syntax that is
66
- # recommended. For more details, see:
67
- # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
68
- # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
69
- # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
70
- config.disable_monkey_patching!
71
-
72
- # This setting enables warnings. It's recommended, but in some cases may
73
- # be too noisy due to issues in dependencies.
74
- config.warnings = true
75
-
76
- # Many RSpec users commonly either run the entire suite or an individual
77
- # file, and it's useful to allow more verbose output when running an
78
- # individual spec file.
79
- if config.files_to_run.one?
80
- # Use the documentation formatter for detailed output,
81
- # unless a formatter has already been configured
82
- # (e.g. via a command-line flag).
83
- config.default_formatter = 'doc'
84
- end
85
-
86
- # Print the 10 slowest examples and example groups at the
87
- # end of the spec run, to help surface which specs are running
88
- # particularly slow.
89
- config.profile_examples = 10
90
-
91
- # Run specs in random order to surface order dependencies. If you find an
92
- # order dependency and want to debug it, you can fix the order by providing
93
- # the seed, which is printed after each run.
94
- # --seed 1234
95
- config.order = :random
96
-
97
- # Seed global randomization in this process using the `--seed` CLI option.
98
- # Setting this allows you to use `--seed` to deterministically reproduce
99
- # test failures related to randomization by passing the same `--seed` value
100
- # as the one that triggered the failure.
101
- Kernel.srand config.seed
102
- =end
103
- end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-umami
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Frantz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-28 00:00:00.000000000 Z
11
+ date: 2017-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -74,6 +74,7 @@ files:
74
74
  - lib/chef-umami/helpers/inspec.rb
75
75
  - lib/chef-umami/helpers/os.rb
76
76
  - lib/chef-umami/logger.rb
77
+ - lib/chef-umami/options.rb
77
78
  - lib/chef-umami/policyfile.rb
78
79
  - lib/chef-umami/policyfile/exporter.rb
79
80
  - lib/chef-umami/policyfile/uploader.rb