bean_counter 0.0.1
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.
- data/.gitignore +17 -0
- data/.rdoc_options +9 -0
- data/.rspec +1 -0
- data/.travis.yml +21 -0
- data/Gemfile +11 -0
- data/LICENSE +22 -0
- data/README.md +306 -0
- data/Rakefile +38 -0
- data/bean_counter.gemspec +26 -0
- data/lib/bean_counter.rb +8 -0
- data/lib/bean_counter/core.rb +115 -0
- data/lib/bean_counter/enqueued_expectation.rb +130 -0
- data/lib/bean_counter/mini_test.rb +3 -0
- data/lib/bean_counter/spec.rb +5 -0
- data/lib/bean_counter/spec_matchers.rb +25 -0
- data/lib/bean_counter/strategies/stalk_climber_strategy.rb +150 -0
- data/lib/bean_counter/strategy.rb +250 -0
- data/lib/bean_counter/test_assertions.rb +227 -0
- data/lib/bean_counter/test_unit.rb +3 -0
- data/lib/bean_counter/tube_expectation.rb +66 -0
- data/lib/bean_counter/version.rb +4 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/spec_spec.rb +224 -0
- data/test/test_helper.rb +52 -0
- data/test/unit/core_test.rb +156 -0
- data/test/unit/enqueued_expectation_test.rb +223 -0
- data/test/unit/strategies/stalk_climber_strategy_test.rb +501 -0
- data/test/unit/strategy_test.rb +98 -0
- data/test/unit/test_assertions_test.rb +270 -0
- data/test/unit/tube_expectation_test.rb +93 -0
- metadata +149 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class StrategyTest < BeanCounter::TestCase
|
4
|
+
|
5
|
+
context 'Strategy' do
|
6
|
+
|
7
|
+
context 'inherited' do
|
8
|
+
|
9
|
+
should 'maintain a dict of defined strategies' do
|
10
|
+
initial_strategies = BeanCounter::Strategy.strategies.keys
|
11
|
+
BeanCounter::DummyStrategy = Class.new(BeanCounter::Strategy)
|
12
|
+
new_strategy = BeanCounter::Strategy.strategies.keys - initial_strategies
|
13
|
+
assert_equal 1, new_strategy.length
|
14
|
+
assert_equal BeanCounter::DummyStrategy, BeanCounter::Strategy.strategies[new_strategy.first]
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
context 'known_strategy?' do
|
21
|
+
|
22
|
+
should 'return true for items that subclasses of BeanCounter::Strategy' do
|
23
|
+
assert BeanCounter::Strategy.known_strategy?(BeanCounter::KnownStrategy)
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
should 'try to lookup sym version of identifier if respond to to_sym' do
|
28
|
+
assert BeanCounter::Strategy.known_strategy?(:'BeanCounter::KnownStrategy')
|
29
|
+
refute BeanCounter::Strategy.known_strategy?('BeanCounter::UnknownStrategy')
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
context 'materialize_strategy' do
|
36
|
+
|
37
|
+
should 'raise ArgumentError if unknown strategy' do
|
38
|
+
original_strategy = BeanCounter.strategy
|
39
|
+
[
|
40
|
+
'BeanCounter::UnknownStrategy',
|
41
|
+
:'BeanCounter::UnknownStrategy',
|
42
|
+
String
|
43
|
+
].each do |bad_strategy|
|
44
|
+
assert_raises(ArgumentError) do
|
45
|
+
BeanCounter.strategy = bad_strategy
|
46
|
+
end
|
47
|
+
assert_equal original_strategy, BeanCounter.strategy
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
should 'return class form of strategy when given valid strategy' do
|
53
|
+
[
|
54
|
+
'BeanCounter::KnownStrategy',
|
55
|
+
:'BeanCounter::KnownStrategy',
|
56
|
+
BeanCounter::KnownStrategy
|
57
|
+
].each do |good_strategy|
|
58
|
+
assert_equal(
|
59
|
+
BeanCounter::KnownStrategy,
|
60
|
+
BeanCounter::Strategy.materialize_strategy(good_strategy)
|
61
|
+
)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
context 'strategies' do
|
69
|
+
|
70
|
+
should 'return an immutable dict of strategies' do
|
71
|
+
strategies = BeanCounter::Strategy.strategies
|
72
|
+
strategies[:Foo] = :Foo
|
73
|
+
refute_equal BeanCounter::Strategy.strategies, strategies
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
context 'interface methods' do
|
80
|
+
|
81
|
+
setup do
|
82
|
+
@strategy = BeanCounter::Strategy.new
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
should 'return NotImplementedError for interface methods' do
|
87
|
+
%w[collect_new_jobs delete_job jobs job_matches? pretty_print_job pretty_print_tube tube_matches? tubes].each do |method|
|
88
|
+
assert_raises(NotImplementedError, "Expected strategy to raise NotImplementedError for #{method}") do
|
89
|
+
@strategy.send(method)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,270 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestAssertionsTest < BeanCounter::TestCase
|
4
|
+
|
5
|
+
setup do
|
6
|
+
BeanCounter.reset!
|
7
|
+
@tube_name = SecureRandom.uuid
|
8
|
+
client.transmit("use #{@tube_name}")
|
9
|
+
@message = SecureRandom.uuid
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
# Fuller testing of assertions handled by matcher and strategy tests.
|
14
|
+
# Just make sure assertions work as expected at high level
|
15
|
+
context 'simple job assertions' do
|
16
|
+
|
17
|
+
should 'match any matching job when not given a count' do
|
18
|
+
refute_enqueued(:body => @message)
|
19
|
+
assert_enqueues(:body => @message) do
|
20
|
+
2.times do
|
21
|
+
client.transmit("put 0 0 120 #{@message.bytesize}\r\n#{@message}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
assert_enqueued(:body => @message)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
should 'match count exactly when given integer count' do
|
29
|
+
refute_enqueued(:body => @message)
|
30
|
+
assert_enqueues(:body => @message, :count => 1) do
|
31
|
+
client.transmit("put 0 0 120 #{@message.bytesize}\r\n#{@message}")
|
32
|
+
end
|
33
|
+
assert_enqueued(:body => @message, :count => 1)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
should 'match count to range when given range' do
|
38
|
+
refute_enqueued(:body => @message)
|
39
|
+
assert_enqueues(:body => @message, :count => 1..3) do
|
40
|
+
2.times do
|
41
|
+
client.transmit("put 0 0 120 #{@message.bytesize}\r\n#{@message}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
assert_enqueued(:body => @message, :count => 1..3)
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
context 'failed assertion expectations' do
|
49
|
+
|
50
|
+
setup do
|
51
|
+
# Setting expectation for call count behaves strangely probably because
|
52
|
+
# of expectation on assert. So count assertions manually
|
53
|
+
@assert_calls = 0
|
54
|
+
self.expects(:assert).at_least_once.with do |truth, message|
|
55
|
+
@assert_calls += 1
|
56
|
+
!truth
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
should 'fail assertion when no matching jobs enqueued' do
|
62
|
+
assert_enqueues(:body => /.*/) { }
|
63
|
+
assert_enqueued(:body => /.*/)
|
64
|
+
|
65
|
+
reset_expectations
|
66
|
+
assert_equal 2, @assert_calls
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
should 'fail assertion when no matching jobs enqueued during block' do
|
71
|
+
client.transmit("put 0 0 120 #{@message.bytesize}\r\n#{@message}")
|
72
|
+
assert_enqueues(:body => @message) {}
|
73
|
+
refute_enqueued(:body => %r[(?!#{@message})])
|
74
|
+
|
75
|
+
reset_expectations
|
76
|
+
# Refute calls assert, so assert_calls is incremented
|
77
|
+
assert_equal 2, @assert_calls
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
should 'fail assertion when too few matching jobs enqueued' do
|
82
|
+
assert_enqueues(:body => @message, :count => 2) do
|
83
|
+
client.transmit("put 0 0 120 #{@message.bytesize}\r\n#{@message}")
|
84
|
+
end
|
85
|
+
assert_enqueued(:body => @message, :count => 2)
|
86
|
+
|
87
|
+
reset_expectations
|
88
|
+
assert_equal 2, @assert_calls
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
should 'fail assertion when too many matching jobs enqueued' do
|
93
|
+
assert_enqueues(:body => @message, :count => 1) do
|
94
|
+
2.times do
|
95
|
+
client.transmit("put 0 0 120 #{@message.bytesize}\r\n#{@message}")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
assert_enqueued(:body => @message, :count => 1)
|
99
|
+
|
100
|
+
reset_expectations
|
101
|
+
assert_equal 2, @assert_calls
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
should 'fail assertion when number of matching jobs outside given range' do
|
106
|
+
assert_enqueues(:body => @message, :count => 1..2) do
|
107
|
+
3.times do
|
108
|
+
client.transmit("put 0 0 120 #{@message.bytesize}\r\n#{@message}")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
assert_enqueued(:body => @message, :count => 1..2)
|
112
|
+
|
113
|
+
reset_expectations
|
114
|
+
assert_equal 2, @assert_calls
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
context 'tube assertions' do
|
123
|
+
|
124
|
+
should 'pass assertion when matching tube found' do
|
125
|
+
client.transmit("put 0 0 120 2\r\nxx")
|
126
|
+
client.transmit("put 0 120 120 2\r\nxx")
|
127
|
+
client.transmit("pause-tube #{@tube_name} 0")
|
128
|
+
|
129
|
+
assert_tube({
|
130
|
+
'name' => @tube_name,
|
131
|
+
'cmd-pause' => 1..3,
|
132
|
+
'current-jobs-ready' => 1,
|
133
|
+
'current-jobs-delayed' => 1,
|
134
|
+
'current-using' => 1,
|
135
|
+
})
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
context 'failed assertion expectations' do
|
140
|
+
|
141
|
+
setup do
|
142
|
+
# Setting expectation for call count behaves strangely probably because
|
143
|
+
# of expectation on assert. So count assertions manually
|
144
|
+
@assert_calls = 0
|
145
|
+
self.expects(:assert).at_least_once.with do |truth, message|
|
146
|
+
@assert_calls += 1
|
147
|
+
!truth
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
should 'fail assertion when no matching tubes found' do
|
153
|
+
assert_tube(:name => /#{SecureRandom.uuid}/)
|
154
|
+
|
155
|
+
reset_expectations
|
156
|
+
assert_equal 1, @assert_calls
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
context 'job refutations' do
|
165
|
+
|
166
|
+
should 'pass refutation when no matching jobs are found' do
|
167
|
+
message = SecureRandom.uuid
|
168
|
+
refute_enqueues(:body => message) do
|
169
|
+
client.transmit("put 0 0 120 #{@message.bytesize}\r\n#{@message}")
|
170
|
+
end
|
171
|
+
assert_enqueued(:body => @message)
|
172
|
+
refute_enqueued(:body => message)
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
should 'pass refutation when if no matching jobs are enqueued during block' do
|
177
|
+
client.transmit("put 0 0 120 #{@message.bytesize}\r\n#{@message}")
|
178
|
+
refute_enqueues(:body => @message) {}
|
179
|
+
assert_enqueued(:body => @message)
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
context 'failed refutation expectations' do
|
184
|
+
|
185
|
+
should 'fail refutation when any matching jobs are enqueued' do
|
186
|
+
# Setting expectation for call count behaves strangely probably because
|
187
|
+
# of expectation on refute. So count refutaions manually
|
188
|
+
@refute_calls = 0
|
189
|
+
self.expects(:assert).at_least_once.with do |truth, message|
|
190
|
+
@refute_calls += 1
|
191
|
+
!truth
|
192
|
+
end
|
193
|
+
uuid = SecureRandom.uuid
|
194
|
+
client.transmit("use #{uuid}")
|
195
|
+
refute_enqueues(:body => /.*/) do
|
196
|
+
client.transmit("put 0 0 120 #{uuid.bytesize}\r\n#{uuid}")
|
197
|
+
end
|
198
|
+
refute_enqueued(:body => /.*/)
|
199
|
+
|
200
|
+
reset_expectations
|
201
|
+
assert_equal 2, @refute_calls
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
context 'tube refutations' do
|
210
|
+
|
211
|
+
should 'pass refutation when no matching tubes are found' do
|
212
|
+
refute_tube(:name => SecureRandom.uuid)
|
213
|
+
|
214
|
+
default_stats = client.transmit('stats-tube default')[:body]
|
215
|
+
urgent = default_stats['current-jobs-urgent']
|
216
|
+
refute_tube({
|
217
|
+
'name' => 'default',
|
218
|
+
'current-jobs-urgent' => (urgent + 5)..(urgent + 10),
|
219
|
+
})
|
220
|
+
watching = default_stats['current-watching']
|
221
|
+
refute_tube({
|
222
|
+
'name' => 'default',
|
223
|
+
'current-watching' => watching + 10,
|
224
|
+
})
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
context 'failed refutation expectations' do
|
229
|
+
|
230
|
+
setup do
|
231
|
+
# Setting expectation for call count behaves strangely probably because
|
232
|
+
# of expectation on assert. So count assertions manually
|
233
|
+
@assert_calls = 0
|
234
|
+
self.expects(:assert).at_least_once.with do |truth, message|
|
235
|
+
@assert_calls += 1
|
236
|
+
!truth
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
|
241
|
+
should 'fail assertion when matching tube found' do
|
242
|
+
client.transmit("put 0 0 120 2\r\nxx")
|
243
|
+
client.transmit("put 0 120 120 2\r\nxx")
|
244
|
+
client.transmit("pause-tube #{@tube_name} 0")
|
245
|
+
|
246
|
+
refute_tube({
|
247
|
+
'name' => @tube_name,
|
248
|
+
'cmd-pause' => 1..3,
|
249
|
+
'current-jobs-ready' => 1,
|
250
|
+
'current-jobs-delayed' => 1,
|
251
|
+
'current-using' => 1,
|
252
|
+
})
|
253
|
+
|
254
|
+
reset_expectations
|
255
|
+
assert_equal 1, @assert_calls
|
256
|
+
end
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|
261
|
+
|
262
|
+
|
263
|
+
def reset_expectations
|
264
|
+
# Must manually call mocha_teardown inside test body or expectation
|
265
|
+
# when setting expectation on assert or refute, otherwise expectation
|
266
|
+
# survives to the next test
|
267
|
+
mocha_teardown
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TubeExpectationTest < BeanCounter::TestCase
|
4
|
+
|
5
|
+
TubeExpectation = BeanCounter::TubeExpectation
|
6
|
+
|
7
|
+
context 'failure message' do
|
8
|
+
|
9
|
+
setup do
|
10
|
+
@expectation = TubeExpectation.new({})
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
should 'return expected message if no tube found' do
|
15
|
+
@expectation.strategy.tubes.expects(:detect).returns(nil)
|
16
|
+
@expectation.expected.expects(:to_s).returns('expected')
|
17
|
+
refute @expectation.matches?
|
18
|
+
expected = 'expected tube matching expected, found none.'
|
19
|
+
assert_equal expected, @expectation.failure_message
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
should 'return empty string if tube found' do
|
24
|
+
@expectation.strategy.tubes.expects(:detect).returns(:tube)
|
25
|
+
assert @expectation.matches?
|
26
|
+
assert_equal '', @expectation.failure_message
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
context '#new' do
|
33
|
+
|
34
|
+
should 'set expected correctly' do
|
35
|
+
expected = {:name => 'some_tube'}
|
36
|
+
expectation = TubeExpectation.new(expected)
|
37
|
+
assert_equal expected, expectation.expected
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
context '#matches?' do
|
44
|
+
|
45
|
+
setup do
|
46
|
+
@expectation = TubeExpectation.new({})
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
should 'return true and set found if strategy.tubes includes match' do
|
51
|
+
@expectation.strategy.expects(:tubes).returns([:wrong_tube, :right_tube, :wrong_tube])
|
52
|
+
@expectation.strategy.expects(:tube_matches?).twice.returns(false, true)
|
53
|
+
assert @expectation.matches?
|
54
|
+
assert_equal :right_tube, @expectation.found
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
should 'return false and set found if strategy does not include match' do
|
59
|
+
@expectation.strategy.expects(:tubes).returns([:wrong_tube])
|
60
|
+
@expectation.strategy.expects(:tube_matches?).returns(false)
|
61
|
+
refute @expectation.matches?({})
|
62
|
+
assert_nil @expectation.found
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
context '#negative_failure_message' do
|
69
|
+
|
70
|
+
setup do
|
71
|
+
@expectation = TubeExpectation.new({})
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
should 'return empty string if nothing found' do
|
76
|
+
@expectation.strategy.expects(:tubes).returns([])
|
77
|
+
refute @expectation.matches?
|
78
|
+
assert_equal '', @expectation.negative_failure_message
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
should 'return expected message if a tube found' do
|
83
|
+
@expectation.strategy.tubes.expects(:detect).returns(:tube)
|
84
|
+
@expectation.strategy.expects(:pretty_print_tube).returns('tube')
|
85
|
+
@expectation.expected.expects(:to_s).returns('expected')
|
86
|
+
assert @expectation.matches?
|
87
|
+
expected = 'expected no tubes matching expected, found tube'
|
88
|
+
assert_equal expected, @expectation.negative_failure_message
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|