rspec-puppet 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # RSpec tests for your Puppet manifests
1
+ # RSpec tests for your Puppet manifests & modules
2
2
 
3
3
  ## Installation
4
4
 
@@ -24,14 +24,18 @@ structure and naming convention.
24
24
  | +-- <class_name>_spec.rb
25
25
  |
26
26
  +-- defines
27
+ | |
28
+ | +-- <define_name>_spec.rb
29
+ |
30
+ +-- functions
27
31
  |
28
- +-- <define_name>_spec.rb
32
+ +-- <function_name>_spec.rb
29
33
 
30
34
  ## Example groups
31
35
 
32
36
  If you use the above directory structure, your examples will automatically be
33
- placed in the correct groups and have access to the custom matchers. If you
34
- choose not to, you can force the examples into the required groups as follows.
37
+ placed in the correct groups and have access to the custom matchers. *If you
38
+ choose not to*, you can force the examples into the required groups as follows.
35
39
 
36
40
  ```ruby
37
41
  describe 'myclass', :type => :class do
@@ -41,11 +45,17 @@ end
41
45
  describe 'mydefine', :type => :define do
42
46
  ...
43
47
  end
48
+
49
+ describe 'myfunction', :type => :puppet_function do
50
+ ...
51
+ end
44
52
  ```
45
53
 
46
- ## Matchers
54
+ ## Defined Types & Classes
55
+
56
+ ### Matchers
47
57
 
48
- ### Checking if a class has been included
58
+ #### Checking if a class has been included
49
59
 
50
60
  You can test if a class has been included in the catalogue with the
51
61
  `include_class` matcher. It takes the class name as a string as its only
@@ -55,7 +65,7 @@ argument
55
65
  it { should include_class('foo') }
56
66
  ```
57
67
 
58
- ### Checking if a resources exists
68
+ #### Checking if a resource exists
59
69
 
60
70
  You can test if a resource exists in the catalogue with the generic
61
71
  `contain_<resource type>` matcher.
@@ -85,9 +95,9 @@ generic `without_<parameter>` chains.
85
95
  it { should contain_file('/foo/bar').without_mode }
86
96
  ```
87
97
 
88
- ## Writing tests
98
+ ### Writing tests
89
99
 
90
- ### Basic test structure
100
+ #### Basic test structure
91
101
 
92
102
  To test that
93
103
 
@@ -112,19 +122,19 @@ describe 'sysctl' do
112
122
  end
113
123
  ```
114
124
 
115
- ### Specifying the title of a resource
125
+ #### Specifying the title of a resource
116
126
 
117
127
  ```ruby
118
128
  let(:title) { 'foo' }
119
129
  ```
120
130
 
121
- ### Specifying the parameters to pass to a resources or parametised class
131
+ #### Specifying the parameters to pass to a resources or parametised class
122
132
 
123
133
  ```ruby
124
134
  let(:params) { {:ensure => 'present', ...} }
125
135
  ```
126
136
 
127
- ### Specifying the FQDN of the test node
137
+ #### Specifying the FQDN of the test node
128
138
 
129
139
  If the manifest you're testing expects to run on host with a particular name,
130
140
  you can specify this as follows
@@ -133,7 +143,7 @@ you can specify this as follows
133
143
  let(:node) { 'testhost.example.com' }
134
144
  ```
135
145
 
136
- ### Specifying the facts that should be available to your manifest
146
+ #### Specifying the facts that should be available to your manifest
137
147
 
138
148
  By default, the test environment contains no facts for your manifest to use.
139
149
  You can set them with a hash
@@ -142,7 +152,7 @@ You can set them with a hash
142
152
  let(:facts) { {:operatingsystem => 'Debian', :kernel => 'Linux', ...} }
143
153
  ```
144
154
 
145
- ### Specifying the path to find your modules
155
+ #### Specifying the path to find your modules
146
156
 
147
157
  I recommend setting a default module path by adding the following code to your
148
158
  `spec_helper.rb`
@@ -158,3 +168,97 @@ However, if you want to specify it in each example, you can do so
158
168
  ```ruby
159
169
  let(:module_path) { '/path/to/your/module/dir' }
