puppet_module_spec_helper 0.1.2 → 0.2.0

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.
@@ -1,5 +1,4 @@
1
- require 'rubygems'
2
- require 'puppet'
1
+ require 'puppet_module_spec_helper/puppet_spec_helper'
3
2
  require 'rspec-puppet'
4
3
 
5
4
  def param_value(subject, type, title, param)
@@ -11,13 +10,14 @@ def verify_contents(subject, title, expected_lines)
11
10
  (content.split("\n") & expected_lines).should == expected_lines
12
11
  end
13
12
 
14
- Puppet.parse_config
15
- puppet_module_path = Puppet[:modulepath]
16
-
17
13
  fixture_path = File.expand_path(File.join(Dir.pwd, 'spec/fixtures'))
18
14
 
15
+ env_module_path = ENV['MODULEPATH']
16
+ module_path = File.join(fixture_path, 'modules')
17
+
18
+ module_path = [module_path, env_module_path].join(':') if env_module_path
19
+
19
20
  RSpec.configure do |c|
20
- fixture_module_path = File.join(fixture_path, 'modules')
21
- c.module_path = [fixture_module_path, puppet_module_path].join(":")
21
+ c.module_path = module_path
22
22
  c.manifest_dir = File.join(fixture_path, 'manifests')
23
23
  end
