methodical 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,217 @@
1
+ require File.expand_path("../test_helper", File.dirname(__FILE__))
2
+ require 'methodical/dsl'
3
+ require 'methodical/action_item'
4
+
5
+ class DslTest < Test::Unit::TestCase
6
+ include Methodical::DSL
7
+
8
+ context "#action" do
9
+ specify "constructs an ActionItem" do
10
+ step = action("TITLE") do
11
+ "RESULT"
12
+ end
13
+
14
+ assert_kind_of Methodical::ActionItem, step
15
+ assert_equal "TITLE", step.title
16
+ assert_equal "RESULT", step.execute!.result
17
+ end
18
+ end
19
+
20
+ context "#sufficient" do
21
+ specify "makes successful actions sufficient" do
22
+ step = action("TITLE") do "RESULT" end
23
+ sufficient_step = sufficient << step
24
+
25
+ assert_equal :sufficient, sufficient_step.execute!.status
26
+ end
27
+
28
+ specify "has no effect on unsuccessful actions" do
29
+ step = action("TITLE") do raise "FAIL" end
30
+ sufficient_step = sufficient << step
31
+
32
+ assert_equal :failed, sufficient_step.execute!.status
33
+ end
34
+ end
35
+
36
+ context "#requisite" do
37
+ specify "makes failed actions abort" do
38
+ step = action("TITLE") do raise "FAIL" end
39
+ requisite_step = requisite << step
40
+
41
+ disposition = requisite_step.execute!
42
+ assert_equal :abort, disposition.status
43
+ end
44
+ end
45
+
46
+ context "#ignore" do
47
+ specify "makes steps ignorable" do
48
+ step = action("TITLE") do raise "FAIL" end
49
+ ignored_step = ignore << step
50
+ ignored_step.execute!
51
+ assert ignored_step.ignored?
52
+ end
53
+ end
54
+
55
+ context "#skip_if" do
56
+ specify "skips step if condition is true" do
57
+ step = skip_if(""){true} << action("TITLE") do
58
+ flunk("Should not get here")
59
+ end
60
+ assert_equal :skipped, step.execute!().status
61
+ end
62
+
63
+ specify "performs step if condition is false" do
64
+ sensor = :unset
65
+ step = skip_if(""){false} << action("TITLE") do
66
+ "RESULT"
67
+ end
68
+ assert_equal "RESULT", step.execute!.result
69
+ end
70
+
71
+ specify "passes baton into condition" do
72
+ baton = stub("Baton")
73
+ sensor = :unset
74
+ step = skip_if(""){|b, s| sensor = b} << action("TITLE") do
75
+ "RESULT"
76
+ end
77
+ step.execute!(baton)
78
+ assert_same baton, sensor
79
+ end
80
+
81
+ specify "passes step into condition" do
82
+ baton = stub("Baton")
83
+ sensor = :unset
84
+ step = skip_if(""){|b, s| sensor = s} << inner = action("TITLE") do
85
+ "RESULT"
86
+ end
87
+ step.execute!(baton)
88
+ assert_same inner, sensor
89
+ end
90
+
91
+ specify "returns reason if skipped" do
92
+ step = skip_if("EXPL"){true} << action("TITLE") do
93
+ flunk("Should not get here")
94
+ end
95
+ assert_equal "EXPL", step.execute!().explanation
96
+ end
97
+
98
+ specify "updates status of step" do
99
+ step = skip_if("EXPL"){true} << action("TITLE") do
100
+ flunk("Should not get here")
101
+ end
102
+ step.execute!
103
+ assert_equal "EXPL", step.explanation
104
+ assert_equal :skipped, step.status
105
+ end
106
+ end
107
+
108
+ context "#handle_error" do
109
+ specify "rescues errors" do
110
+ step = handle_error(RuntimeError){|b,s,e| s.succeed! } <<
111
+ action("TITLE") do
112
+ raise "UH-OH"
113
+ end
114
+ assert_nothing_raised do
115
+ step.execute!(nil, true)
116
+ end
117
+ end
118
+
119
+ specify "substitutes its own disposition" do
120
+ step = handle_error(RuntimeError){|b,s,e| s.succeed! } <<
121
+ action("TITLE") do
122
+ raise "UH-OH"
123
+ end
124
+ assert_equal :succeeded, step.execute!(nil, true).status
125
+ end
126
+
127
+ end
128
+
129
+ context "#filter" do
130
+ specify "modifies step disposition" do
131
+ step = filter {|d|
132
+ d.merge(:status => :failed, :explanation => "MODIFIED")
133
+ } << action("TITLE") {
134
+ |b,s| s.succeed!("ORIGINAL")
135
+ }
136
+ result = step.execute!
137
+ assert_equal :failed, result.status
138
+ assert_equal "MODIFIED", result.explanation
139
+ assert_equal :failed, step.status
140
+ assert_equal "MODIFIED", step.explanation
141
+ end
142
+ end
143
+
144
+ context "#recover_failure" do
145
+ specify "executes block on failure" do
146
+ sensor = :unset
147
+ step = action("test") do |b,s| s.fail!("FAIL") end
148
+ wrapped_step = recover_failure do |baton, step, disposition|
149
+ sensor = :set
150
+ end << step
151
+ wrapped_step.execute!
152
+ assert_equal :set, sensor
153
+ end
154
+
155
+ specify "does not execute block on success" do
156
+ sensor = :unset
157
+ step = action("test") do |b,s| s.succeed!("OK") end
158
+ wrapped_step = recover_failure do |baton, step, disposition|
159
+ sensor = :set
160
+ end << step
161
+ wrapped_step.execute!
162
+ assert_equal :unset, sensor
163
+ end
164
+
165
+ specify "does not execute block on error" do
166
+ sensor = :unset
167
+ step = action("test") do raise StandardError, "BAD" end
168
+ wrapped_step = recover_failure do |baton, step, disposition|
169
+ sensor = :set
170
+ end << step
171
+ wrapped_step.execute!
172
+ assert_equal :unset, sensor
173
+ end
174
+ end
175
+
176
+ context "#retry_on_failure" do
177
+ specify "retries on failure" do
178
+ call_count = 0
179
+ step = action("test") do
180
+ call_count += 1
181
+ if call_count == 1
182
+ raise RuntimeError, "FAIL!"
183
+ end
184
+ end
185
+ wrapped_step = (retry_on_failure(2) << step)
186
+ wrapped_step.execute!
187
+ assert_equal 2, call_count
188
+ end
189
+
190
+ specify "will not retry more than the specified number of times" do
191
+ call_count = 0
192
+ step = action("test") do
193
+ call_count += 1
194
+ raise RuntimeError, "FAIL!"
195
+ end
196
+ wrapped_step = (retry_on_failure(2) << step)
197
+ wrapped_step.execute!
198
+ assert_equal 3, call_count
199
+ end
200
+
201
+ specify "will not retry if timeout expires" do
202
+ time = Time.mktime(1970, 1, 1)
203
+ clock = stub("Clock", :now => time)
204
+ call_count = 0
205
+ step = action("test") do
206
+ call_count += 1
207
+ time += 1
208
+ clock.stubs(:now => time)
209
+ raise RuntimeError, "FAIL!"
210
+ end
211
+ wrapped_step = (retry_on_failure(2, 1, :clock => clock) << step)
212
+ wrapped_step.execute!
213
+ assert_equal 1, call_count
214
+ end
215
+ end
216
+
217
+ end
@@ -0,0 +1,79 @@
1
+ require File.expand_path("../test_helper", File.dirname(__FILE__))
2
+ require 'methodical/modifier'
3
+ require 'methodical/action_item'
4
+
5
+ class ModifierTest < Test::Unit::TestCase
6
+ context "#execute!" do
7
+ specify "executes the modifier block" do
8
+ step = stub_everything("ActionItem")
9
+ sensor = :unset
10
+ it = Methodical::Modifier.new("NAME", step) do
11
+ sensor = :set
12
+ end
13
+ it.execute!
14
+ assert_equal :set, sensor
15
+ end
16
+
17
+ specify "passes the action item to the block" do
18
+ step = stub_everything("ActionItem")
19
+ sensor = :unset
20
+ it = Methodical::Modifier.new("NAME", step) do |action_item, baton|
21
+ sensor = action_item
22
+ end
23
+ it.execute!
24
+ assert_same step, sensor
25
+ end
26
+
27
+ specify "passes a baton to the block" do
28
+ baton = stub("Baton")
29
+ step = stub_everything("ActionItem")
30
+ sensor = :unset
31
+ it = Methodical::Modifier.new("NAME", step) do |action_item, baton|
32
+ sensor = baton
33
+ end
34
+ it.execute!(baton)
35
+ assert_not_nil sensor
36
+ assert_same baton, sensor
37
+ end
38
+ end
39
+
40
+ context "#<<" do
41
+ specify "composes modifier and modified" do
42
+ step = stub_everything("ActionItem")
43
+ it = Methodical::Modifier.new("NAME")
44
+ it << step
45
+ assert_same step, it.action_item
46
+ end
47
+
48
+ specify "returns the modifier" do
49
+ step = stub_everything("ActionItem")
50
+ it = Methodical::Modifier.new("NAME")
51
+ assert_same it, (it << step)
52
+ end
53
+
54
+ specify "delegates to action_item, if set" do
55
+ mod2 = stub("Inner Modifier")
56
+ step = stub_everything("ActionItem")
57
+ it = Methodical::Modifier.new("NAME", mod2)
58
+ mod2.expects(:<<).with(step)
59
+ it << step
60
+ end
61
+ end
62
+
63
+ context "#clone" do
64
+ specify "deeply copies action item" do
65
+ step = stub_everything("ActionItem")
66
+ copy = stub_everything("Copy")
67
+ it = Methodical::Modifier.new("NAME", step)
68
+ step.expects(:clone).returns(copy).at_least_once
69
+ assert_same copy, it.clone.action_item
70
+ end
71
+ end
72
+
73
+ specify "delegates unknown methods to action item" do
74
+ step = stub_everything("ActionItem")
75
+ it = Methodical::Modifier.new("NAME", step)
76
+ step.expects(:foo).with("bar")
77
+ it.foo("bar")
78
+ end
79
+ end
@@ -0,0 +1,825 @@
1
+ require File.expand_path("../test_helper", File.dirname(__FILE__))
2
+ require 'methodical/simple_action_item'
3
+
4
+ class SimpleActionItemTest < Test::Unit::TestCase
5
+ include Methodical
6
+
7
+ specify "can be updated all at once" do
8
+ it = SimpleActionItem.new("Test") {}
9
+ it.update!(:skipped, "EXPLANATION", [1,2,3])
10
+ assert_equal :skipped, it.status
11
+ assert_equal "EXPLANATION", it.explanation
12
+ assert_equal [1,2,3], it.result
13
+ end
14
+
15
+ context "#update" do
16
+ specify "returns a disposition" do
17
+ it = SimpleActionItem.new("Test") {}
18
+ assert_equal(
19
+ Disposition.new([:skipped, "EXPLANATION", [1,2,3]]),
20
+ it.update!(:skipped, "EXPLANATION", [1,2,3]))
21
+ end
22
+ end
23
+
24
+ specify "defaults to NOT ignored" do
25
+ it = SimpleActionItem.new("Test") {}
26
+ assert !it.ignored?
27
+ end
28
+
29
+ specify "defaults to being relevant" do
30
+ it = SimpleActionItem.new("Test") {}
31
+ assert it.relevant?
32
+ end
33
+
34
+ specify "defaults to empty details" do
35
+ it = SimpleActionItem.new("Test") {}
36
+ assert_equal "", it.details
37
+ end
38
+
39
+ context "created from a block" do
40
+ specify "executes the block when called" do
41
+ sensor = :unset
42
+ it = SimpleActionItem.new("Test") do
43
+ sensor = :set
44
+ end
45
+ it.execute!
46
+ assert_equal :set, sensor
47
+ end
48
+
49
+ specify "has the given title" do
50
+ it = SimpleActionItem.new("Foo") {}
51
+ assert_equal "Foo", it.title
52
+ end
53
+
54
+ specify "knows it is undone before being called" do
55
+ it = SimpleActionItem.new("Foo") {}
56
+ assert !it.done?
57
+ end
58
+
59
+ specify "knows it is done after being called" do
60
+ it = SimpleActionItem.new("Foo") {}
61
+ it.execute!
62
+ assert it.done?
63
+ end
64
+
65
+ specify "has a status of :succeeded after being called" do
66
+ it = SimpleActionItem.new("Foo") {}
67
+ it.execute!
68
+ assert_equal :succeeded, it.status
69
+ end
70
+
71
+ specify "has a status of :not_started before being called" do
72
+ it = SimpleActionItem.new("Foo") {}
73
+ assert_equal :not_started, it.status
74
+ end
75
+
76
+ specify "knows it has neither succeeded or failed before being called" do
77
+ it = SimpleActionItem.new("Foo") {}
78
+ assert !it.succeeded?
79
+ assert !it.failed?
80
+ assert !it.bad?
81
+ end
82
+
83
+ specify "can format a status message" do
84
+ it = SimpleActionItem.new("Foo") {}
85
+ assert_equal "Foo: Not started.", it.synopsis
86
+ end
87
+
88
+ specify "passes self to block" do
89
+ sensor = :unset
90
+ it = SimpleActionItem.new("Foo") do |baton, step|
91
+ sensor = step
92
+ end
93
+ it.execute!(nil)
94
+ assert_same it, sensor
95
+ end
96
+
97
+ specify "called with a baton object, passes baton to block" do
98
+ sensor = :unset
99
+ it = SimpleActionItem.new("Foo") do |baton, step|
100
+ sensor = baton
101
+ end
102
+ test_baton = stub("Baton")
103
+ it.execute!(test_baton)
104
+ assert_same test_baton, sensor
105
+ end
106
+ end
107
+
108
+ context "created from a callable" do
109
+ specify "executes the callable when called" do
110
+ sensor = :unset
111
+ callable = lambda do |baton, step|
112
+ sensor = :set
113
+ end
114
+ it = SimpleActionItem.new("Test", callable)
115
+ it.execute!
116
+ assert_equal :set, sensor
117
+ end
118
+
119
+ specify "called with a baton object, passes baton to callable" do
120
+ sensor = :unset
121
+ callable = lambda do |baton, step|
122
+ sensor = baton
123
+ end
124
+ it = SimpleActionItem.new("Foo", callable)
125
+ test_baton = stub("Baton")
126
+ it.execute!(test_baton)
127
+ assert_same test_baton, sensor
128
+ end
129
+ end
130
+
131
+ context "with a block that throws a disposition" do
132
+ specify "should save and return the disposition" do
133
+ it = SimpleActionItem.new("Failure") do
134
+ throw(:methodical_disposition,
135
+ Methodical::Disposition(:in_progress, "Procrastinating", 42))
136
+ end
137
+ assert_equal(Methodical::Disposition(:in_progress, "Procrastinating", 42),
138
+ it.execute!)
139
+ assert_equal(Methodical::Disposition(:in_progress, "Procrastinating", 42),
140
+ it.disposition)
141
+ end
142
+ end
143
+
144
+ context "with a block that raises a runtime error" do
145
+ specify "has a status of :failed after being called" do
146
+ it = SimpleActionItem.new("Failure") do raise "Fail" end
147
+ it.execute!
148
+ assert_equal :failed, it.status
149
+ end
150
+
151
+ specify "stores the exception" do
152
+ it = SimpleActionItem.new("Failure") do raise "Fail" end
153
+ it.execute!
154
+ assert_kind_of RuntimeError, it.error
155
+ assert_equal "Fail", it.error.message
156
+ end
157
+
158
+ specify "returns a disposition from call" do
159
+ it = SimpleActionItem.new("Failure") do raise "Fail" end
160
+ assert_kind_of Methodical::Disposition, it.execute!
161
+ assert_equal "Fail", it.execute!.explanation
162
+ end
163
+
164
+ specify "details should be derived from the error backtrace" do
165
+ error = RuntimeError.new("Fail")
166
+ error.set_backtrace(['FRAME1', 'FRAME2'])
167
+ it = SimpleActionItem.new("Failure") do raise error end
168
+ assert_equal "FRAME1\nFRAME2", it.execute!.details
169
+ end
170
+
171
+ end
172
+
173
+ context "with a block that raises a StandardError" do
174
+ specify "has a status of :bad after being called" do
175
+ it = SimpleActionItem.new("Failure") do
176
+ raise StandardError, "Fail"
177
+ end
178
+ it.execute!
179
+ assert_equal :bad, it.status
180
+ end
181
+
182
+ specify "stores the exception" do
183
+ it = SimpleActionItem.new("Failure") do
184
+ raise StandardError, "Fail"
185
+ end
186
+ it.execute!
187
+ assert_kind_of StandardError, it.error
188
+ assert_equal "Fail", it.error.message
189
+ end
190
+
191
+ specify "details should be derived from the error backtrace" do
192
+ error = StandardError.new("Fail")
193
+ error.set_backtrace(['FRAME1', 'FRAME2'])
194
+ it = SimpleActionItem.new("Failure") do raise error end
195
+ assert_equal "FRAME1\nFRAME2", it.execute!.details
196
+ end
197
+ end
198
+
199
+ context "with a block that raises a Exception" do
200
+ specify "has a status of :bad after being called" do
201
+ it = SimpleActionItem.new("Failure") do
202
+ raise Exception, "Alert!"
203
+ end
204
+ begin
205
+ it.execute!
206
+ rescue Exception
207
+ end
208
+ assert_equal :bad, it.status
209
+ end
210
+
211
+ specify "stores the exception" do
212
+ it = SimpleActionItem.new("Failure") do
213
+ raise Exception, "Fail"
214
+ end
215
+ begin
216
+ it.execute!
217
+ rescue Exception
218
+ end
219
+ assert_kind_of Exception, it.error
220
+ assert_equal "Fail", it.error.message
221
+ assert_equal "Fail", it.explanation
222
+ end
223
+
224
+ specify "passes the exception on" do
225
+ it = SimpleActionItem.new("Failure") do
226
+ raise Exception, "Fail"
227
+ end
228
+ assert_raises(Exception) do
229
+ it.execute!
230
+ end
231
+ end
232
+
233
+ specify "details should be derived from the error backtrace" do
234
+ error = Exception.new("Fail")
235
+ error.set_backtrace(['FRAME1', 'FRAME2'])
236
+ it = SimpleActionItem.new("Failure") do raise error end
237
+ begin
238
+ it.execute!
239
+ rescue Exception
240
+ end
241
+ assert_equal "FRAME1\nFRAME2", it.details
242
+ end
243
+
244
+ end
245
+
246
+ context "with a block that returns no details" do
247
+ specify "has no explanation" do
248
+ it = SimpleActionItem.new("Foo") {}
249
+ it.execute!
250
+ assert it.explanation.blank?
251
+ end
252
+
253
+ specify "returns a disposition on call" do
254
+ it = SimpleActionItem.new("Foo") {}
255
+ assert_kind_of Methodical::Disposition, it.execute!
256
+ end
257
+ end
258
+
259
+ context "with a block that returns success details" do
260
+ specify "uses second element for explanation" do
261
+ it = SimpleActionItem.new("Foo") do
262
+ [:succeeded, "EXPLANATION", nil]
263
+ end
264
+ it.execute!
265
+ assert_equal "EXPLANATION", it.explanation
266
+ end
267
+
268
+ specify "uses third element for result" do
269
+ it = SimpleActionItem.new("Foo") do
270
+ [:succeeded, "EXPLANATION", {:frobozz => "magic"}]
271
+ end
272
+ it.execute!
273
+ assert_equal({:frobozz => "magic"}, it.result)
274
+ end
275
+
276
+ specify "returns a disposition on call" do
277
+ it = SimpleActionItem.new("Foo") do
278
+ [:succeeded, "EXPLANATION", {:frobozz => "magic"}]
279
+ end
280
+ assert_kind_of Methodical::Disposition, it.execute!
281
+ end
282
+ end
283
+
284
+ context "with a status of :skipped" do
285
+ specify "can format a status message" do
286
+ it = SimpleActionItem.new("Foo") {}
287
+ it.status = :skipped
288
+ assert_equal "Foo: Skipped.", it.synopsis
289
+ end
290
+ end
291
+
292
+ context "with a status of :abort" do
293
+ specify "can format a status message" do
294
+ it = SimpleActionItem.new("Foo") {}
295
+ it.status = :abort
296
+ assert_equal "Foo: Failed.", it.synopsis
297
+ end
298
+ end
299
+
300
+ context "with the ignored bit set" do
301
+ specify "knows it is ignored" do
302
+ it = SimpleActionItem.new("Foo") {}
303
+ it.ignored = true
304
+ assert it.ignored?
305
+ end
306
+
307
+ specify "does not count towards overall outcome" do
308
+ it = SimpleActionItem.new("Foo") {}
309
+ it.ignored = true
310
+ assert !it.relevant?
311
+ end
312
+
313
+ end
314
+
315
+ context "failed, with the ignored bit set" do
316
+ specify "can format a status message" do
317
+ it = SimpleActionItem.new("Foo") {}
318
+ it.status = :failed
319
+ it.explanation = "Stuff happened"
320
+ it.ignored = true
321
+ assert_equal "Foo: Failed (Stuff happened) (Ignored).", it.synopsis
322
+ end
323
+
324
+ specify "should say continuing is OK" do
325
+ it = SimpleActionItem.new("Foo") {}
326
+ it.status = :failed
327
+ it.explanation = "Stuff happened"
328
+ it.ignored = true
329
+ assert it.continue?
330
+ end
331
+
332
+ specify "is not decisive" do
333
+ it = SimpleActionItem.new("Foo") {}
334
+ it.status = :failed
335
+ it.ignored = true
336
+ assert !it.decisive?
337
+ end
338
+ end
339
+
340
+ context "aborted, with the ignored bit set" do
341
+ specify "can format a status message" do
342
+ it = SimpleActionItem.new("Foo") {}
343
+ it.status = :abort
344
+ it.explanation = "Stuff happened"
345
+ it.ignored = true
346
+ assert_equal "Foo: Failed (Stuff happened) (Ignored).", it.synopsis
347
+ end
348
+
349
+ specify "should NOT say continuing is OK" do
350
+ it = SimpleActionItem.new("Foo") {}
351
+ it.status = :abort
352
+ it.explanation = "Stuff happened"
353
+ it.ignored = true
354
+ assert !it.continue?
355
+ end
356
+
357
+ specify "is not decisive" do
358
+ it = SimpleActionItem.new("Foo") {}
359
+ it.status = :aborted
360
+ it.ignored = true
361
+ assert !it.decisive?
362
+ end
363
+ end
364
+
365
+ context "succeeded, with the ignored bit set" do
366
+ specify "can format a status message" do
367
+ it = SimpleActionItem.new("Foo") {}
368
+ it.status = :succeeded
369
+ it.explanation = "Stuff happened"
370
+ it.ignored = true
371
+ assert_equal "Foo: OK (Stuff happened).", it.synopsis
372
+ end
373
+
374
+ specify "should say continuing is OK" do
375
+ it = SimpleActionItem.new("Foo") {}
376
+ it.status = :succeeded
377
+ it.explanation = "Stuff happened"
378
+ it.ignored = true
379
+ assert it.continue?
380
+ end
381
+ end
382
+
383
+ context "with a status of :sufficient" do
384
+ specify "can format a status message" do
385
+ it = SimpleActionItem.new("Foo") {}
386
+ it.status = :sufficient
387
+ assert_equal "Foo: OK.", it.synopsis
388
+ end
389
+ end
390
+
391
+ context "with a status of :finish" do
392
+ specify "can format a status message" do
393
+ it = SimpleActionItem.new("Foo") {}
394
+ it.status = :finish
395
+ assert_equal "Foo: OK.", it.synopsis
396
+ end
397
+
398
+ specify "should NOT approve continuation" do
399
+ it = SimpleActionItem.new("Foo") {}
400
+ it.status = :finish
401
+ assert !it.continue?
402
+ end
403
+ end
404
+
405
+ context "with a block that returns a single value" do
406
+ specify "has no explanation" do
407
+ it = SimpleActionItem.new("Foo") do
408
+ "RESULT"
409
+ end
410
+ it.execute!
411
+ assert it.explanation.blank?
412
+ end
413
+
414
+ specify "uses value for result" do
415
+ it = SimpleActionItem.new("Foo") do
416
+ "RESULT"
417
+ end
418
+ it.execute!
419
+ assert_equal("RESULT", it.result)
420
+ end
421
+ end
422
+
423
+ context "which has failed" do
424
+ specify "knows it has failed" do
425
+ it = SimpleActionItem.new("Failure") do raise "Fail" end
426
+ it.execute!
427
+ assert it.failed?
428
+ end
429
+
430
+ specify "knows it has not succeeded" do
431
+ it = SimpleActionItem.new("Failure") do raise "Fail" end
432
+ it.execute!
433
+ assert !it.succeeded?
434
+ end
435
+
436
+ specify "is decisive" do
437
+ it = SimpleActionItem.new("Failure") do raise "Fail" end
438
+ it.execute!
439
+ assert it.decisive?
440
+ end
441
+
442
+ specify "knows it is not bad" do
443
+ it = SimpleActionItem.new("Fail") do raise "Fail" end
444
+ it.execute!
445
+ assert !it.bad?
446
+ end
447
+
448
+ specify "gets explanation from error" do
449
+ it = SimpleActionItem.new("Fail") do raise "Fail" end
450
+ it.execute!
451
+ assert_equal "Fail", it.explanation
452
+ end
453
+
454
+ specify "can format a status message" do
455
+ it = SimpleActionItem.new("Foo") do raise "MESSAGE" end
456
+ it.execute!
457
+ assert_equal "Foo: Failed (MESSAGE).", it.synopsis
458
+ end
459
+ end
460
+
461
+ context "which has raised a standard error" do
462
+ specify "knows it has failed" do
463
+ it = SimpleActionItem.new("Failure") do
464
+ raise StandardError, "Fail"
465
+ end
466
+ it.execute!
467
+ assert it.failed?
468
+ end
469
+
470
+ specify "knows it has not succeeded" do
471
+ it = SimpleActionItem.new("Failure") do
472
+ raise StandardError, "Fail"
473
+ end
474
+ it.execute!
475
+ assert !it.succeeded?
476
+ end
477
+
478
+ specify "knows it is bad" do
479
+ it = SimpleActionItem.new("Fail") do
480
+ raise StandardError, "Fail"
481
+ end
482
+ it.execute!
483
+ assert it.bad?
484
+ end
485
+
486
+ specify "gets explanation from error" do
487
+ it = SimpleActionItem.new("Fail") do raise StandardError, "Fail" end
488
+ it.execute!
489
+ assert_equal "Fail", it.explanation
490
+ end
491
+
492
+ specify "can format a status message" do
493
+ it = SimpleActionItem.new("Foo") do
494
+ raise StandardError, "SOME_ERROR"
495
+ end
496
+ it.execute!
497
+ assert_equal "Foo: Error (SOME_ERROR).", it.synopsis
498
+ end
499
+ end
500
+
501
+ context "which has succeeded" do
502
+ specify "knows it has not failed" do
503
+ it = SimpleActionItem.new("Success") do end
504
+ it.execute!
505
+ assert !it.failed?
506
+ end
507
+
508
+ specify "knows it has succeeded" do
509
+ it = SimpleActionItem.new("Success") do end
510
+ it.execute!
511
+ assert it.succeeded?
512
+ end
513
+
514
+ specify "knows it is not bad" do
515
+ it = SimpleActionItem.new("Success") do end
516
+ it.execute!
517
+ assert !it.bad?
518
+ end
519
+
520
+ specify "can format a status message" do
521
+ it = SimpleActionItem.new("Foo") {}
522
+ it.execute!
523
+ assert_equal "Foo: OK.", it.synopsis
524
+ end
525
+
526
+ end
527
+
528
+ context "#succeed!" do
529
+ specify "throws :methodical_disposition" do
530
+ it = SimpleActionItem.new("TEST") {}
531
+ assert_throws(:methodical_disposition) do
532
+ it.succeed!
533
+ end
534
+ end
535
+
536
+ specify "throws a disposition object" do
537
+ it = SimpleActionItem.new("TEST") {}
538
+ assert_kind_of(Methodical::Disposition,
539
+ catch(:methodical_disposition) { it.succeed! })
540
+ end
541
+
542
+ specify "throws a successful disposition" do
543
+ it = SimpleActionItem.new("TEST") {}
544
+ assert_equal(:succeeded,
545
+ catch(:methodical_disposition) { it.succeed! }.status)
546
+ end
547
+
548
+ specify "throws the given explanation" do
549
+ it = SimpleActionItem.new("TEST") {}
550
+ assert_equal("EXPL",
551
+ catch(:methodical_disposition) { it.succeed!("EXPL") }.explanation)
552
+ end
553
+
554
+ specify "throws the given result" do
555
+ it = SimpleActionItem.new("TEST") {}
556
+ assert_equal(42,
557
+ catch(:methodical_disposition) { it.succeed!("EXPL", 42) }.result)
558
+ end
559
+
560
+ specify "throws the given details" do
561
+ it = SimpleActionItem.new("TEST") {}
562
+ assert_equal("DETAILS",
563
+ catch(:methodical_disposition) {
564
+ it.succeed!("EXPL", 42, "DETAILS")
565
+ }.details)
566
+ end
567
+ end
568
+
569
+ context "#failed!" do
570
+ specify "throws :methodical_disposition" do
571
+ it = SimpleActionItem.new("TEST") {}
572
+ assert_throws(:methodical_disposition) do
573
+ it.fail!
574
+ end
575
+ end
576
+
577
+ specify "throws a disposition object" do
578
+ it = SimpleActionItem.new("TEST") {}
579
+ assert_kind_of(Methodical::Disposition,
580
+ catch(:methodical_disposition) { it.fail! })
581
+ end
582
+
583
+ specify "throws a failed disposition" do
584
+ it = SimpleActionItem.new("TEST") {}
585
+ assert_equal(:failed,
586
+ catch(:methodical_disposition) { it.fail! }.status)
587
+ end
588
+
589
+ specify "throws the given explanation" do
590
+ it = SimpleActionItem.new("TEST") {}
591
+ assert_equal("EXPL",
592
+ catch(:methodical_disposition) { it.fail!("EXPL") }.explanation)
593
+ end
594
+
595
+ specify "throws the given result" do
596
+ it = SimpleActionItem.new("TEST") {}
597
+ assert_equal(42,
598
+ catch(:methodical_disposition) { it.fail!("EXPL", 42) }.result)
599
+ end
600
+
601
+ specify "throws the given error" do
602
+ it = SimpleActionItem.new("TEST") {}
603
+ assert_equal("FOO",
604
+ catch(:methodical_disposition) {
605
+ it.fail!("EXPL", 42, RuntimeError.new("FOO"))
606
+ }.error.message)
607
+ end
608
+
609
+ specify "throws the given details" do
610
+ it = SimpleActionItem.new("TEST") {}
611
+ assert_equal("DETAILS",
612
+ catch(:methodical_disposition) {
613
+ it.fail!("EXPL", 42, nil, "DETAILS")
614
+ }.details)
615
+ end
616
+ end
617
+
618
+ context "#skip!" do
619
+ specify "throws :methodical_disposition" do
620
+ it = SimpleActionItem.new("TEST") {}
621
+ assert_throws(:methodical_disposition) do
622
+ it.skip!
623
+ end
624
+ end
625
+
626
+ specify "throws a disposition object" do
627
+ it = SimpleActionItem.new("TEST") {}
628
+ assert_kind_of(Methodical::Disposition,
629
+ catch(:methodical_disposition) { it.skip! })
630
+ end
631
+
632
+ specify "throws a skipped disposition" do
633
+ it = SimpleActionItem.new("TEST") {}
634
+ assert_equal(:skipped,
635
+ catch(:methodical_disposition) { it.skip! }.status)
636
+ end
637
+
638
+ specify "throws the given explanation" do
639
+ it = SimpleActionItem.new("TEST") {}
640
+ assert_equal("EXPL",
641
+ catch(:methodical_disposition) { it.skip!("EXPL") }.explanation)
642
+ end
643
+
644
+ specify "throws the given details" do
645
+ it = SimpleActionItem.new("TEST") {}
646
+ assert_equal("DETAILS",
647
+ catch(:methodical_disposition) {
648
+ it.skip!("EXPL", "DETAILS")
649
+ }.details)
650
+ end
651
+ end
652
+
653
+ context "#checkpoint!" do
654
+ specify "throws :methodical_disposition" do
655
+ it = SimpleActionItem.new("TEST") {}
656
+ assert_throws(:methodical_disposition) do
657
+ it.checkpoint!
658
+ end
659
+ end
660
+
661
+ specify "throws a disposition object" do
662
+ it = SimpleActionItem.new("TEST") {}
663
+ assert_kind_of(Methodical::Disposition,
664
+ catch(:methodical_disposition) { it.checkpoint! })
665
+ end
666
+
667
+ specify "throws an in_progress disposition" do
668
+ it = SimpleActionItem.new("TEST") {}
669
+ assert_equal(:in_progress,
670
+ catch(:methodical_disposition) { it.checkpoint! }.status)
671
+ end
672
+
673
+ specify "throws the given explanation" do
674
+ it = SimpleActionItem.new("TEST") {}
675
+ assert_equal("EXPL",
676
+ catch(:methodical_disposition) { it.checkpoint!("EXPL") }.explanation)
677
+ end
678
+
679
+ specify "throws the given memento" do
680
+ it = SimpleActionItem.new("TEST") {}
681
+ assert_equal(42,
682
+ catch(:methodical_disposition) { it.checkpoint!("EXPL", 42) }.memento)
683
+ end
684
+
685
+ specify "throws the given details" do
686
+ it = SimpleActionItem.new("TEST") {}
687
+ assert_equal("DETAILS",
688
+ catch(:methodical_disposition) {
689
+ it.checkpoint!("EXPL", 42, "DETAILS")
690
+ }.details)
691
+ end
692
+ end
693
+
694
+
695
+ context "#sufficient!" do
696
+ specify "throws :methodical_disposition" do
697
+ it = SimpleActionItem.new("TEST") {}
698
+ assert_throws(:methodical_disposition) do
699
+ it.sufficient!
700
+ end
701
+ end
702
+
703
+ specify "throws a disposition object" do
704
+ it = SimpleActionItem.new("TEST") {}
705
+ assert_kind_of(Methodical::Disposition,
706
+ catch(:methodical_disposition) { it.sufficient! })
707
+ end
708
+
709
+ specify "throws a sufficient disposition" do
710
+ it = SimpleActionItem.new("TEST") {}
711
+ assert_equal(:sufficient,
712
+ catch(:methodical_disposition) { it.sufficient! }.status)
713
+ end
714
+
715
+ specify "throws the given explanation" do
716
+ it = SimpleActionItem.new("TEST") {}
717
+ assert_equal("EXPL",
718
+ catch(:methodical_disposition) { it.sufficient!("EXPL") }.explanation)
719
+ end
720
+
721
+ specify "throws the given result" do
722
+ it = SimpleActionItem.new("TEST") {}
723
+ assert_equal(42,
724
+ catch(:methodical_disposition) { it.sufficient!("EXPL", 42) }.result)
725
+ end
726
+
727
+ specify "throws the given details" do
728
+ it = SimpleActionItem.new("TEST") {}
729
+ assert_equal("DETAILS",
730
+ catch(:methodical_disposition) {
731
+ it.sufficient!("EXPL", 42, "DETAILS")
732
+ }.details)
733
+ end
734
+ end
735
+
736
+ context "#finish!" do
737
+ specify "throws :methodical_disposition" do
738
+ it = SimpleActionItem.new("TEST") {}
739
+ assert_throws(:methodical_disposition) do
740
+ it.finish!
741
+ end
742
+ end
743
+
744
+ specify "throws a disposition object" do
745
+ it = SimpleActionItem.new("TEST") {}
746
+ assert_kind_of(Methodical::Disposition,
747
+ catch(:methodical_disposition) { it.finish! })
748
+ end
749
+
750
+ specify "throws a finish disposition" do
751
+ it = SimpleActionItem.new("TEST") {}
752
+ assert_equal(:finish,
753
+ catch(:methodical_disposition) { it.finish! }.status)
754
+ end
755
+
756
+ specify "throws the given explanation" do
757
+ it = SimpleActionItem.new("TEST") {}
758
+ assert_equal("EXPL",
759
+ catch(:methodical_disposition) { it.finish!("EXPL") }.explanation)
760
+ end
761
+
762
+ specify "throws the given result" do
763
+ it = SimpleActionItem.new("TEST") {}
764
+ assert_equal(42,
765
+ catch(:methodical_disposition) { it.finish!("EXPL", 42) }.result)
766
+ end
767
+
768
+ specify "throws the given details" do
769
+ it = SimpleActionItem.new("TEST") {}
770
+ assert_equal("DETAILS",
771
+ catch(:methodical_disposition) {
772
+ it.finish!("EXPL", 42, "DETAILS")
773
+ }.details)
774
+ end
775
+ end
776
+
777
+ context "#abort!" do
778
+ specify "throws :methodical_disposition" do
779
+ it = SimpleActionItem.new("TEST") {}
780
+ assert_throws(:methodical_disposition) do
781
+ it.abort!
782
+ end
783
+ end
784
+
785
+ specify "throws a disposition object" do
786
+ it = SimpleActionItem.new("TEST") {}
787
+ assert_kind_of(Methodical::Disposition,
788
+ catch(:methodical_disposition) { it.abort! })
789
+ end
790
+
791
+ specify "throws an abort disposition" do
792
+ it = SimpleActionItem.new("TEST") {}
793
+ assert_equal(:abort,
794
+ catch(:methodical_disposition) { it.abort! }.status)
795
+ end
796
+
797
+ specify "throws the given explanation" do
798
+ it = SimpleActionItem.new("TEST") {}
799
+ assert_equal("EXPL",
800
+ catch(:methodical_disposition) { it.abort!("EXPL") }.explanation)
801
+ end
802
+
803
+ specify "throws the given result" do
804
+ it = SimpleActionItem.new("TEST") {}
805
+ assert_equal(42,
806
+ catch(:methodical_disposition) { it.abort!("EXPL", 42) }.result)
807
+ end
808
+
809
+ specify "throws the given error" do
810
+ it = SimpleActionItem.new("TEST") {}
811
+ assert_equal("FOO",
812
+ catch(:methodical_disposition) {
813
+ it.abort!("EXPL", 42, RuntimeError.new("FOO"))
814
+ }.error.message)
815
+ end
816
+
817
+ specify "throws the given details" do
818
+ it = SimpleActionItem.new("TEST") {}
819
+ assert_equal("DETAILS",
820
+ catch(:methodical_disposition) {
821
+ it.abort!("EXPL", 42, nil, "DETAILS")
822
+ }.details)
823
+ end
824
+ end
825
+ end