minitest-chef-handler 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/History.txt +8 -1
  2. data/LICENSE +1 -0
  3. data/README.md +58 -2
  4. data/Rakefile +15 -0
  5. data/examples/{cookbooks → chef-handler-cookbook/cookbooks}/chef_handler/README.md +0 -0
  6. data/examples/{cookbooks → chef-handler-cookbook/cookbooks}/chef_handler/attributes/default.rb +0 -0
  7. data/examples/{cookbooks → chef-handler-cookbook/cookbooks}/chef_handler/files/default/handlers/README +0 -0
  8. data/examples/{cookbooks → chef-handler-cookbook/cookbooks}/chef_handler/metadata.json +0 -0
  9. data/examples/{cookbooks → chef-handler-cookbook/cookbooks}/chef_handler/metadata.rb +0 -0
  10. data/examples/{cookbooks → chef-handler-cookbook/cookbooks}/chef_handler/providers/default.rb +0 -0
  11. data/examples/{cookbooks → chef-handler-cookbook/cookbooks}/chef_handler/recipes/default.rb +0 -0
  12. data/examples/{cookbooks → chef-handler-cookbook/cookbooks}/chef_handler/recipes/json_file.rb +0 -0
  13. data/examples/{cookbooks → chef-handler-cookbook/cookbooks}/chef_handler/recipes/minitest.rb +0 -0
  14. data/examples/{cookbooks → chef-handler-cookbook/cookbooks}/chef_handler/resources/default.rb +0 -0
  15. data/examples/{cookbooks → simple-solo/cookbooks}/foo/recipes/default.rb +0 -0
  16. data/examples/{cookbooks → simple-solo/cookbooks}/foo/test/test_foo.rb +0 -0
  17. data/examples/{dna.json → simple-solo/dna.json} +0 -0
  18. data/examples/simple-solo/solo.rb +6 -0
  19. data/examples/simple-solo/spec/foo_spec.rb +9 -0
  20. data/examples/{test → simple-solo/test}/test_foo.rb +0 -0
  21. data/examples/spec_examples/attributes/default.rb +8 -0
  22. data/examples/spec_examples/files/default/tests/minitest/example_test.rb +232 -0
  23. data/examples/spec_examples/metadata.rb +5 -0
  24. data/examples/spec_examples/recipes/default.rb +68 -0
  25. data/examples/spec_examples/templates/default/foo.erb +3 -0
  26. data/lib/minitest-chef-handler.rb +8 -23
  27. data/lib/minitest-chef-handler/assertions.rb +129 -0
  28. data/lib/minitest-chef-handler/context.rb +16 -0
  29. data/lib/minitest-chef-handler/infections.rb +37 -0
  30. data/lib/minitest-chef-handler/resources.rb +54 -0
  31. data/lib/minitest-chef-handler/runner.rb +12 -0
  32. data/lib/minitest-chef-handler/spec.rb +19 -0
  33. data/lib/minitest-chef-handler/unit.rb +11 -0
  34. data/minitest-chef-handler.gemspec +3 -1
  35. data/spec/minitest-chef-handler/assertions_spec.rb +293 -0
  36. data/spec/minitest-chef-handler/infections_spec.rb +31 -0
  37. data/spec/minitest-chef-handler/resources_spec.rb +51 -0
  38. data/spec/spec_helper.rb +16 -0
  39. metadata +65 -22
  40. data/examples/solo.rb +0 -4
data/History.txt CHANGED
@@ -1,4 +1,11 @@
1
- === 0.3.0 / 2012-05-10
1
+ === 0.4.0 / 04-20-2012
2
+
3
+ * 2 new features:
4
+
5
+ * Add spec cases support.
6
+ * Add custom assertions support.
7
+
8
+ === 0.3.0 / 04-10-2012
2
9
 
3
10
  * 1 bug fix:
4
11
 
data/LICENSE CHANGED
@@ -1,6 +1,7 @@
1
1
  == minitest-chef-handler
2
2
 
3
3
  Copyright (c) 2012 David Calavera
4
+ Copyright 2012, Opscode, Inc.
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining
6
7
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -17,7 +17,7 @@ $ gem install minitest-chef-handler
17
17
 
18
18
  ## Usage
19
19
 
20
- 1. Add the report handler to your client.rb or solo.rb file:
20
+ Add the report handler to your client.rb or solo.rb file:
21
21
 
22
22
  ```ruby
23
23
  require 'minitest-chef-handler'
@@ -25,7 +25,9 @@ require 'minitest-chef-handler'
25
25
  report_handlers << MiniTest::Chef::Handler.new
26
26
  ```
27
27
 