160
170
  ```
171
+
172
+ ## Functions
173
+
174
+ ### Matchers
175
+
176
+ All of the standard RSpec matchers are available for you to use when testing
177
+ Puppet functions.
178
+
179
+ ```ruby
180
+ it 'should be able to do something' do
181
+ subject.call('foo') == 'bar'
182
+ end
183
+ ```
184
+
185
+ For your convenience though, a `run` matcher exists to provide easier to
186
+ understand test cases.
187
+
188
+ ```ruby
189
+ it { should run.with_params('foo').and_return('bar') }
190
+ ```
191
+
192
+ ### Writing tests
193
+
194
+ #### Basic test structure
195
+
196
+ ```ruby
197
+ require 'spec_helper'
198
+
199
+ describe '<function name>' do
200
+ ...
201
+ end
202
+ ```
203
+
204
+ #### Specifying the name of the function to test
205
+
206
+ The name of the function must be provided in the top level description, e.g.
207
+
208
+ ```ruby
209
+ describe 'split' do
210
+ ```
211
+
212
+ #### Specifying the arguments to pass to the function
213
+
214
+ You can specify the arguments to pass to your function during the test(s) using
215
+ either the `with_params` chain method in the `run` matcher
216
+
217
+ ```ruby
218
+ it { should run.with_params('foo', 'bar', ['baz']) }
219
+ ```
220
+
221
+ Or by using the `call` method on the subject directly
222
+
223
+ ```ruby
224
+ it 'something' do
225
+ subject.call('foo', 'bar', ['baz'])
226
+ end
227
+ ```
228
+
229
+ #### Testing the results of the function
230
+
231
+ You can test the result of a function (if it produces one) using either the
232
+ `and_returns` chain method in the `run` matcher
233
+
234
+ ```ruby
235
+ it { should run.with_params('foo').and_return('bar') }
236
+ ```
237
+
238
+ Or by using any of the existing RSpec matchers on the subject directly
239
+
240
+ ```ruby
241
+ it 'something' do
242
+ subject.call('foo') == 'bar'
243
+ subject.call('baz').should be_an Array
244
+ end
245
+ ```
246
+
247
+ #### Testing the errors thrown by the function
248
+
249
+ You can test whether the function throws an exception using either the
250
+ `and_raises_error` chain method in the `run` matcher
251
+
252
+ ```ruby
253
+ it { should run.with_params('a', 'b').and_raise_error(Puppet::ParseError) }
254
+ it { should_not run.with_params('a').and_raise_error(Puppet::ParseError) }
255
+ ```
256
+
257
+ Or by using the existing `raises_error` RSpec matcher
258
+
259
+ ```ruby
260
+ it 'something' do
261
+ expect { subject.call('a', 'b') }.should raise_error(Puppet::ParseError)
262
+ expect { subject.call('a') }.should_not raise_error(Puppet::ParseError)
263
+ end
264
+ ```
@@ -1,6 +1,7 @@
1
1
  require 'rspec-puppet/support'
2
2
  require 'rspec-puppet/example/define_example_group'
3
3
  require 'rspec-puppet/example/class_example_group'
4
+ require 'rspec-puppet/example/function_example_group'
4
5
 
5
6
  RSpec::configure do |c|
6
7
  def c.escaped_path(*parts)
@@ -14,4 +15,8 @@ RSpec::configure do |c|
14
15
  c.include RSpec::Puppet::ClassExampleGroup, :type => :class, :example_group => {
15
16
  :file_path => c.escaped_path(%w[spec classes])
16
17
  }
18
+
19
+ c.include RSpec::Puppet::FunctionExampleGroup, :type => :puppet_function, :example_group => {
20
+ :file_path => c.escaped_path(%w[spec functions])
21
+ }
17
22
  end
@@ -1,6 +1,6 @@
1
1
  module RSpec::Puppet
2
2
  module ClassExampleGroup
3
- include RSpec::Puppet::Matchers
3
+ include RSpec::Puppet::ManifestMatchers
4
4
  include RSpec::Puppet::Support
5
5
 
6
6
  def subject
@@ -1,6 +1,6 @@
1
1
  module RSpec::Puppet
2
2
  module DefineExampleGroup
3
- include RSpec::Puppet::Matchers
3
+ include RSpec::Puppet::ManifestMatchers
4
4
  include RSpec::Puppet::Support
5
5
 
6
6
  def subject
@@ -0,0 +1,17 @@
1
+ module RSpec::Puppet
2
+ module FunctionExampleGroup
3
+ include RSpec::Puppet::FunctionMatchers
4
+
5
+ def subject
6
+ function_name = self.class.top_level_description.downcase
7
+
8
+ Puppet[:modulepath] = self.respond_to?(:module_path) ? module_path : RSpec.configuration.module_path
9
+ Puppet[:libdir] = Dir["#{Puppet[:modulepath]}/*/lib"].entries.join(File::PATH_SEPARATOR)
10
+ Puppet::Parser::Functions.autoloader.loadall
11
+
12
+ scope = Puppet::Parser::Scope.new
13
+
14
+ scope.method "function_#{function_name}".to_sym
15
+ end
16
+ end
17
+ end
@@ -1,3 +1,4 @@
1
1
  require 'rspec-puppet/matchers/create_generic'
2
2
  require 'rspec-puppet/matchers/create_resource'
3
3
  require 'rspec-puppet/matchers/include_class'
4
+ require 'rspec-puppet/matchers/run'
@@ -1,5 +1,5 @@
1
1
  module RSpec::Puppet
2
- module Matchers
2
+ module ManifestMatchers
3
3
  class CreateGeneric
4
4
  def initialize(*args, &block)
5
5
  @exp_resource_type = args.shift.to_s.gsub(/^(create|contain)_/, '')
@@ -76,7 +76,7 @@ module RSpec::Puppet
76
76
  end
77
77
 
78
78
  def method_missing(method, *args, &block)
79
- return RSpec::Puppet::Matchers::CreateGeneric.new(method, *args, &block) if method.to_s =~ /^(create|contain)_/
79
+ return RSpec::Puppet::ManifestMatchers::CreateGeneric.new(method, *args, &block) if method.to_s =~ /^(create|contain)_/
80
80
  super
81
81
  end
82
82
  end
@@ -1,5 +1,5 @@
1
1
  module RSpec::Puppet
2
- module Matchers
2
+ module ManifestMatchers
3
3
  extend RSpec::Matchers::DSL
4
4
 
5
5
  matcher :create_resource do |expected_type, expected_title|
@@ -1,5 +1,5 @@
1
1
  module RSpec::Puppet
2
- module Matchers
2
+ module ManifestMatchers
3
3
  extend RSpec::Matchers::DSL
4
4
 
5
5
  matcher :include_class do |expected_class|
@@ -0,0 +1,76 @@
1
+ module RSpec::Puppet
2
+ module FunctionMatchers
3
+ extend RSpec::Matchers::DSL
4
+
5
+ matcher :run do
6
+ match do |func_obj|
7
+ if @params
8
+ @func = lambda { func_obj.call(@params) }
9
+ else
10
+ @func = lambda { func_obj.call }
11
+ end
12
+
13
+ if @expected_error
14
+ begin
15
+ @func.call
16
+ rescue @expected_error
17
+ #XXX check error string here
18
+ true
19
+ rescue
20
+ false
21
+ end
22
+ else
23
+ if @expected_return
24
+ @func.call == @expected_return
25
+ else
26
+ begin
27
+ @func.call
28
+ rescue
29
+ false
30
+ end
31
+ true
32
+ end
33
+ end
34
+ end
35
+
36
+ chain :with_params do |*params|
37
+ @params = params
38
+ end
39
+
40
+ chain :and_return do |value|
41
+ @expected_return = value
42
+ end
43
+
44
+ # XXX support error string and regexp
45
+ chain :and_raise_error do |value|
46
+ @expected_error = value
47
+ end
48
+
49
+ failure_message_for_should do |func_obj|
50
+ func_name = func_obj.name.gsub(/^function_/, '')
51
+ func_params = @params.inspect[1..-2]
52
+
53
+ if @expected_return
54
+ "expected #{func_name}(#{func_params}) to have returned #{@expected_return.inspect} instead of #{@func.call.inspect}"
55
+ elsif @expected_error
56
+ "expected #{func_name}(#{func_params}) to have raised #{@expected_error.inspect}"
57
+ else
58
+ "expected #{func_name}(#{func_params}) to have run successfully"
59
+ end
60
+ end
61
+
62
+ failure_message_for_should_not do |func_obj|
63
+ func_name = func_obj.name.gsub(/^function_/, '')
64
+ func_params = @params.inspect[1..-2]
65
+
66
+ if @expected_return
67
+ "expected #{func_name}(#{func_params}) to not have returned #{@expected_return.inspect}"
68
+ elsif @expected_error
69
+ "expected #{func_name}(#{func_params}) to not have raised #{@expected_error.inspect}"
70
+ else
71
+ "expected #{func_name}(#{func_params}) to not have run successfully"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'rspec-puppet'
3
- s.version = '0.0.9'
3
+ s.version = '0.1.0'
4
4
  s.homepage = 'https://github.com/rodjek/rspec-puppet/'
5
5
  s.summary = 'RSpec tests for your Puppet manifests'
6
6
  s.description = 'RSpec tests for your Puppet manifests'
@@ -8,10 +8,12 @@ Gem::Specification.new do |s|
8
8
  s.files = [
9
9
  'lib/rspec-puppet/example/class_example_group.rb',
10
10
  'lib/rspec-puppet/example/define_example_group.rb',
11
+ 'lib/rspec-puppet/example/function_example_group.rb',
11
12
  'lib/rspec-puppet/example.rb',
12
13
  'lib/rspec-puppet/matchers/create_generic.rb',
13
14
  'lib/rspec-puppet/matchers/create_resource.rb',
14
15
  'lib/rspec-puppet/matchers/include_class.rb',
16
+ 'lib/rspec-puppet/matchers/run.rb',
15
17
  'lib/rspec-puppet/matchers.rb',
16
18
  'lib/rspec-puppet/support.rb',
17
19
  'lib/rspec-puppet.rb',
@@ -25,6 +27,7 @@ Gem::Specification.new do |s|
25
27
  'spec/defines/sysctl_spec.rb',
26
28
  'spec/fixtures/boolean/manifests/init.pp',
27
29
  'spec/fixtures/sysctl/manifests/init.pp',
30
+ 'spec/functions/split_spec.rb',
28
31
  'spec/spec_helper.rb',
29
32
  ]
30
33
 
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'split' do
4
+ it { should run.with_params('aoeu', 'o').and_return(['a', 'eu']) }
5
+ it { should run.with_params('foo').and_raise_error(Puppet::ParseError) }
6
+ it { should_not run.with_params('foo').and_raise_error(Puppet::DevError) }
7
+
8
+ it 'something' do
9
+ expect { subject.call('foo') }.should raise_error(Puppet::ParseError)
10
+ end
11
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-puppet
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 9
10
- version: 0.0.9
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tim Sharpe
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-09-16 00:00:00 Z
18
+ date: 2011-11-03 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rspec
@@ -42,10 +42,12 @@ extra_rdoc_files: []
42
42
  files:
43
43
  - lib/rspec-puppet/example/class_example_group.rb
44
44
  - lib/rspec-puppet/example/define_example_group.rb
45
+ - lib/rspec-puppet/example/function_example_group.rb
45
46
  - lib/rspec-puppet/example.rb
46
47
  - lib/rspec-puppet/matchers/create_generic.rb
47
48
  - lib/rspec-puppet/matchers/create_resource.rb
48
49
  - lib/rspec-puppet/matchers/include_class.rb
50
+ - lib/rspec-puppet/matchers/run.rb
49
51
  - lib/rspec-puppet/matchers.rb
50
52
  - lib/rspec-puppet/support.rb
51
53
  - lib/rspec-puppet.rb
@@ -59,6 +61,7 @@ files:
59
61
  - spec/defines/sysctl_spec.rb
60
62
  - spec/fixtures/boolean/manifests/init.pp
61
63
  - spec/fixtures/sysctl/manifests/init.pp
64
+ - spec/functions/split_spec.rb
62
65
  - spec/spec_helper.rb
63
66
  homepage: https://github.com/rodjek/rspec-puppet/
64
67
  licenses: []