@@ -0,0 +1,187 @@
1
+ require 'puppet_module_spec_helper/puppetlabs_spec_helper'
2
+
3
+ # Don't want puppet getting the command line arguments for rake or autotest
4
+ ARGV.clear
5
+
6
+ require 'puppet'
7
+ require 'mocha'
8
+ gem 'rspec', '>=2.0.0'
9
+ require 'rspec/expectations'
10
+
11
+ require 'pathname'
12
+ require 'tmpdir'
13
+
14
+ require 'puppet_module_spec_helper/puppetlabs_spec/files'
15
+
16
+ ######################################################################################
17
+ # WARNING #
18
+ ######################################################################################
19
+ #
20
+ # You should probably be frightened by this file. :)
21
+ #
22
+ # The goal of this file is to try to maximize spec-testing compatibility between
23
+ # multiple versions of various external projects (which depend on puppet core) and
24
+ # multiple versions of puppet core itself. This is accomplished via a series
25
+ # of hacks and magical incantations that I am not particularly proud of. However,
26
+ # after discussion it was decided that the goal of achieving compatibility was
27
+ # a very worthy one, and that isolating the hacks to one place in a non-production
28
+ # project was as good a solution as we could hope for.
29
+ #
30
+ # You may want to hold your nose before you proceed. :)
31
+ #
32
+
33
+
34
+ # This is just a utility class to allow us to isolate the various version-specific
35
+ # branches of initialization logic into methods without polluting the global namespace.#
36
+ module Puppet
37
+ class PuppetSpecInitializer
38
+ # This method uses the "new"/preferred approach of delegating all of the test
39
+ # state initialization to puppet itself, via Puppet::Test::TestHelper API. This
40
+ # should be fairly future-proof as long as that API doesn't change, which it
41
+ # hopefully will not need to.
42
+ def self.initialize_via_testhelper(config)
43
+ # connect rspec hooks to TestHelper methods.
44
+ config.before :all do
45
+ Puppet::Test::TestHelper.before_all_tests()
46
+ end
47
+
48
+ config.after :all do
49
+ Puppet::Test::TestHelper.after_all_tests()
50
+ end
51
+
52
+ config.before :each do
53
+ Puppet::Test::TestHelper.before_each_test()
54
+ end
55
+
56
+ config.after :each do
57
+ Puppet::Test::TestHelper.after_each_test()
58
+ end
59
+ end
60
+
61
+ # This method is for initializing puppet state for testing for older versions
62
+ # of puppet that do not support the new TestHelper API. As you can see,
63
+ # this involves explicitly modifying global variables, directly manipulating
64
+ # Puppet's Settings singleton object, and other fun implementation details
65
+ # that code external to puppet should really never know about.
66
+ def self.initialize_via_fallback_compatibility(config)
67
+ config.before :all do
68
+ # nothing to do for now
69
+ end
70
+
71
+ config.after :all do
72
+ # nothing to do for now
73
+ end
74
+
75
+ config.before :each do
76
+ # these globals are set by Application
77
+ $puppet_application_mode = nil
78
+ $puppet_application_name = nil
79
+
80
+ # REVISIT: I think this conceals other bad tests, but I don't have time to
81
+ # fully diagnose those right now. When you read this, please come tell me
82
+ # I suck for letting this float. --daniel 2011-04-21
83
+ Signal.stubs(:trap)
84
+
85
+ # Set the confdir and vardir to gibberish so that tests
86
+ # have to be correctly mocked.
87
+ Puppet[:confdir] = "/dev/null"
88
+ Puppet[:vardir] = "/dev/null"
89
+
90
+ # Avoid opening ports to the outside world
91
+ Puppet.settings[:bindaddress] = "127.0.0.1"
92
+ end
93
+
94
+ config.after :each do
95
+ Puppet.settings.clear
96
+
97
+ Puppet::Node::Environment.clear
98
+ Puppet::Util::Storage.clear
99
+ Puppet::Util::ExecutionStub.reset if Puppet::Util.constants.include? "ExecutionStub"
100
+
101
+ PuppetlabsSpec::Files.cleanup
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+
108
+
109
+ # Here we attempt to load the new TestHelper API, and print a warning if we are falling back
110
+ # to compatibility mode for older versions of puppet.
111
+ begin
112
+ require 'puppet/test/test_helper'
113
+ rescue LoadError => err
114
+ $stderr.puts("Warning: you appear to be using an older version of puppet; spec_helper will use fallback compatibility mode.")
115
+ end
116
+
117
+
118
+ # JJM Hack to make the stdlib tests run in Puppet 2.6 (See puppet commit cf183534)
119
+ if not Puppet.constants.include? "Test" then
120
+ module Puppet::Test
121
+ class LogCollector
122
+ def initialize(logs)
123
+ @logs = logs
124
+ end
125
+
126
+ def <<(value)
127
+ @logs << value
128
+ end
129
+ end
130
+ end
131
+ Puppet::Util::Log.newdesttype :log_collector do
132
+ match "Puppet::Test::LogCollector"
133
+
134
+ def initialize(messages)
135
+ @messages = messages
136
+ end
137
+
138
+ def handle(msg)
139
+ @messages << msg
140
+ end
141
+ end
142
+ end
143
+
144
+
145
+ # And here is where we do the main rspec configuration / setup.
146
+ RSpec.configure do |config|
147
+ config.mock_with :mocha
148
+
149
+ # determine whether we can use the new API or not, and call the appropriate initializer method.
150
+ if (defined?(Puppet::Test::TestHelper))
151
+ Puppet::PuppetSpecInitializer.initialize_via_testhelper(config)
152
+ else
153
+ Puppet::PuppetSpecInitializer.initialize_via_fallback_compatibility(config)
154
+ end
155
+
156
+ # Here we do some general setup that is relevant to all initialization modes, regardless
157
+ # of the availability of the TestHelper API.
158
+
159
+ config.before :each do
160
+ # Here we redirect logging away from console, because otherwise the test output will be
161
+ # obscured by all of the log output.
162
+ #
163
+ # TODO: in a more sane world, we'd move this logging redirection into our TestHelper
164
+ # class, so that it was not coupled with a specific testing framework (rspec in this
165
+ # case). Further, it would be nicer and more portable to encapsulate the log messages
166
+ # into an object somewhere, rather than slapping them on an instance variable of the
167
+ # actual test class--which is what we are effectively doing here.
168
+ #
169
+ # However, because there are over 1300 tests that are written to expect
170
+ # this instance variable to be available--we can't easily solve this problem right now.
171
+ @logs = []
172
+ Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(@logs))
173
+
174
+ @log_level = Puppet::Util::Log.level
175
+ end
176
+
177
+ config.after :each do
178
+ # clean up after the logging changes that we made before each test.
179
+
180
+ # TODO: this should be abstracted in the future--see comments above the '@logs' block in the
181
+ # "before" code above.
182
+ @logs.clear
183
+ Puppet::Util::Log.close_all
184
+ Puppet::Util::Log.level = @log_level
185
+ end
186
+
187
+ end
@@ -0,0 +1,57 @@
1
+ require 'fileutils'
2
+ require 'tempfile'
3
+ require 'pathname'
4
+
5
+ # A support module for testing files.
6
+ module PuppetlabsSpec::Files
7
+ # This code exists only to support tests that run as root, pretty much.
8
+ # Once they have finally been eliminated this can all go... --daniel 2011-04-08
9
+ def self.in_tmp(path)
10
+ tempdir = Dir.tmpdir
11
+
12
+ Pathname.new(path).ascend do |dir|
13
+ return true if File.identical?(tempdir, dir)
14
+ end
15
+
16
+ false
17
+ end
18
+
19
+ def self.cleanup
20
+ $global_tempfiles ||= []
21
+ while path = $global_tempfiles.pop do
22
+ fail "Not deleting tmpfile #{path} outside regular tmpdir" unless in_tmp(path)
23
+
24
+ begin
25
+ FileUtils.rm_r path, :secure => true
26
+ rescue Errno::ENOENT
27
+ # nothing to do
28
+ end
29
+ end
30
+ end
31
+
32
+ def make_absolute(path)
33
+ path = File.expand_path(path)
34
+ path[0] = 'c' if Puppet.features.microsoft_windows?
35
+ path
36
+ end
37
+
38
+ def tmpfilename(name)
39
+ # Generate a temporary file, just for the name...
40
+ source = Tempfile.new(name)
41
+ path = source.path
42
+ source.close!
43
+
44
+ # ...record it for cleanup,
45
+ $global_tempfiles ||= []
46
+ $global_tempfiles << File.expand_path(path)
47
+
48
+ # ...and bam.
49
+ path
50
+ end
51
+
52
+ def tmpdir(name)
53
+ path = tmpfilename(name)
54
+ FileUtils.mkdir_p(path)
55
+ path
56
+ end
57
+ end
@@ -0,0 +1,49 @@
1
+ # This module provides some helper methods to assist with fixtures. It's
2
+ # methods are designed to help when you have a conforming fixture layout so we
3
+ # get project consistency.
4
+ module PuppetlabsSpec::Fixtures
5
+
6
+ # Returns the joined path of the global FIXTURE_DIR plus any path given to it
7
+ def fixtures(*rest)
8
+ File.join(PuppetlabsSpec::FIXTURE_DIR, *rest)
9
+ end
10
+
11
+ # Returns the path to your relative fixture dir. So if your spec test is
12
+ # <project>/spec/unit/facter/foo_spec.rb then your relative dir will be
13
+ # <project>/spec/fixture/unit/facter/foo
14
+ def my_fixture_dir
15
+ callers = caller
16
+ while line = callers.shift do
17
+ next unless found = line.match(%r{/spec/(.*)_spec\.rb:})
18
+ return fixtures(found[1])
19
+ end
20
+ fail "sorry, I couldn't work out your path from the caller stack!"
21
+ end
22
+
23
+ # Given a name, returns the full path of a file from your relative fixture
24
+ # dir as returned by my_fixture_dir.
25
+ def my_fixture(name)
26
+ file = File.join(my_fixture_dir, name)
27
+ unless File.readable? file then
28
+ fail "fixture '#{name}' for #{my_fixture_dir} is not readable"
29
+ end
30
+ return file
31
+ end
32
+
33
+ # Return the contents of the file using read when given a name. Uses
34
+ # my_fixture to work out the relative path.
35
+ def my_fixture_read(name)
36
+ File.read(my_fixture(name))
37
+ end
38
+
39
+ # Provides a block mechanism for iterating across the files in your fixture
40
+ # area.
41
+ def my_fixtures(glob = '*', flags = 0)
42
+ files = Dir.glob(File.join(my_fixture_dir, glob), flags)
43
+ unless files.length > 0 then
44
+ fail "fixture '#{glob}' for #{my_fixture_dir} had no files!"
45
+ end
46
+ block_given? and files.each do |file| yield file end
47
+ files
48
+ end
49
+ end
@@ -0,0 +1,87 @@
1
+ require 'stringio'
2
+
3
+ ########################################################################
4
+ # Backward compatibility for Jenkins outdated environment.
5
+ module RSpec
6
+ module Matchers
7
+ module BlockAliases
8
+ alias_method :to, :should unless method_defined? :to
9
+ alias_method :to_not, :should_not unless method_defined? :to_not
10
+ alias_method :not_to, :should_not unless method_defined? :not_to
11
+ end
12
+ end
13
+ end
14
+
15
+
16
+ ########################################################################
17
+ # Custom matchers...
18
+ RSpec::Matchers.define :have_matching_element do |expected|
19
+ match do |actual|
20
+ actual.any? { |item| item =~ expected }
21
+ end
22
+ end
23
+
24
+
25
+ RSpec::Matchers.define :exit_with do |expected|
26
+ actual = nil
27
+ match do |block|
28
+ begin
29
+ block.call
30
+ rescue SystemExit => e
31
+ actual = e.status
32
+ end
33
+ actual and actual == expected
34
+ end
35
+ failure_message_for_should do |block|
36
+ "expected exit with code #{expected} but " +
37
+ (actual.nil? ? " exit was not called" : "we exited with #{actual} instead")
38
+ end
39
+ failure_message_for_should_not do |block|
40
+ "expected that exit would not be called with #{expected}"
41
+ end
42
+ description do
43
+ "expect exit with #{expected}"
44
+ end
45
+ end
46
+
47
+
48
+ RSpec::Matchers.define :have_printed do |expected|
49
+ match do |block|
50
+ $stderr = $stdout = StringIO.new
51
+
52
+ begin
53
+ block.call
54
+ ensure
55
+ $stdout.rewind
56
+ @actual = $stdout.read
57
+
58
+ $stdout = STDOUT
59
+ $stderr = STDERR
60
+ end
61
+
62
+ if @actual then
63
+ case expected
64
+ when String
65
+ @actual.include? expected
66
+ when Regexp
67
+ expected.match @actual
68
+ else
69
+ raise ArgumentError, "No idea how to match a #{@actual.class.name}"
70
+ end
71
+ end
72
+ end
73
+
74
+ failure_message_for_should do |actual|
75
+ if actual.nil? then
76
+ "expected #{expected.inspect}, but nothing was printed"
77
+ else
78
+ "expected #{expected.inspect} to be printed; got:\n#{actual}"
79
+ end
80
+ end
81
+
82
+ description do
83
+ "expect #{expected.inspect} to be printed"
84
+ end
85
+
86
+ diffable
87
+ end
@@ -0,0 +1,20 @@
1
+ # Define the main module namespace for use by the helper modules
2
+ module PuppetlabsSpec
3
+ end
4
+
5
+ # Require all necessary helper libraries so they can be used later
6
+ require 'puppet_module_spec_helper/puppetlabs_spec/files'
7
+ require 'puppet_module_spec_helper/puppetlabs_spec/fixtures'
8
+ require 'puppet_module_spec_helper/puppetlabs_spec/matchers'
9
+
10
+ RSpec.configure do |config|
11
+ # Include PuppetlabsSpec helpers so they can be called at convenience
12
+ config.extend PuppetlabsSpec::Files
13
+ config.extend PuppetlabsSpec::Fixtures
14
+ config.include PuppetlabsSpec::Fixtures
15
+
16
+ # This will cleanup any files that were created with tmpdir or tmpfile
17
+ config.after :each do
18
+ PuppetlabsSpec::Files.cleanup
19
+ end
20
+ end
@@ -10,6 +10,12 @@ RSpec::Core::RakeTask.new(:spec) do |t|
10
10
  t.pattern = 'spec/{classes,defines,unit}/**/*_spec.rb'
