puppet_module_spec_helper 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'