28
- 2. Write your tests as normal MiniTest cases extending from MiniTest::Chef::TestCase:
28
+ ### Test cases
29
+
30
+ Write your tests as normal MiniTest cases extending from MiniTest::Chef::TestCase:
29
31
 
30
32
  ```ruby
31
33
  class TestNginx < MiniTest::Chef::TestCase
@@ -45,6 +47,60 @@ class TestNginx < MiniTest::Chef::TestCase
45
47
  end
46
48
  ```
47
49
 
50
+ ### Spec cases
51
+
52
+ Wrap your descriptions with a class extending from MiniTest::Chef::Spec:
53
+
54
+ ```ruby
55
+ class NginxSpec < MiniTest::Chef::Spec
56
+ describe 'configuration' do
57
+ it 'creates nginx.conf'
58
+ end
59
+ end
60
+ ```
61
+
62
+ Use the prefix `recipe::` in your descriptions:
63
+
64
+ ```ruby
65
+ describe "recipe::nginx::configuration" do
66
+ it 'creates nginx.conf'
67
+ end
68
+ ```
69
+
70
+ Or use `describe_recipe` to define your specs:
71
+
72
+ ```ruby
73
+ describe_recipe "nginx::configuration" do
74
+ it 'creates nginx.conf'
75
+ end
76
+ ```
77
+
78
+ You still have access to Chef's `run_status`, `node` and `run_context` from your specs:
79
+
80
+ ```ruby
81
+ describe_recipe 'nginx:configuration' do
82
+ it 'installs version 1.0.15' do
83
+ node[:nginx][:version].should == '1.0.15'
84
+ end
85
+ end
86
+ ```
87
+
88
+ ### Custom assertions
89
+
90
+ By including `MiniTest::Chef::Resources` and `MiniTest::Chef::Assertions` you
91
+ can also make assertions like these:
92
+
93
+ ```ruby
94
+ file("/etc/fstab").must_have(:mode, "644")
95
+ package("less").must_be_installed
96
+ service("chef-client").must_be_running
97
+ ```
98
+
99
+ The resources supported are: `cron`, `directory`, `file`, `group`, `ifconfig`,
100
+ `link`, `mount`, `package`, `service` and `user`.
101
+
102
+ For example usage see the tests under the `examples/spec_examples` directory.
103
+
48
104
  ## Further configuration
49
105
 
50
106
  These are the options the handler accepts:
data/Rakefile CHANGED
@@ -1,2 +1,17 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ desc 'Verify that nothing is broken against the simple solo example'
6
+ task :test do
7
+ Dir.chdir('./examples/simple-solo') do
8
+ sh 'ruby -I../../lib -S chef-solo -c solo.rb -j dna.json'
9
+ end
10
+ end
11
+
12
+ Rake::TestTask.new do |t|
13
+ t.name = 'spec'
14
+ t.pattern = 'spec/**/*_spec.rb'
15
+ end
16
+
17
+ task :default => [:spec, :test]
File without changes
@@ -0,0 +1,6 @@
1
+ require 'minitest-chef-handler'
2
+
3
+ path = './{test/test_*,spec/*_spec}.rb'
4
+
5
+ report_handlers << MiniTest::Chef::Handler.new(:path => path)
6
+ cookbook_path File.expand_path('cookbooks', File.dirname(__FILE__))
@@ -0,0 +1,9 @@
1
+ describe_recipe 'foo' do
2
+ it 'creates the temporal file' do
3
+ File.exist?('/tmp/temporal_file').must_equal true
4
+ end
5
+
6
+ it "succeed" do
7
+ run_status.success?.must_equal true
8
+ end
9
+ end
File without changes
@@ -0,0 +1,8 @@
1
+ #
2
+ # Cookbook Name:: spec_examples
3
+ # Attributes:: default
4
+ #
5
+ # Copyright 2012, Opscode, Inc.
6
+ #
7
+
8
+ default['spec_examples']['pager'] = 'less'
@@ -0,0 +1,232 @@
1
+ require 'minitest/spec'
2
+ #
3
+ # Cookbook Name:: spec_examples
4
+ # Spec:: default
5
+ #
6
+ # Copyright 2012, Opscode, Inc.
7
+ #
8
+ describe_recipe 'spec_examples::default' do
9
+
10
+ # It's often convenient to load these includes in a separate helper along with
11
+ # your own helper methods, but here we just include them directly:
12
+ include MiniTest::Chef::Assertions
13
+ include MiniTest::Chef::Context
14
+ include MiniTest::Chef::Resources
15
+
16
+ describe "files" do
17
+
18
+ # = Testing that a file exists =
19
+ #
20
+ # The simplest assertion is that a file exists following the Chef run:
21
+ it "creates the config file" do
22
+ file("/etc/fstab").must_exist
23
+ end
24
+
25
+ # All of the matchers starting with 'must_' also have a negative 'wont_'.
26
+ # So conversely we can also check that a file does not exist:
27
+ it "ensures that the foobar file is removed if present" do
28
+ file("/etc/foobar").wont_exist
29
+ end
30
+
31
+ # = Testing for behaviour =
32
+ #
33
+ # Chef has multiple resource types that create files. We use file to test
34
+ # all of them.
35
+ #
36
+ # This is not valid:
37
+ #
38
+ # cookbook_file(file_path).must_exist
39
+ #
40
+ # Testing the behaviour - is the file is created with the right content?
41
+ # - is preferable to testing how the file gets there. This way if your
42
+ # recipe switches from using a cookbook_file resource to a template resource
43
+ # your tests should still work.
44
+
45
+ # Let's go beyond just checking for existence to testing the other file
46
+ # attributes.
47
+
48
+ # = Other file attributes =
49
+
50
+ # Use .with on a resource and specify the attribute and expected value:
51
+ it "has the expected ownership and permissions" do
52
+ file("/etc/fstab").must_exist.with(:owner, "root")
53
+ end
54
+
55
+ # You can also use .must_have:
56
+ it "only root can modify the config file" do
57
+ file("/etc/fstab").must_have(:mode, "644")
58
+ end
59
+
60
+ # And you can chain attributes together if you are asserting several.
61
+ # You don't want to get too carried away doing this but it can be useful.
62
+ it "only root can modify the config file" do
63
+ file("/etc/fstab").must_have(:mode, "644").with(:owner, "root").and(:group, "root")
64
+ end
65
+
66
+ # Alternatively you could express it like this so each assertion is nicely
67
+ # self-contained:
68
+ describe "only root can modify the config file - alternate syntax" do
69
+ let(:config) { file("/etc/fstab") }
70
+ it { config.must_have(:mode, "644") }
71
+ it { config.must_have(:owner, "root") }
72
+ it { config.must_have(:group, "root") }
73
+ end
74
+
75
+ # = Checking file content =
76
+
77
+ # You can check if a config file contains a string:
78
+ it "sets phasers to stun" do
79
+ file('/tmp/foo').must_include 'phaser_setting=stun'
80
+ end
81
+
82
+ # Or if a file matches a regular expression:
83
+ it "sets phasers to off or stun" do
84
+ file('/tmp/foo').must_match /^phaser_setting=(off|stun)$/
85
+ file('/tmp/foo').wont_match /^phaser_setting=kill$/
86
+ end
87
+
88
+ # = Checking file timestamps =
89
+ it "touches the config to force a reload" do
90
+ file("/tmp/foo").must_be_modified_after(run_status.start_time)
91
+ end
92
+
93
+ it "leaves the hosts file alone" do
94
+ file("/etc/hosts").wont_be_modified_after(run_status.start_time)
95
+ end
96
+
97
+ # = Directories =
98
+
99
+ # The file existence and permissions matchers are also valid for
100
+ # directories:
101
+ it { directory("/etc/").must_exist.with(:owner, "root") }
102
+
103
+ # = Links =
104
+
105
+ it "symlinks the foo in" do
106
+ link("/tmp/foo-symbolic").must_exist.with(
107
+ :link_type, :symbolic).and(:to, "/tmp/foo")
108
+ end
109
+
110
+ end
111
+
112
+ describe "packages" do
113
+
114
+ # = Checking for package install =
115
+ it "installs my favorite pager" do
116
+ package("less").must_be_installed
117
+ end
118
+
119
+ it "doesn't install emacs" do
120
+ package("emacs").wont_be_installed
121
+ end
122
+
123
+ # = Package names =
124
+ #
125
+ # When writing cookbooks intended for use on multiple different operating
126
+ # systems or flavors you will often need to supply a different package
127
+ # name based on the node.platform.
128
+ #
129
+ # If you choose to test for package installation in your tests then you
130
+ # will also need to provide the right package name, which can lead to
131
+ # duplication.
132
+
133
+ it "installs my favorite pager" do
134
+ package(node['spec_examples']['pager']).must_be_installed
135
+ end
136
+
137
+ # = Package versions =
138
+ it "installs the package with the right version" do
139
+ package("less").must_be_installed.with(:version, "436-1")
140
+ end
141
+ end
142
+
143
+ describe "services" do
144
+
145
+ # You can assert that a service must be running following the converge:
146
+ it "runs as a daemon" do
147
+ service("chef-client").must_be_running
148
+ end
149
+
150
+ # And that it will start when the server boots:
151
+ it "boots on startup" do
152
+ service("chef-client").must_be_enabled
153
+ end
154
+
155
+ end
156
+
157
+ describe "users and groups" do
158
+
159
+ # = Users =
160
+
161
+ # Check if a user has been created:
162
+ it "creates a user for the daemon to run as" do
163
+ user("sshd").must_exist
164
+ end
165
+
166
+ # You can also use .with here to test attributes:
167
+ it "creates the user with the expected properties" do
168
+ user("sshd").must_exist.with(:home, '/var/run/sshd')
169
+ end
170
+
171
+ it "has an informative comment against the user" do
172
+ user("list").must_have(:comment, 'Mailing List Manager')
173
+ end
174
+
175
+ it "has the expected uid" do
176
+ user("root").must_have(:uid, 0)
177
+ end
178
+
179
+ # = Groups =
180
+
181
+ it "creates the users group" do
182
+ group("chipmunks").must_exist
183
+ end
184
+
185
+ # Check for group membership, you can pass a single user or an array of
186
+ # users:
187
+ it "grants group membership to the expected users" do
188
+ group("chipmunks").must_include('alvin')
189
+ group("chipmunks").must_include(['alvin', 'simon'])
190
+ group("chipmunks").wont_include('michelangelo')
191
+ end
192
+
193
+ # Alternatively rather than checking if the group includes specific users
194
+ # you can test that the group is made up of exactly the users you specify:
195
+ it "grants group membership only to specific users" do
196
+ group("chipmunks").must_have(:members, ['alvin', 'simon', 'theodore'])
197
+ end
198
+ end
199
+
200
+ describe "cron entries" do
201
+
202
+ it "creates a crontab entry" do
203
+ cron("noop").must_exist.with(:hour, "5").and(:minute, "0").and(:day, "*")
204
+ end
205
+
206
+ it "removes the self-destruct countdown" do
207
+ cron("self-destruct").wont_exist
208
+ end
209
+
210
+ end
211
+
212
+ # Note that the syntax for testing the mount resource is slightly different.
213
+ # You need to specify the device in the call to mount.
214
+ describe "mount" do
215
+ it { mount("/mnt", :device => "/dev/null").must_be_mounted }
216
+ it { mount("/mnt", :device => "/dev/null").must_be_enabled.with(:fstype, "tmpfs") }
217
+ it { mount("/mnt", :device => "/dev/olympus").wont_be_mounted }
218
+ end
219
+
220
+ describe "networking" do
221
+
222
+ # = Test network interface settings =
223
+ describe "ifconfig" do
224
+ it "has the expected network interfaces configured" do
225
+ ifconfig(node['ipaddress'], :device => "eth0").must_exist
226
+ ifconfig(node['ipaddress'], :device => "eth1").wont_exist
227
+ end
228
+ end
229
+
230
+ end
231
+
232
+ end
@@ -0,0 +1,5 @@
1
+ maintainer "Opscode, Inc."
2
+ maintainer_email "andrew@kotirisoftware.com"
3
+ license "MIT"
4
+ description "MiniTest::Spec examples for minitest-chef-handler"
5
+ version "0.1.0"
@@ -0,0 +1,68 @@
1
+ #
2
+ # Cookbook Name:: spec_examples
3
+ # Recipe:: default
4
+ #
5
+ # Copyright 2012, Opscode, Inc.
6
+ #
7
+
8
+ template "/tmp/foo" do
9
+ variables({
10
+ 'phasers' => 'stun'
11
+ })
12
+ action :create
13
+ end
14
+
15
+ file "/tmp/foo" do
16
+ action :touch
17
+ end
18
+
19
+ package "less" do
20
+ action :install
21
+ end
22
+
23
+ package node['spec_examples']['pager'] do
24
+ action :install
25
+ end
26
+
27
+ chipmunks = %w{alvin simon theodore}
28
+ chipmunks.each do |chipmunk|
29
+ user chipmunk do
30
+ action :create
31
+ end
32
+ end
33
+
34
+ group "chipmunks" do
35
+ members chipmunks
36
+ action :create
37
+ end
38
+
39
+ %w{hard symbolic}.each do |link_type|
40
+ link "/tmp/foo-#{link_type}" do
41
+ to "/tmp/foo"
42
+ link_type link_type
43
+ action :create
44
+ end
45
+ end
46
+
47
+ package "cron" do
48
+ action :install
49
+ end
50
+
51
+ cron "noop" do
52
+ hour "5"
53
+ minute "0"
54
+ command "/bin/true"
55
+ end
56
+
57
+ mount "/mnt" do
58
+ pass 0
59
+ fstype "tmpfs"
60
+ device "/dev/null"
61
+ options "nr_inodes=999k,mode=755,size=500m"
62
+ action [:mount, :enable]
63
+ end
64
+
65
+ ifconfig "192.168.20.2" do
66
+ device "eth0"
67
+ action :add
68
+ end