11
11
  end
12
12
 
13
+ desc "Generate code coverage information"
14
+ RSpec::Core::RakeTask.new(:coverage) do |t|
15
+ t.rcov = true
16
+ t.rcov_opts = ['--exclude', 'spec']
17
+ end
18
+
13
19
  # This is a helper for the self-symlink entry of fixtures.yml
14
20
  def source_dir
15
21
  Dir.pwd
metadata CHANGED
@@ -1,114 +1,134 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: puppet_module_spec_helper
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.2
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Branan Purvine-Riley
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2012-05-29 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2012-05-30 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: rake
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :runtime
23
22
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
30
- - !ruby/object:Gem::Dependency
31
- name: rspec
32
- requirement: !ruby/object:Gem::Requirement
23
+ requirement: &id001 !ruby/object:Gem::Requirement
33
24
  none: false
34
- requirements:
35
- - - '='
36
- - !ruby/object:Gem::Version
37
- version: 2.9.0
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
38
32
  type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rspec
39
36
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
37
+ requirement: &id002 !ruby/object:Gem::Requirement
41
38
  none: false
42
- requirements:
43
- - - '='
44
- - !ruby/object:Gem::Version
39
+ requirements:
40
+ - - "="
41
+ - !ruby/object:Gem::Version
42
+ hash: 43
43
+ segments:
44
+ - 2
45
+ - 9
46
+ - 0
45
47
  version: 2.9.0
