chef-umami 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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