evented-spec 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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"