46
- - !ruby/object:Gem::Dependency
47
- name: mocha
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - '='
52
- - !ruby/object:Gem::Version
53
- version: 0.10.5
54
48
  type: :runtime
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: mocha
55
52
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
53
+ requirement: &id003 !ruby/object:Gem::Requirement
57
54
  none: false
58
- requirements:
59
- - - '='
60
- - !ruby/object:Gem::Version
55
+ requirements:
56
+ - - "="
57
+ - !ruby/object:Gem::Version
58
+ hash: 61
59
+ segments:
60
+ - 0
61
+ - 10
62
+ - 5
61
63
  version: 0.10.5
62
- - !ruby/object:Gem::Dependency
63
- name: rspec-puppet
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: 0.1.1
70
64
  type: :runtime
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: rspec-puppet
71
68
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
69
+ requirement: &id004 !ruby/object:Gem::Requirement
73
70
  none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 25
75
+ segments:
76
+ - 0
77
+ - 1
78
+ - 1
77
79
  version: 0.1.1
78
- description: Contains rake tasks and a standard spec_helper for running spec tests
79
- on puppet modules
80
- email:
80
+ type: :runtime
81
+ version_requirements: *id004
82
+ description: Contains rake tasks and a standard spec_helper for running spec tests on puppet modules
83
+ email:
81
84
  - branan@puppetlabs.com
