evented-spec 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.
@@ -0,0 +1,32 @@
1
+ module EventedSpec
2
+ # Miscellanous utility methods used throughout the code.
3
+ module Util
4
+ extend self
5
+
6
+ # Creates a deep clone of an object. Different from normal Object#clone
7
+ # method which is shallow clone (doesn't traverse hashes and arrays,
8
+ # cloning their contents).
9
+ #
10
+ # @param Object to clone
11
+ # @return Deep clone of the given object
12
+ def deep_clone(value)
13
+ case value
14
+ when Hash
15
+ value.inject({}) do |result, kv|
16
+ result[kv[0]] = deep_clone(kv[1])
17
+ result
18
+ end
19
+ when Array
20
+ value.inject([]) do |result, item|
21
+ result << deep_clone(item)
22
+ end
23
+ else
24
+ begin
25
+ value.clone
26
+ rescue TypeError
27
+ value
28
+ end
29
+ end
30
+ end # deep_clone
31
+ end # module Util
32
+ end # module EventedSpec
@@ -0,0 +1,8 @@
1
+ require 'pathname'
2
+
3
+ module EventedSpec
4
+ # Path to version file
5
+ VERSION_FILE = Pathname.new(__FILE__).dirname + '/../../VERSION'
6
+ # Gem version
7
+ VERSION = VERSION_FILE.exist? ? VERSION_FILE.read.strip : nil
8
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe EventedSpec::SpecHelper, "Cool.io bindings" do
5
+ include EventedSpec::SpecHelper
6
+ default_timeout 0.1
7
+ let(:event_loop) { Coolio::Loop.default }
8
+
9
+ after(:each) {
10
+ event_loop.instance_variable_get(:@running).should be_false
11
+ }
12
+
13
+ describe "#coolio" do
14
+ it "should execute given block in the right scope" do
15
+ coolio do
16
+ @variable = true
17
+ done
18
+ end
19
+ @variable.should be_true
20
+ end
21
+
22
+ it "should start default cool.io loop and give control" do
23
+ coolio do
24
+ event_loop.instance_variable_get(:@running).should be_true
25
+ done
26
+ end
27
+ end
28
+
29
+ it "should stop the event loop afterwards" do
30
+ coolio do
31
+ @do_something_useful = true
32
+ done
33
+ end
34
+ event_loop.instance_variable_get(:@running).should be_false
35
+ end
36
+
37
+ it "should raise SpecTimeoutExceededError when #done is not issued" do
38
+ expect {
39
+ coolio do
40
+ end
41
+ }.to raise_error(EventedSpec::SpecHelper::SpecTimeoutExceededError)
42
+ end
43
+
44
+ it "should propagate mismatched rspec expectations" do
45
+ expect {
46
+ coolio do
47
+ :fail.should == :win
48
+ end
49
+ }.to raise_error(RSPEC::Expectations::ExpectationNotMetError)
50
+ end
51
+ end
52
+
53
+
54
+ describe "#done" do
55
+ it "should execute given block" do
56
+ coolio do
57
+ done(0.05) do
58
+ @variable = true
59
+ end
60
+ end
61
+ @variable.should be_true
62
+ end
63
+
64
+ it "should cancel timeout" do
65
+ expect {
66
+ coolio do
67
+ done(0.2)
68
+ end
69
+ }.to_not raise_error
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,132 @@
1
+ require 'spec_helper'
2
+
3
+ describe EventedSpec::SpecHelper, " .default_options" do
4
+ include EventedSpec::SpecHelper
5
+ root_default_options = {:root_key => 1}
6
+ default_options root_default_options
7
+
8
+ it 'subsequent and nested groups should not change root default options' do
9
+ root_default_options.should == {:root_key => 1}
10
+ end
11
+
12
+ it 'example has access to default options' do
13
+ default_options.should == root_default_options
14
+ end
15
+
16
+ it 'defaults can be changed inside example, diverging from example group defaults' do
17
+ default_options[:example_key] = :example_value
18
+ default_options.should have_key :example_key
19
+ default_options.should_not == root_default_options
20
+ end
21
+
22
+ it 'changing example defaults has no effect on subsequent examples' do
23
+ default_options.should_not have_key :example_key
24
+ default_options.should == root_default_options
25
+ end
26
+
27
+ context 'inside nested example group 1' do
28
+ nested_default_options = default_options
29
+
30
+ it 'nested group defaults start as a copy of enclosing group default_options' do
31
+ nested_default_options.should == root_default_options
32
+ end
33
+
34
+ it 'example has access to default options' do
35
+ default_options.should == nested_default_options
36
+ end
37
+
38
+ it 'can be changed, thus diverging from example group default_options' do
39
+ default_options[:example_key] = :example_value
40
+ default_options.should have_key :example_key
41
+ default_options.should_not == root_default_options
42
+ end
43
+
44
+ it 'changing example default_options has no effect on subsequent examples' do
45
+ default_options.should_not have_key :example_key
46
+ default_options.should == root_default_options
47
+ end
48
+
49
+ context 'inside deeply nested example group 1' do
50
+ nested_default_options = default_options
51
+
52
+ it 'nested group defaults start as a copy of enclosing group default_options' do
53
+ nested_default_options.should == root_default_options
54
+ end
55
+
56
+ it 'example has access to default options' do
57
+ default_options.should == nested_default_options
58
+ end
59
+
60
+ it 'can be changed in example, thus diverging from example group default_options' do
61
+ default_options[:example_key] = :example_value
62
+ default_options.should have_key :example_key
63
+ default_options.should_not == nested_default_options
64
+ end
65
+
66
+ it 'changing example default_options has no effect on subsequent examples' do
67
+ default_options.should_not have_key :example_key
68
+ default_options.should == nested_default_options
69
+ end
70
+ end # inside deeply nested example group 1
71
+ end # inside nested example group 1
72
+
73
+ context 'inside nested example group 2' do
74
+ default_options[:nested_key] = :nested_value
75
+ nested_default_options = default_options
76
+
77
+ it 'changing default options inside nested group works' do
78
+ nested_default_options.should have_key :nested_key
79
+ end
80
+
81
+ it 'changing default_options in nested group affects example default_options' do
82
+ default_options.should == nested_default_options
83
+ default_options.should_not == root_default_options
84
+ end
85
+
86
+ it 'can be changed in example, thus diverging from example group default_options' do
87
+ default_options[:example_key] = :example_value
88
+ default_options.should have_key :example_key
89
+ default_options.should have_key :nested_key
90
+ default_options.should_not == nested_default_options
91
+ default_options.should_not == root_default_options
92
+ end
93
+
94
+ it 'changing example default_options has no effect on subsequent examples' do
95
+ default_options.should == nested_default_options
96
+ end
97
+
98
+ context 'inside deeply nested example group 2' do
99
+ default_options[:deeply_nested_key] = :deeply_nested_value
100
+ deeply_nested_default_options = default_options
101
+
102
+ it 'inherits default options from enclosing group' do
103
+ deeply_nested_default_options.should have_key :nested_key
104
+ end
105
+
106
+ it 'changing default options inside deeply nested group works' do
107
+ deeply_nested_default_options.should have_key :deeply_nested_key
108
+ end
109
+
110
+ it 'changing default_options in nested group affects example group default_options' do
111
+ default_options.should == deeply_nested_default_options
112
+ default_options.should have_key :nested_key
113
+ default_options.should have_key :deeply_nested_key
114
+ default_options.should_not == nested_default_options
115
+ default_options.should_not == root_default_options
116
+ end
117
+
118
+ it 'can be changed in example, thus diverging from example group default_options' do
119
+ default_options[:example_key] = :example_value
120
+ default_options.should have_key :example_key
121
+ default_options.should have_key :nested_key
122
+ default_options.should have_key :deeply_nested_key
123
+ default_options.should_not == nested_default_options
124
+ default_options.should_not == root_default_options
125
+ end
126
+
127
+ it 'changing example default_options has no effect on subsequent examples' do
128
+ default_options.should == deeply_nested_default_options
129
+ end
130
+ end # inside deeply nested example group 2
131
+ end # inside nested example group 2
132
+ end # describe AMQP, "default_options"
@@ -0,0 +1,231 @@
1
+ require 'spec_helper'
2
+
3
+ # Registers specific hook type as being called,
4
+ # sets expectations about EM reactor and AMQP connection state
5
+ module HookHelper
6
+ def hook(type, reactor, connection)
7
+ @hooks_called << type.to_sym if type
8
+ if :reactor_running == reactor
9
+ EM.reactor_running?.should be_true
10
+ else
11
+ EM.reactor_running?.should be_false
12
+ end
13
+ if :amqp_connected == connection
14
+ AMQP.connection.should be_connected
15
+ else
16
+ if AMQP.connection
17
+ AMQP.connection.connected?.should be_false
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ shared_examples_for 'hooked em specs' do
24
+ it 'should execute em_before' do
25
+ em do
26
+ @hooks_called.should include :em_before
27
+ @hooks_called.should_not include :em_after
28
+ done
29
+ end
30
+ end
31
+
32
+ it 'should execute em_after if business exception is raised' do
33
+ # Expectation is set in after{} hook
34
+ em do
35
+ expect {
36
+ raise StandardError
37
+ }.to raise_error
38
+ done
39
+ end
40
+ end
41
+
42
+ it 'should execute em_after if RSpec expectation fails' do
43
+ # Expectation is set in after{} hook
44
+ em do
45
+ expect { :this.should == :fail
46
+ }.to raise_error RSPEC::Expectations::ExpectationNotMetError
47
+ done
48
+ end
49
+ end
50
+ end
51
+
52
+ shared_examples_for 'hooked amqp specs' do
53
+ it 'should execute em_before' do
54
+ amqp do
55
+ @hooks_called.should include :em_before
56
+ @hooks_called.should_not include :em_after
57
+ @hooks_called.should include :amqp_before
58
+ @hooks_called.should_not include :amqp_after
59
+ done
60
+ end
61
+ end
62
+
63
+ it 'should execute em_after if business exception is raised' do
64
+ # Expectation is set in after{} hook
65
+ amqp do
66
+ expect {
67
+ raise StandardError
68
+ }.to raise_error
69
+ done
70
+ end
71
+ end
72
+
73
+ it 'should execute em_after if RSpec expectation fails' do
74
+ # Expectation is set in after{} hook
75
+ amqp do
76
+ expect { :this.should == :fail
77
+ }.to raise_error RSPEC::Expectations::ExpectationNotMetError
78
+ done
79
+ end
80
+ end
81
+ end
82
+
83
+ describe EventedSpec::SpecHelper, ".em_before/.em_after" do
84
+ before { @hooks_called = [] }
85
+ include HookHelper
86
+ describe AMQP, " tested with EventedSpec::SpecHelper" do
87
+ include EventedSpec::SpecHelper
88
+ default_options AMQP_OPTS if defined? AMQP_OPTS
89
+
90
+ before { hook :before, :reactor_not_running, :amqp_not_connected }
91
+ em_before { hook :em_before, :reactor_running, :amqp_not_connected }
92
+ em_after { hook(:em_after, :reactor_running, :amqp_not_connected) }
93
+
94
+ context 'for non-evented specs' do
95
+ after {
96
+ @hooks_called.should == [:before]
97
+ hook :after, :reactor_not_running, :amqp_not_connected }
98
+
99
+ it 'should NOT execute em_before or em_after' do
100
+ @hooks_called.should_not include :em_before
101
+ @hooks_called.should_not include :em_after
102
+ end
103
+
104
+ it 'should NOT execute em_after if business exception is raised' do
105
+ expect { raise StandardError
106
+ }.to raise_error
107
+ end
108
+
109
+ it 'should execute em_after if RSpec expectation fails' do
110
+ expect { :this.should == :fail
111
+ }.to raise_error RSPEC::Expectations::ExpectationNotMetError
112
+ end
113
+ end # context 'for non-evented specs'
114
+
115
+ context 'for evented specs' do #, pending: true do
116
+ after do
117
+ @hooks_called.should include :before, :em_before, :em_after
118
+ hook :after, :reactor_not_running, :amqp_not_connected
119
+ end
120
+
121
+ context 'with em block' do
122
+
123
+ it_should_behave_like 'hooked em specs'
124
+
125
+ it 'should not run nested em hooks' do
126
+ em do
127
+ @hooks_called.should_not include :context_em_before, :context_before
128
+ done
129
+ end
130
+ end
131
+
132
+ it 'should not run hooks from unrelated group' do
133
+ em do
134
+ @hooks_called.should_not include :amqp_context_em_before,
135
+ :amqp_context_before,
136
+ :amqp_before,
137
+ :context_amqp_before
138
+ done
139
+ end
140
+ end
141
+
142
+ context 'inside nested example group' do
143
+ before { hook :context_before, :reactor_not_running, :amqp_not_connected }
144
+ em_before { hook :context_em_before, :reactor_running, :amqp_not_connected }
145
+ em_after { hook :context_em_after, :reactor_running, :amqp_not_connected }
146
+
147
+ after do
148
+ @hooks_called.should include :before,
149
+ :context_before,
150
+ :em_before,
151
+ :context_em_before,
152
+ :context_em_after,
153
+ :em_after
154
+ hook :after, :reactor_not_running, :amqp_not_connected
155
+ end
156
+
157
+ it_should_behave_like 'hooked em specs'
158
+
159
+ it 'should fire all nested :before hooks, but no :after hooks' do
160
+ em do
161
+ @hooks_called.should == [:before,
162
+ :context_before,
163
+ :em_before,
164
+ :context_em_before]
165
+ done
166
+ end
167
+ end
168
+
169
+ end # context 'inside nested example group'
170
+ end # context 'with em block'
171
+
172
+ context 'with amqp block' do
173
+ amqp_before { hook :amqp_before, :reactor_running, :amqp_connected }
174
+ amqp_after { hook :amqp_after, :reactor_running, :amqp_connected }
175
+
176
+ it_should_behave_like 'hooked amqp specs'
177
+
178
+ it 'should not run nested em hooks' do
179
+ amqp do
180
+ @hooks_called.should_not include :amqp_context_before,
181
+ :amqp_context_em_before,
182
+ :context_amqp_before
183
+ done
184
+ end
185
+ end
186
+
187
+ it 'should not run hooks from unrelated group' do
188
+ amqp do
189
+ @hooks_called.should_not include :context_em_before, :context_before
190
+ done
191
+ end
192
+ end
193
+
194
+ context 'inside nested example group' do
195
+ before { hook :amqp_context_before, :reactor_not_running, :amqp_not_connected }
196
+ em_before { hook :amqp_context_em_before, :reactor_running, :amqp_not_connected }
197
+ em_after { hook :amqp_context_em_after, :reactor_running, :amqp_not_connected }
198
+ amqp_before { hook :context_amqp_before, :reactor_running, :amqp_connected }
199
+ amqp_after { hook :context_amqp_after, :reactor_running, :amqp_connected }
200
+
201
+ after { @hooks_called.should == [:before,
202
+ :amqp_context_before,
203
+ :em_before,
204
+ :amqp_context_em_before,
205
+ :amqp_before,
206
+ :context_amqp_before,
207
+ :context_amqp_after,
208
+ :amqp_after,
209
+ :amqp_context_em_after,
210
+ :em_after]
211
+ hook :after, :reactor_not_running, :amqp_not_connected }
212
+
213
+ it_should_behave_like 'hooked amqp specs'
214
+
215
+ it 'should fire all :before hooks in correct order' do
216
+ amqp do
217
+ @hooks_called.should == [:before,
218
+ :amqp_context_before,
219
+ :em_before,
220
+ :amqp_context_em_before,
221
+ :amqp_before,
222
+ :context_amqp_before]
223
+ done
224
+ end
225
+ end
226
+
227
+ end # context 'inside nested example group'
228
+ end # context 'with amqp block'
229
+ end # context 'for evented specs'
230
+ end # describe EventedSpec, " tested with EventedSpec::SpecHelper"
231
+ end # describe EventedSpec, " with em_before/em_after"