Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 293 lines (211 sloc) 6.295 kb
89ac6b8 @rodjek Initial function testing mock up
authored
1 # RSpec tests for your Puppet manifests & modules
0cfaf65 @rodjek Basic README
authored
2
3610227 @rodjek Update readme
authored
3 ## Installation
4
6c0b835 @rodjek Start documenting all the things
authored
5 gem install rspec-puppet
6
7 ## Naming conventions
8
9 For clarity and consistency, I recommend that you use the following directory
10 structure and naming convention.
11
12 module
13 |
14 +-- manifests
15 |
16 +-- lib
17 |
18 +-- spec
19 |
20 +-- spec_helper.rb
21 |
22 +-- classes
23 | |
24 | +-- <class_name>_spec.rb
25 |
26 +-- defines
89ac6b8 @rodjek Initial function testing mock up
authored
27 | |
28 | +-- <define_name>_spec.rb
29 |
30 +-- functions
a1b5ebe @rodjek Add support for testing the catalogue for a defined host
authored
31 | |
32 | +-- <function_name>_spec.rb
33 |
34 +-- hosts
6c0b835 @rodjek Start documenting all the things
authored
35 |
a1b5ebe @rodjek Add support for testing the catalogue for a defined host
authored
36 +-- <host_name>_spec.rb
6c0b835 @rodjek Start documenting all the things
authored
37
38 ## Example groups
39
40 If you use the above directory structure, your examples will automatically be
89ac6b8 @rodjek Initial function testing mock up
authored
41 placed in the correct groups and have access to the custom matchers. *If you
42 choose not to*, you can force the examples into the required groups as follows.
6c0b835 @rodjek Start documenting all the things
authored
43
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
44 ```ruby
45 describe 'myclass', :type => :class do
46 ...
47 end
6c0b835 @rodjek Start documenting all the things
authored
48
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
49 describe 'mydefine', :type => :define do
50 ...
51 end
89ac6b8 @rodjek Initial function testing mock up
authored
52
53 describe 'myfunction', :type => :puppet_function do
54 ...
55 end
a1b5ebe @rodjek Add support for testing the catalogue for a defined host
authored
56
57 describe 'myhost.example.com', :type => :host do
58 ...
59 end
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
60 ```
6c0b835 @rodjek Start documenting all the things
authored
61
89ac6b8 @rodjek Initial function testing mock up
authored
62 ## Defined Types & Classes
63
64 ### Matchers
6c0b835 @rodjek Start documenting all the things
authored
65
89ac6b8 @rodjek Initial function testing mock up
authored
66 #### Checking if a class has been included
6c0b835 @rodjek Start documenting all the things
authored
67
68 You can test if a class has been included in the catalogue with the
69 `include_class` matcher. It takes the class name as a string as its only
70 argument
71
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
72 ```ruby
73 it { should include_class('foo') }
74 ```
6c0b835 @rodjek Start documenting all the things
authored
75
eb50b75 @rodjek Double plural
authored
76 #### Checking if a resource exists
6c0b835 @rodjek Start documenting all the things
authored
77
78 You can test if a resource exists in the catalogue with the generic
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
79 `contain_<resource type>` matcher.
80
81 ```ruby
82 it { should contain_augeas('bleh') }
83 ```
84
85 If your resource type includes :: (e.g.
d13bee6 @rodjek Update README to suggest contain_ over create_
authored
86 `foo::bar` simply replace the :: with __ (two underscores).
6c0b835 @rodjek Start documenting all the things
authored
87
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
88 ```ruby
89 it { should contain_foo__bar('baz') }
90 ```
6c0b835 @rodjek Start documenting all the things
authored
91
92 You can further test the parameters that have been passed to the resources with
93 the generic `with_<parameter>` chains.
94
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
95 ```ruby
96 it { should contain_package('mysql-server').with_ensure('present') }
97 ```
6c0b835 @rodjek Start documenting all the things
authored
98
4184c54 @bodepd Add with method to generic matcher
bodepd authored
99 You can use the `with` method to verify the value of multiple parameters.
100
101 ```ruby
102 it do should contain_service('keystone').with(
103 'ensure' => 'running',
104 'enable' => 'true',
105 'hasstatus' => 'true',
106 'hasrestart' => 'true'
107 ) end
108 ```
109
ac695d6 @rodjek Add support for testing undefined resource parameters
authored
110 You can also test that specific parameters have been left undefined with the
111 generic `without_<parameter>` chains.
112
113 ```ruby
114 it { should contain_file('/foo/bar').without_mode }
115 ```
116
4588a91 @bodepd Add 'without' method
bodepd authored
117 You can use the without method to verify that a list of parameters have not been
118 defined
119
120 ```ruby
121 it { should contain_service('keystone').without(
122 ['restart', 'status']
123 )}
124 ```
125
89ac6b8 @rodjek Initial function testing mock up
authored
126 ### Writing tests
6c0b835 @rodjek Start documenting all the things
authored
127
89ac6b8 @rodjek Initial function testing mock up
authored
128 #### Basic test structure
0cfaf65 @rodjek Basic README
authored
129
91f1c9a @rodjek Explain it a bit better
authored
130 To test that
131
132 sysctl { 'baz'
133 value => 'foo',
134 }
135
136 Will cause the following resource to be in included in catalogue for a host
137
138 exec { 'sysctl/reload':
139 command => '/sbin/sysctl -p /etc/sysctl.conf',
140 }
141
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
142 We can write the following testcase (in `spec/defines/sysctl_spec.rb`)
91f1c9a @rodjek Explain it a bit better
authored
143
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
144 ```ruby
145 describe 'sysctl' do
146 let(:title) { 'baz' }
147 let(:params) { { :value => 'foo' } }
0cfaf65 @rodjek Basic README
authored
148
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
149 it { should contain_exec('sysctl/reload').with_command("/sbin/sysctl -p /etc/sysctl.conf") }
150 end
151 ```
6c0b835 @rodjek Start documenting all the things
authored
152
89ac6b8 @rodjek Initial function testing mock up
authored
153 #### Specifying the title of a resource
6c0b835 @rodjek Start documenting all the things
authored
154
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
155 ```ruby
156 let(:title) { 'foo' }
157 ```
6c0b835 @rodjek Start documenting all the things
authored
158
89ac6b8 @rodjek Initial function testing mock up
authored
159 #### Specifying the parameters to pass to a resources or parametised class
6c0b835 @rodjek Start documenting all the things
authored
160
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
161 ```ruby
162 let(:params) { {:ensure => 'present', ...} }
163 ```
6c0b835 @rodjek Start documenting all the things
authored
164
89ac6b8 @rodjek Initial function testing mock up
authored
165 #### Specifying the FQDN of the test node
6c0b835 @rodjek Start documenting all the things
authored
166
167 If the manifest you're testing expects to run on host with a particular name,
168 you can specify this as follows
169
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
170 ```ruby
171 let(:node) { 'testhost.example.com' }
172 ```
6c0b835 @rodjek Start documenting all the things
authored
173
89ac6b8 @rodjek Initial function testing mock up
authored
174 #### Specifying the facts that should be available to your manifest
6c0b835 @rodjek Start documenting all the things
authored
175
176 By default, the test environment contains no facts for your manifest to use.
177 You can set them with a hash
178
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
179 ```ruby
180 let(:facts) { {:operatingsystem => 'Debian', :kernel => 'Linux', ...} }
181 ```
6c0b835 @rodjek Start documenting all the things
authored
182
89ac6b8 @rodjek Initial function testing mock up
authored
183 #### Specifying the path to find your modules
6c0b835 @rodjek Start documenting all the things
authored
184
185 I recommend setting a default module path by adding the following code to your
186 `spec_helper.rb`
187
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
188 ```ruby
189 RSpec.configure do |c|
190 c.module_path = '/path/to/your/module/dir'
191 end
192 ```
6c0b835 @rodjek Start documenting all the things
authored
193
194 However, if you want to specify it in each example, you can do so
195
20cfb2d @rodjek Prettify README with some syntax highlighting
authored
196 ```ruby
197 let(:module_path) { '/path/to/your/module/dir' }
198 ```
89ac6b8 @rodjek Initial function testing mock up
authored
199
200 ## Functions
201
202 ### Matchers
203
204 All of the standard RSpec matchers are available for you to use when testing
205 Puppet functions.
206
81257c7 @rodjek Document function testing
authored
207 ```ruby
208 it 'should be able to do something' do
209 subject.call('foo') == 'bar'
210 end
211 ```
212
213 For your convenience though, a `run` matcher exists to provide easier to
214 understand test cases.
215
216 ```ruby
217 it { should run.with_params('foo').and_return('bar') }
218 ```
219
89ac6b8 @rodjek Initial function testing mock up
authored
220 ### Writing tests
221
222 #### Basic test structure
223
81257c7 @rodjek Document function testing
authored
224 ```ruby
225 require 'spec_helper'
226
227 describe '<function name>' do
228 ...
229 end
230 ```
231
89ac6b8 @rodjek Initial function testing mock up
authored
232 #### Specifying the name of the function to test
233
81257c7 @rodjek Document function testing
authored
234 The name of the function must be provided in the top level description, e.g.
235
236 ```ruby
237 describe 'split' do
238 ```
239
89ac6b8 @rodjek Initial function testing mock up
authored
240 #### Specifying the arguments to pass to the function
241
81257c7 @rodjek Document function testing
authored
242 You can specify the arguments to pass to your function during the test(s) using
243 either the `with_params` chain method in the `run` matcher
89ac6b8 @rodjek Initial function testing mock up
authored
244
245 ```ruby
81257c7 @rodjek Document function testing
authored
246 it { should run.with_params('foo', 'bar', ['baz']) }
89ac6b8 @rodjek Initial function testing mock up
authored
247 ```
248
81257c7 @rodjek Document function testing
authored
249 Or by using the `call` method on the subject directly
250
251 ```ruby
252 it 'something' do
253 subject.call('foo', 'bar', ['baz'])
254 end
255 ```
89ac6b8 @rodjek Initial function testing mock up
authored
256
257 #### Testing the results of the function
258
81257c7 @rodjek Document function testing
authored
259 You can test the result of a function (if it produces one) using either the
260 `and_returns` chain method in the `run` matcher
89ac6b8 @rodjek Initial function testing mock up
authored
261
262 ```ruby
81257c7 @rodjek Document function testing
authored
263 it { should run.with_params('foo').and_return('bar') }
264 ```
265
266 Or by using any of the existing RSpec matchers on the subject directly
267
268 ```ruby
269 it 'something' do
270 subject.call('foo') == 'bar'
271 subject.call('baz').should be_an Array
89ac6b8 @rodjek Initial function testing mock up
authored
272 end
273 ```
81257c7 @rodjek Document function testing
authored
274
275 #### Testing the errors thrown by the function
276
277 You can test whether the function throws an exception using either the
278 `and_raises_error` chain method in the `run` matcher
279
280 ```ruby
281 it { should run.with_params('a', 'b').and_raise_error(Puppet::ParseError) }
282 it { should_not run.with_params('a').and_raise_error(Puppet::ParseError) }
283 ```
284
285 Or by using the existing `raises_error` RSpec matcher
286
287 ```ruby
288 it 'something' do
289 expect { subject.call('a', 'b') }.should raise_error(Puppet::ParseError)
290 expect { subject.call('a') }.should_not raise_error(Puppet::ParseError)
bb9f233 @rodjek Missing an end in an example
authored
291 end
81257c7 @rodjek Document function testing
authored
292 ```
Something went wrong with that request. Please try again.