82
85
  executables: []
86
+
83
87
  extensions: []
88
+
84
89
  extra_rdoc_files: []
85
- files:
90
+
91
+ files:
92
+ - lib/puppet_module_spec_helper/module_spec_helper.rb
93
+ - lib/puppet_module_spec_helper/puppet_spec_helper.rb
94
+ - lib/puppet_module_spec_helper/puppetlabs_spec/files.rb
95
+ - lib/puppet_module_spec_helper/puppetlabs_spec/fixtures.rb
96
+ - lib/puppet_module_spec_helper/puppetlabs_spec/matchers.rb
97
+ - lib/puppet_module_spec_helper/puppetlabs_spec_helper.rb
86
98
  - lib/puppet_module_spec_helper/rake_tasks.rb
87
- - lib/puppet_module_spec_helper/spec_helper.rb
88
- - lib/puppet_module_spec_helper.rb
89
99
  - LICENSE
90
100
  homepage: http://github.com/branan/module-spec-helper
91
101
  licenses: []
102
+
92
103
  post_install_message:
93
104
  rdoc_options: []
94
- require_paths:
105
+
106
+ require_paths:
95
107
  - lib
96
- required_ruby_version: !ruby/object:Gem::Requirement
108
+ required_ruby_version: !ruby/object:Gem::Requirement
97
109
  none: false
98
- requirements:
99
- - - ! '>='
100
- - !ruby/object:Gem::Version
101
- version: '0'
102
- required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ hash: 3
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
118
  none: false
104
- requirements:
105
- - - ! '>='
106
- - !ruby/object:Gem::Version
107
- version: '0'
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ hash: 3
123
+ segments:
124
+ - 0
125
+ version: "0"
108
126
  requirements: []
127
+
109
128
  rubyforge_project:
110
129
  rubygems_version: 1.8.23
111
130
  signing_key:
112
131
  specification_version: 3
113
132
  summary: Standard tasks and configuration for module spec tests
114
133
  test_files: []
134
+
@@ -1 +0,0 @@
1
- require 'puppet_module_spec_helper/spec_helper'