minitest-chef-handler 0.3.0 → 0.4.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.
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