minilab 1.0.0-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/.document +2 -0
  2. data/CHANGES +2 -0
  3. data/LICENSE +19 -0
  4. data/README +107 -0
  5. data/Rakefile +145 -0
  6. data/config/environment.rb +15 -0
  7. data/config/objects.yml +22 -0
  8. data/lib/analog_io.rb +30 -0
  9. data/lib/digital_auxport_io.rb +49 -0
  10. data/lib/digital_configuration.rb +66 -0
  11. data/lib/digital_port_io.rb +68 -0
  12. data/lib/extension/extconf.rb +4 -0
  13. data/lib/extension/minilab_hardware.c +235 -0
  14. data/lib/extension/minilab_hardware.so +0 -0
  15. data/lib/library_translator.rb +48 -0
  16. data/lib/minilab.rb +149 -0
  17. data/lib/minilab_context.rb +39 -0
  18. data/lib/result_verifier.rb +14 -0
  19. data/test/integration/analog_input_output_test.rb +43 -0
  20. data/test/integration/connect_to_hardware_test.rb +13 -0
  21. data/test/integration/digital_input_output_test.rb +114 -0
  22. data/test/integration/integration_test.rb +53 -0
  23. data/test/integration/require_minilab_test.rb +9 -0
  24. data/test/system/analog_input.test +3 -0
  25. data/test/system/analog_output.test +37 -0
  26. data/test/system/digital_port_input.test +5 -0
  27. data/test/system/digital_port_output.test +39 -0
  28. data/test/system/digital_port_read_byte.test +26 -0
  29. data/test/system/digital_screw_terminals_input.test +2 -0
  30. data/test/system/digital_screw_terminals_output.test +11 -0
  31. data/test/system/minilab_driver.rb +85 -0
  32. data/test/test_helper.rb +11 -0
  33. data/test/unit/analog_io_test.rb +87 -0
  34. data/test/unit/digital_auxport_io_test.rb +114 -0
  35. data/test/unit/digital_configuration_test.rb +136 -0
  36. data/test/unit/digital_port_io_test.rb +117 -0
  37. data/test/unit/library_translator_test.rb +100 -0
  38. data/test/unit/minilab_context_test.rb +82 -0
  39. data/test/unit/minilab_hardware_test.rb +83 -0
  40. data/test/unit/minilab_test.rb +131 -0
  41. data/test/unit/result_verifier_test.rb +33 -0
  42. data/vendor/behaviors/lib/behaviors.rb +50 -0
  43. data/vendor/behaviors/tasks/behaviors_tasks.rake +140 -0
  44. data/vendor/behaviors/test/behaviors_tasks_test.rb +71 -0
  45. data/vendor/behaviors/test/behaviors_test.rb +50 -0
  46. data/vendor/behaviors/test/tasks_test/Rakefile +16 -0
  47. data/vendor/behaviors/test/tasks_test/doc/behaviors.html +55 -0
  48. data/vendor/behaviors/test/tasks_test/lib/user.rb +2 -0
  49. data/vendor/behaviors/test/tasks_test/test/user_test.rb +17 -0
  50. data/vendor/constructor/Rakefile +44 -0
  51. data/vendor/constructor/config/environment.rb +12 -0
  52. data/vendor/constructor/lib/constructor.rb +132 -0
  53. data/vendor/constructor/test/constructor_test.rb +366 -0
  54. data/vendor/constructor/test/helper.rb +3 -0
  55. data/vendor/diy/README +26 -0
  56. data/vendor/diy/Rakefile +18 -0
  57. data/vendor/diy/lib/constructor.rb +114 -0
  58. data/vendor/diy/lib/diy.rb +329 -0
  59. data/vendor/diy/proto/context.rb +117 -0
  60. data/vendor/diy/proto/context.yml +20 -0
  61. data/vendor/diy/test/diy_test.rb +370 -0
  62. data/vendor/diy/test/files/broken_construction.yml +7 -0
  63. data/vendor/diy/test/files/cat/cat.rb +4 -0
  64. data/vendor/diy/test/files/cat/extra_conflict.yml +5 -0
  65. data/vendor/diy/test/files/cat/heritage.rb +2 -0
  66. data/vendor/diy/test/files/cat/needs_input.yml +3 -0
  67. data/vendor/diy/test/files/cat/the_cat_lineage.rb +1 -0
  68. data/vendor/diy/test/files/dog/dog_model.rb +4 -0
  69. data/vendor/diy/test/files/dog/dog_presenter.rb +4 -0
  70. data/vendor/diy/test/files/dog/dog_view.rb +2 -0
  71. data/vendor/diy/test/files/dog/file_resolver.rb +2 -0
  72. data/vendor/diy/test/files/dog/other_thing.rb +2 -0
  73. data/vendor/diy/test/files/dog/simple.yml +11 -0
  74. data/vendor/diy/test/files/donkey/foo.rb +8 -0
  75. data/vendor/diy/test/files/donkey/foo/bar/qux.rb +7 -0
  76. data/vendor/diy/test/files/fud/objects.yml +13 -0
  77. data/vendor/diy/test/files/fud/toy.rb +15 -0
  78. data/vendor/diy/test/files/gnu/objects.yml +14 -0
  79. data/vendor/diy/test/files/gnu/thinger.rb +8 -0
  80. data/vendor/diy/test/files/goat/base.rb +8 -0
  81. data/vendor/diy/test/files/goat/can.rb +6 -0
  82. data/vendor/diy/test/files/goat/goat.rb +6 -0
  83. data/vendor/diy/test/files/goat/objects.yml +12 -0
  84. data/vendor/diy/test/files/goat/paper.rb +6 -0
  85. data/vendor/diy/test/files/goat/plane.rb +8 -0
  86. data/vendor/diy/test/files/goat/shirt.rb +6 -0
  87. data/vendor/diy/test/files/goat/wings.rb +8 -0
  88. data/vendor/diy/test/files/horse/holder_thing.rb +4 -0
  89. data/vendor/diy/test/files/horse/objects.yml +7 -0
  90. data/vendor/diy/test/files/yak/core_model.rb +4 -0
  91. data/vendor/diy/test/files/yak/core_presenter.rb +4 -0
  92. data/vendor/diy/test/files/yak/core_view.rb +1 -0
  93. data/vendor/diy/test/files/yak/data_source.rb +1 -0
  94. data/vendor/diy/test/files/yak/fringe_model.rb +4 -0
  95. data/vendor/diy/test/files/yak/fringe_presenter.rb +4 -0
  96. data/vendor/diy/test/files/yak/fringe_view.rb +1 -0
  97. data/vendor/diy/test/files/yak/my_objects.yml +21 -0
  98. data/vendor/diy/test/test_helper.rb +40 -0
  99. data/vendor/hardmock/CHANGES +8 -0
  100. data/vendor/hardmock/LICENSE +7 -0
  101. data/vendor/hardmock/README +48 -0
  102. data/vendor/hardmock/Rakefile +100 -0
  103. data/vendor/hardmock/TODO +7 -0
  104. data/vendor/hardmock/config/environment.rb +12 -0
  105. data/vendor/hardmock/homepage/demo.rb +21 -0
  106. data/vendor/hardmock/homepage/hardmock_sample.png +0 -0
  107. data/vendor/hardmock/homepage/index.html +65 -0
  108. data/vendor/hardmock/init.rb +3 -0
  109. data/vendor/hardmock/lib/hardmock.rb +634 -0
  110. data/vendor/hardmock/lib/method_cleanout.rb +14 -0
  111. data/vendor/hardmock/rcov.rake +18 -0
  112. data/vendor/hardmock/test/functional/assert_error_test.rb +52 -0
  113. data/vendor/hardmock/test/functional/auto_verify_test.rb +192 -0
  114. data/vendor/hardmock/test/functional/direct_mock_usage_test.rb +396 -0
  115. data/vendor/hardmock/test/functional/hardmock_test.rb +380 -0
  116. data/vendor/hardmock/test/test_helper.rb +23 -0
  117. data/vendor/hardmock/test/unit/expectation_builder_test.rb +18 -0
  118. data/vendor/hardmock/test/unit/expector_test.rb +56 -0
  119. data/vendor/hardmock/test/unit/method_cleanout_test.rb +35 -0
  120. data/vendor/hardmock/test/unit/mock_control_test.rb +172 -0
  121. data/vendor/hardmock/test/unit/mock_test.rb +273 -0
  122. data/vendor/hardmock/test/unit/simple_expectation_test.rb +345 -0
  123. data/vendor/hardmock/test/unit/trapper_test.rb +60 -0
  124. data/vendor/hardmock/test/unit/verify_error_test.rb +34 -0
  125. data/vendor/systir/systir.rb +403 -0
  126. data/vendor/systir/test/unit/ui/xml/testrunner.rb +192 -0
  127. data/vendor/systir/test/unit/ui/xml/xmltestrunner.xslt +109 -0
  128. metadata +235 -0
@@ -0,0 +1,345 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+ require 'hardmock'
3
+
4
+ class SimpleExpectationTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @mock = TheMock.new
8
+ end
9
+ #
10
+ # HELPERS
11
+ #
12
+
13
+ class TheMock
14
+ def _name; 'the_mock'; end
15
+ end
16
+ class OtherMock
17
+ def _name; 'other_mock'; end
18
+ end
19
+
20
+ #
21
+ # TESTS
22
+ #
23
+
24
+ def test_to_s
25
+ ex = SimpleExpectation.new( :mock => @mock, :method => 'a_func', :arguments => [1, "two", :three, { :four => 4 }] )
26
+ assert_equal %|the_mock.a_func(1, "two", :three, {:four=>4})|, ex.to_s
27
+ end
28
+
29
+ def test_apply_method_call
30
+ se = SimpleExpectation.new(:mock => @mock, :method => 'some_func',
31
+ :arguments => [1,'two',:three] )
32
+
33
+ # Try it good:
34
+ assert_nothing_raised ExpectationError do
35
+ se.apply_method_call( @mock, 'some_func', [1,'two',:three], nil )
36
+ end
37
+
38
+ # Bad func name:
39
+ err = assert_raise ExpectationError do
40
+ se.apply_method_call( @mock, 'wrong_func', [1,'two',:three], nil )
41
+ end
42
+ assert_match(/wrong method/i, err.message)
43
+ assert_match(/wrong_func/i, err.message)
44
+ assert_match(/[1, "two", :three]/i, err.message)
45
+ assert_match(/some_func/i, err.message)
46
+ assert_match(/the_mock/i, err.message)
47
+
48
+ # Wrong mock
49
+ err = assert_raise ExpectationError do
50
+ se.apply_method_call( OtherMock.new, 'some_func', [1,'two',:three], nil )
51
+ end
52
+ assert_match(/[1, "two", :three]/i, err.message)
53
+ assert_match(/some_func/i, err.message)
54
+ assert_match(/the_mock/i, err.message)
55
+ assert_match(/other_mock/i, err.message)
56
+
57
+ # Wrong args
58
+ err = assert_raise ExpectationError do
59
+ se.apply_method_call( @mock, 'some_func', [1,'two',:four], nil)
60
+ end
61
+ assert_match(/[1, "two", :three]/i, err.message)
62
+ assert_match(/[1, "two", :four]/i, err.message)
63
+ assert_match(/wrong arguments/i, err.message)
64
+ assert_match(/some_func/i, err.message)
65
+ end
66
+
67
+ def test_apply_method_call_should_call_proc_when_given
68
+ # now with a proc
69
+ thinger = nil
70
+ the_proc = Proc.new { thinger = :shaq }
71
+ se = SimpleExpectation.new(:mock => @mock, :method => 'some_func',
72
+ :block => the_proc)
73
+
74
+ # Try it good:
75
+ assert_nil thinger
76
+ assert_nothing_raised ExpectationError do
77
+ se.apply_method_call(@mock, 'some_func', [], nil)
78
+ end
79
+ assert_equal :shaq, thinger, 'wheres shaq??'
80
+ end
81
+
82
+ def test_apply_method_call_passes_runtime_block_as_last_argument_to_expectation_block
83
+
84
+ passed_block = nil
85
+ exp_block_called = false
86
+ exp_block = Proc.new { |blk|
87
+ exp_block_called = true
88
+ passed_block = blk
89
+ }
90
+
91
+ se = SimpleExpectation.new(:mock => @mock, :method => 'some_func', :block => exp_block,
92
+ :arguments => [])
93
+
94
+ set_flag = false
95
+ runtime_block = Proc.new { set_flag = true }
96
+
97
+ assert_nil passed_block, "Passed block should be nil"
98
+ assert !set_flag, "set_flag should be off"
99
+
100
+ # Go
101
+ se.apply_method_call( @mock, 'some_func', [], runtime_block)
102
+
103
+ # Examine the passed block
104
+ assert exp_block_called, "Expectation block not called"
105
+ assert_not_nil passed_block, "Should have been passed a block"
106
+ assert !set_flag, "set_flag should still be off"
107
+ passed_block.call
108
+ assert set_flag, "set_flag should be on"
109
+ end
110
+
111
+ def test_apply_method_call_fails_when_theres_no_expectation_block_to_handle_the_runtime_block
112
+ se = SimpleExpectation.new(:mock => @mock, :method => 'some_func', :arguments => [])
113
+ runtime_block = Proc.new { set_flag = true }
114
+ err = assert_raise ExpectationError do
115
+ se.apply_method_call( @mock, 'some_func', [], runtime_block)
116
+ end
117
+ assert_match(/unexpected block/i, err.message)
118
+ assert_match(/the_mock.some_func()/i, err.message)
119
+ end
120
+
121
+ def test_returns
122
+ se = SimpleExpectation.new(:mock => @mock, :method => 'some_func',
123
+ :arguments => [1,'two',:three])
124
+
125
+ se.returns "A value"
126
+
127
+ assert_equal "A value", se.apply_method_call(@mock, 'some_func', [1,'two',:three], nil)
128
+ end
129
+
130
+ def test_apply_method_call_captures_block_value
131
+ the_proc = lambda { "in the block" }
132
+ se = SimpleExpectation.new(:mock => @mock, :method => 'do_it', :arguments => [], :block => the_proc)
133
+
134
+ assert_nil se.block_value, "Block value starts out nil"
135
+
136
+ se.apply_method_call(@mock, 'do_it', [], nil)
137
+
138
+ assert_equal "in the block", se.block_value, "Block value not captured"
139
+ end
140
+
141
+ def test_trigger
142
+ # convenience method for block_value.call
143
+ target = false
144
+ inner_proc = lambda { target = true }
145
+ the_proc = lambda { inner_proc }
146
+ se = SimpleExpectation.new(:mock => @mock, :method => 'do_it', :arguments => [], :block => the_proc)
147
+
148
+ assert_nil se.block_value, "Block value starts out nil"
149
+ se.apply_method_call(@mock, 'do_it', [], nil)
150
+ assert_not_nil se.block_value, "Block value not set"
151
+
152
+ assert !target, "Target should still be false"
153
+ se.trigger
154
+ assert target, "Target not true!"
155
+ end
156
+
157
+ def test_trigger_with_arguments
158
+ # convenience method for block_value.call
159
+ target = nil
160
+ inner_proc = lambda { |one,two| target = [one,two] }
161
+ the_proc = lambda { inner_proc }
162
+ se = SimpleExpectation.new(:mock => @mock, :method => 'do_it', :arguments => [], :block => the_proc)
163
+
164
+ assert_nil se.block_value, "Block value starts out nil"
165
+ se.apply_method_call(@mock, 'do_it', [], nil)
166
+ assert_not_nil se.block_value, "Block value not set"
167
+
168
+ assert_nil target, "target should still be nil"
169
+ se.trigger 'cat','dog'
170
+ assert_equal ['cat','dog'], target
171
+ end
172
+
173
+ def test_trigger_nil_block_value
174
+ se = SimpleExpectation.new(:mock => @mock, :method => 'do_it', :arguments => [])
175
+
176
+ assert_nil se.block_value, "Block value starts out nil"
177
+ se.apply_method_call(@mock, 'do_it', [], nil)
178
+ assert_nil se.block_value, "Block value should still be nil"
179
+
180
+ err = assert_raise ExpectationError do
181
+ se.trigger
182
+ end
183
+ assert_match(/do_it/i, err.message)
184
+ assert_match(/block value/i, err.message)
185
+ end
186
+
187
+ def test_trigger_non_proc_block_value
188
+ the_block = lambda { "woops" }
189
+ se = SimpleExpectation.new(:mock => @mock, :method => 'do_it', :arguments => [], :block => the_block)
190
+
191
+ se.apply_method_call(@mock, 'do_it', [], nil)
192
+ assert_equal "woops", se.block_value
193
+
194
+ err = assert_raise ExpectationError do
195
+ se.trigger
196
+ end
197
+ assert_match(/do_it/i, err.message)
198
+ assert_match(/trigger/i, err.message)
199
+ assert_match(/woops/i, err.message)
200
+ end
201
+
202
+
203
+
204
+ def test_proc_used_for_return
205
+ the_proc = lambda { "in the block" }
206
+ se = SimpleExpectation.new(:mock => @mock, :method => 'do_it', :arguments => [], :block => the_proc)
207
+
208
+ assert_equal "in the block", se.apply_method_call(@mock, 'do_it', [], nil)
209
+ assert_equal "in the block", se.block_value, "Captured block value affected wrongly"
210
+ end
211
+
212
+ def test_explicit_return_overrides_proc_return
213
+ the_proc = lambda { "in the block" }
214
+ se = SimpleExpectation.new(:mock => @mock, :method => 'do_it', :arguments => [], :block => the_proc)
215
+ se.returns "the override"
216
+ assert_equal "the override", se.apply_method_call(@mock, 'do_it', [], nil)
217
+ assert_equal "in the block", se.block_value, "Captured block value affected wrongly"
218
+ end
219
+
220
+ def test_yields
221
+ se = SimpleExpectation.new(:mock => @mock, :method => 'each_bean', :arguments => [:side_slot] )
222
+ se.yields :bean1, :bean2
223
+
224
+ things = []
225
+ a_block = lambda { |thinger| things << thinger }
226
+
227
+ se.apply_method_call(@mock,'each_bean',[:side_slot],a_block)
228
+ assert_equal [:bean1,:bean2], things, "Wrong things"
229
+ end
230
+
231
+ def test_yields_block_takes_no_arguments
232
+ se = SimpleExpectation.new(:mock => @mock, :method => 'each_bean', :arguments => [:side_slot] )
233
+ se.yields
234
+
235
+ things = []
236
+ a_block = lambda { things << 'OOF' }
237
+ se.apply_method_call(@mock,'each_bean',[:side_slot],a_block)
238
+ assert_equal ['OOF'], things
239
+ end
240
+
241
+ def test_yields_params_to_block_takes_no_arguments
242
+ se = SimpleExpectation.new(:mock => @mock, :method => 'each_bean', :arguments => [:side_slot] )
243
+ se.yields :wont_fit
244
+
245
+ things = []
246
+ a_block = lambda { things << 'WUP' }
247
+
248
+ err = assert_raise ExpectationError do
249
+ se.apply_method_call(@mock,'each_bean',[:side_slot],a_block)
250
+ end
251
+ assert_match(/wont_fit/i, err.message)
252
+ assert_match(/arity -1/i, err.message)
253
+ assert_equal [], things, "Wrong things"
254
+ end
255
+
256
+ def test_yields_with_returns
257
+ se = SimpleExpectation.new(:mock => @mock, :method => 'each_bean', :arguments => [:side_slot] ,
258
+ :returns => 'the results')
259
+
260
+ exp = se.yields :bean1, :bean2
261
+ assert_same se, exp, "'yields' needs to return a reference to the expectation"
262
+ things = []
263
+ a_block = lambda { |thinger| things << thinger }
264
+ returned = se.apply_method_call(@mock,'each_bean',[:side_slot],a_block)
265
+ assert_equal [:bean1,:bean2], things, "Wrong things"
266
+ assert_equal 'the results', returned, "Wrong return value"
267
+ end
268
+
269
+ def test_yields_with_raises
270
+ se = SimpleExpectation.new(:mock => @mock, :method => 'each_bean', :arguments => [:side_slot],
271
+ :raises => RuntimeError.new("kerboom"))
272
+
273
+ exp = se.yields :bean1, :bean2
274
+ assert_same se, exp, "'yields' needs to return a reference to the expectation"
275
+ things = []
276
+ a_block = lambda { |thinger| things << thinger }
277
+ err = assert_raise RuntimeError do
278
+ se.apply_method_call(@mock,'each_bean',[:side_slot],a_block)
279
+ end
280
+ assert_match(/kerboom/i, err.message)
281
+ assert_equal [:bean1,:bean2], things, "Wrong things"
282
+ end
283
+
284
+ def test_yields_and_inner_block_explodes
285
+ se = SimpleExpectation.new(:mock => @mock, :method => 'each_bean', :arguments => [:side_slot])
286
+
287
+ exp = se.yields :bean1, :bean2
288
+ assert_same se, exp, "'yields' needs to return a reference to the expectation"
289
+ things = []
290
+ a_block = lambda { |thinger|
291
+ things << thinger
292
+ raise "nasty"
293
+ }
294
+ err = assert_raise RuntimeError do
295
+ se.apply_method_call(@mock,'each_bean',[:side_slot],a_block)
296
+ end
297
+ assert_match(/nasty/i, err.message)
298
+ assert_equal [:bean1], things, "Wrong things"
299
+ end
300
+
301
+ def test_yields_with_several_arrays
302
+ se = SimpleExpectation.new(:mock => @mock, :method => 'each_bean', :arguments => [:side_slot] )
303
+ se.yields ['a','b'], ['c','d']
304
+
305
+ things = []
306
+ a_block = lambda { |thinger| things << thinger }
307
+
308
+ se.apply_method_call(@mock,'each_bean',[:side_slot],a_block)
309
+ assert_equal [ ['a','b'], ['c','d'] ], things, "Wrong things"
310
+ end
311
+
312
+ def test_yields_tuples
313
+ se = SimpleExpectation.new(:mock => @mock, :method => 'each_bean', :arguments => [:side_slot] )
314
+ se.yields ['a','b','c'], ['d','e','f']
315
+
316
+ things = []
317
+ a_block = lambda { |left,mid,right|
318
+ things << { :left => left, :mid => mid, :right => right }
319
+ }
320
+
321
+ se.apply_method_call(@mock,'each_bean',[:side_slot],a_block)
322
+ assert_equal [
323
+ {:left => 'a', :mid => 'b', :right => 'c' },
324
+ {:left => 'd', :mid => 'e', :right => 'f' },
325
+ ], things, "Wrong things"
326
+ end
327
+
328
+ def test_yields_tuples_size_mismatch
329
+ se = SimpleExpectation.new(:mock => @mock, :method => 'each_bean', :arguments => [:side_slot] )
330
+ se.yields ['a','b','c'], ['d','e','f']
331
+
332
+ things = []
333
+ a_block = lambda { |left,mid|
334
+ things << { :left => left, :mid => mid }
335
+ }
336
+
337
+ err = assert_raise ExpectationError do
338
+ se.apply_method_call(@mock,'each_bean',[:side_slot],a_block)
339
+ end
340
+ assert_match(/arity/i, err.message)
341
+ assert_match(/the_mock.each_bean/i, err.message)
342
+ assert_match(/"a", "b", "c"/i, err.message)
343
+ assert_equal [], things, "Wrong things"
344
+ end
345
+ end
@@ -0,0 +1,60 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+ require 'hardmock'
3
+
4
+ class TrapperTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @mock = Object.new
8
+ @mock_control = MyControl.new
9
+ @builder = ExpBuilder.new
10
+ @trapper = Trapper.new(@mock, @mock_control, @builder)
11
+ end
12
+
13
+ #
14
+ # HELPERS
15
+ #
16
+
17
+ class MyControl
18
+ attr_reader :added
19
+ def add_expectation(expectation)
20
+ @added ||= []
21
+ @added << expectation
22
+ end
23
+ end
24
+
25
+ class ExpBuilder
26
+ attr_reader :options
27
+ def build_expectation(options)
28
+ @options = options
29
+ "dummy expectation"
30
+ end
31
+ end
32
+
33
+ #
34
+ # TESTS
35
+ #
36
+
37
+ def test_method_missing
38
+
39
+ output = @trapper.change(:less)
40
+
41
+ assert_same @mock, @builder.options[:mock]
42
+ assert_equal :change, @builder.options[:method]
43
+ assert_equal [:less], @builder.options[:arguments]
44
+ assert_not_nil @builder.options[:block]
45
+ assert @builder.options[:suppress_arguments_to_block], ":suppress_arguments_to_block should be set"
46
+ assert_equal [ "dummy expectation" ], @mock_control.added,
47
+ "Wrong expectation added to control"
48
+
49
+ assert_equal "dummy expectation", output, "Expectation should have been returned"
50
+
51
+ # Examine the block. It should take one argument and simply return
52
+ # that argument. because of the 'suppress arguments to block'
53
+ # setting, the argument can only end up being a block, in practice.
54
+ trapper_block = @builder.options[:block]
55
+ assert_equal "the argument", trapper_block.call("the argument"),
56
+ "The block should merely return the passed argument"
57
+ end
58
+
59
+
60
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+ require 'hardmock'
3
+
4
+ class VerifyErrorTest < Test::Unit::TestCase
5
+
6
+ #
7
+ # TESTS
8
+ #
9
+
10
+ def test_formatted_list_of_unmet_expectations
11
+ mock1 = Mock.new('mock1')
12
+ mock2 = Mock.new('mock2')
13
+ exp1 = SimpleExpectation.new( :mock => mock1, :method => 'send_parts', :arguments => [1,2,:a] )
14
+ exp2 = SimpleExpectation.new( :mock => mock2, :method => 'grind_it', :arguments => [] )
15
+
16
+ exp_list = [ exp1, exp2 ]
17
+
18
+ err = VerifyError.new("This is the error", exp_list)
19
+ assert_equal "This is the error:\n * #{exp1.to_s}\n * #{exp2.to_s}", err.message
20
+ end
21
+
22
+ def test_empty_list_of_expectations
23
+ # this is not a normal case; not spending a lot of time to make this better
24
+ exp_list = []
25
+ err = VerifyError.new("This is the error:\n", exp_list)
26
+ end
27
+
28
+ def test_nil_expectation_list
29
+ # this is not a normal case; not spending a lot of time to make this better
30
+ exp_list = []
31
+ err = VerifyError.new("This is the error:\n", exp_list)
32
+ end
33
+
34
+ end
@@ -0,0 +1,403 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # = DESCRIPTION
4
+ #
5
+ # Systir stands for "SYStem Testing In Ruby". It's a framework for
6
+ # automating system-level tests using domain-specific language, and contains
7
+ # some tools and hints on how to construct and utilize your own domain language.
8
+ #
9
+ # The breakdown of using Systir for test automation is:
10
+ # 1. Tester defines test steps using project- and technology-specific language.
11
+ # * Tests are written in files like +authentication+.+test+ and
12
+ # +order_placement+.+test+
13
+ # 2. The Toolsmith implements a driver to support the syntax of that language
14
+ # * In a project-specific module, the Toolsmith writes an extension of the
15
+ # Systir::LanguageDriver class to support the macros used in *.test
16
+ # 3. The Tester's "scripts" are gathered up by Systir, executed, and a report
17
+ # is generated.
18
+ # * Toolsmith writes a short script which uses Systest::Launcher to compose
19
+ # *.test files into a suite for execution.
20
+ #
21
+ # = TECHNICAL NOTE
22
+ # Under the hood, Systir is an extension of Test::Unit. The output from
23
+ # executing the test suite should therefor be familiar to a Ruby coder.
24
+ # Additionally, it might be educational to the Toolsmith to understand that
25
+ # LanguageDriver is a derivative of Test::Unit::TestCase, and that all *.test
26
+ # files become test methods inside the TestCase which is then composed as a
27
+ # Test::Unit::TestSuite
28
+ #
29
+
30
+ require 'test/unit'
31
+ require 'test/unit/ui/console/testrunner'
32
+ require 'test/unit/ui/xml/testrunner'
33
+ require 'find'
34
+ require 'stringio'
35
+ require 'ostruct'
36
+
37
+ # This disables the auto-run-at-exit feature inside test/unit.rb:
38
+ Test::Unit.run = true
39
+
40
+ module Test
41
+ module Unit
42
+ class TestResult
43
+ attr_reader :failures, :errors, :assertion_count
44
+ attr_accessor :output
45
+ end
46
+ end
47
+ end
48
+
49
+ #
50
+ # Systir contains classes and modules to support writing and launching
51
+ # high-level test scripts.
52
+ #
53
+ module Systir
54
+
55
+ VERSION = '0.5'
56
+
57
+ #
58
+ # Systir::LanguageDriver is a special derivative of TestCase designed to
59
+ # contain user code written to support more macro-fied testing scripts.
60
+ #
61
+ class LanguageDriver < Test::Unit::TestCase
62
+ attr_accessor :params
63
+
64
+ # == Description
65
+ # Installs a back-reference from this Driver instance into the specified Helper
66
+ # and returns a reference to that Helper. Typically thismethod is called
67
+ # on the same line you return the helper from once it's built.
68
+ #
69
+ # == Params
70
+ # +helper+ :: The Helper instance you're handing control over to
71
+ #
72
+ # == Return
73
+ # The same +helper+ reference that was sent in as a parameter.
74
+ #
75
+ # == Details
76
+ #
77
+ # Since Helpers are usually built as support for domain-level syntax,
78
+ # they usually require a direct reference to macro functions built into
79
+ # the driver. Additionally, the Helper may need to make assertions
80
+ # defined in the driver, or test/unit itself, and only the Driver may
81
+ # count assertions; the Helper must use a special internal implementation
82
+ # of 'add_assertion' in order to increment the test's assertion count.
83
+ #
84
+ # Some aliases have been added to aid readability
85
+ #
86
+ def associate_helper(helper)
87
+ unless helper.respond_to? :driver=
88
+ raise "helper doesn't support 'driver=' method"
89
+ end
90
+ helper.driver = self
91
+ return helper
92
+ end
93
+ alias_method :return_helper, :associate_helper
94
+ alias_method :hand_off_to, :associate_helper
95
+
96
+ # (INTERNAL USE)
97
+ # Sneaky trick to expose the private mix-in method +add_assertion+ from
98
+ # Test::Unit::Assertions. Helpers derivatives that make assertions are
99
+ # able to have them counted because of this method.
100
+ # (See associate_helper.)
101
+ def collect_assertion
102
+ add_assertion
103
+ end
104
+ end
105
+
106
+ # = Description
107
+ # Imports test scripts into the given driver class
108
+ # and produces a TestSuite ready for execution
109
+ class Builder
110
+ def initialize(driver_class)
111
+ raise 'driver class must be a Systir::LanguageDriver' unless driver_class < Systir::LanguageDriver
112
+ @driver_class = driver_class
113
+ remove_test_methods
114
+ end
115
+
116
+ # Read contents from_file, wrap text in 'def',
117
+ # add the resulting code as a new method on the target driver class
118
+ def import_test(test)
119
+ # Transform the test script into a test method inside
120
+ # the driver class:
121
+ text = File.readlines(test.path)
122
+ text = "def test_#{test.fullname}\n#{text}\nend\n";
123
+
124
+ # Dynamically define the method:
125
+ @driver_class.class_eval(text, File.basename(test.path), 0)
126
+ test_case = @driver_class.new("test_#{test.fullname}")
127
+ test_case.params = test.params
128
+ test_case
129
+ end
130
+
131
+ def suite_for_directory(dir)
132
+ list = TestList.new
133
+ Find.find(dir) do |path|
134
+ if File.basename(path) =~ /\.test$/
135
+ list.add :test => path
136
+ end
137
+ if File.directory? path
138
+ next
139
+ end
140
+ end
141
+ suite_for_test_list list
142
+ end
143
+
144
+ def suite_for_file(filename,params=nil)
145
+ list = TestList.new
146
+ list.add :test => filename, :params => params
147
+ suite_for_test_list list
148
+ end
149
+
150
+ def suite_for_list(file_list)
151
+ list = TestList.new
152
+ file_list.each do |path|
153
+ list.add :test => path
154
+ end
155
+ suite_for_test_list list
156
+ end
157
+
158
+ def suite_for_test_list(test_list)
159
+ suite = Test::Unit::TestSuite.new(@driver_class.name)
160
+ test_list.tests.each do |test|
161
+ suite << import_test(test)
162
+ end
163
+ suite
164
+ end
165
+
166
+ def remove_test_methods
167
+ methods = @driver_class.public_instance_methods.select { |m|
168
+ m =~ /^test_/
169
+ }
170
+ methods.each do |method|
171
+ @driver_class.send(:undef_method,method)
172
+ end
173
+ end
174
+ end
175
+
176
+ class TestList #:nodoc:
177
+ attr_reader :tests
178
+
179
+ def initialize
180
+ @tests = []
181
+ end
182
+
183
+ def add(args)
184
+ test = OpenStruct.new
185
+ test.path = args[:test]
186
+ test.params = args[:params]
187
+ test.name = File.basename(test.path).sub(/\.test$/, '')
188
+ test.fullname = test.name + (args[:name_suffix] ? "_#{args[:name_suffix]}" : '')
189
+ @tests << test
190
+ end
191
+ end
192
+
193
+ # = Description
194
+ # Launcher is the utility for launching Systir test scripts.
195
+ #
196
+ class Launcher
197
+ #
198
+ # Creates a new Launcher, the following arguments may be specified in a hash
199
+ #
200
+ # :stdout - true or false, whether to send test reporting output to stdout (default true)
201
+ # :format - :console or :xml, format of test reporting output (default :xml)
202
+ #
203
+ # note: output is available via the TestResult returned from the following methods:
204
+ # * find_and_run_all_tests
205
+ # * run_test
206
+ # * run_test_list
207
+ # * run_suite
208
+ #
209
+ def initialize(args={})
210
+ @stdout = args[:stdout].nil? ? true : args[:stdout]
211
+ @format = args[:format].nil? ? :console : args[:format]
212
+ end
213
+
214
+ #
215
+ # Find and run all the system test scripts in the given directory.
216
+ # Tests are identified by the .test file extension.
217
+ #
218
+ def find_and_run_all_tests(driver_class, dir='.')
219
+ raise 'dir cannot be nil' if dir.nil?
220
+ raise 'dir does not exist' unless File.directory?(dir)
221
+ b = Builder.new(driver_class)
222
+ execute b.suite_for_directory(dir)
223
+ end
224
+
225
+ #
226
+ # Run a specific test, optionally providing parameters to be available
227
+ # within the driver instance.
228
+ #
229
+ # Systir::Launcher.new.run_test(MyDriver, './tests/foo.test')
230
+ #
231
+ # Systir::Launcher.new.run_test(MyDriver, './tests/foo.test', :opt1 => 'thinger', :another => 'bar')
232
+ #
233
+ # given parameters are available via the <tt>params</tt> method on the
234
+ # driver instance which returns the hash passed to run_test.
235
+ #
236
+ # returns TestResult
237
+ #
238
+ def run_test(driver_class, filename, params=nil)
239
+ raise 'filename cannot be nil' if filename.nil?
240
+ raise 'filename does not exist' unless File.exists?(filename)
241
+ b = Builder.new(driver_class)
242
+ execute b.suite_for_file(filename,params)
243
+ end
244
+
245
+ #
246
+ # Run a specific list of tests
247
+ #
248
+ # returns TestResult
249
+ #
250
+ def run_test_list(driver_class, file_list)
251
+ raise 'file_list cannot be nil' if file_list.nil?
252
+ raise 'file_list cannot be empty' if file_list.empty?
253
+ b = Builder.new(driver_class)
254
+ execute b.suite_for_list(file_list)
255
+ end
256
+
257
+ #
258
+ # Run a suite of tests defined by a given block.
259
+ #
260
+ # launcher.run_suite(MyDriver) do |suite|
261
+ # suite.add :test => './tests/run_me_twice.test'
262
+ # suite.add :test => './tests/run_me_twice.test', :name_suffix => 'other_one'
263
+ # suite.add :test => './tests/specific_parameters.test', :params => {:one => 'mine', :two => 'also mine'}
264
+ # end
265
+ #
266
+ # :test - path to the systir test file
267
+ # :name_suffix - (optional) string appended to the end of the test name in
268
+ # this suite run.this option is useful when running multiple
269
+ # tests from the same file.
270
+ # :params - (optional) hash of parameters to be set on the driver instance
271
+ # for the execution of this test
272
+ #
273
+ # returns TestResult
274
+ #
275
+ def run_suite(driver_class)
276
+ b = Builder.new(driver_class)
277
+ suite = TestList.new
278
+ yield suite
279
+ execute b.suite_for_test_list(suite)
280
+ end
281
+
282
+ #
283
+ # Use console test runner to execute the given suite
284
+ #
285
+ def execute(suite)
286
+ buffer = StringIO.new
287
+ ios = []
288
+ ios << STDOUT if @stdout
289
+ ios << buffer
290
+ io = MethodMulticaster.new(ios)
291
+ level = Test::Unit::UI::NORMAL
292
+
293
+ runner = case @format
294
+ when :console
295
+ Test::Unit::UI::Console::TestRunner
296
+ when :xml
297
+ Test::Unit::UI::XML::TestRunner
298
+ else
299
+ raise "don't know anything about runner: [#{@runner}]"
300
+ end
301
+
302
+ result = runner.new(suite, level, io).start
303
+ buffer.rewind
304
+ result.output = buffer.read
305
+ result
306
+ end
307
+ end
308
+
309
+ class MethodMulticaster #:nodoc:
310
+ def initialize(targets)
311
+ @targets = targets
312
+ end
313
+
314
+ def method_missing(method,*args)
315
+ @targets.each do |target|
316
+ target.send(method,*args)
317
+ end
318
+ end
319
+ end
320
+
321
+
322
+ # = DESCRIPTION
323
+ # Systir::Helper is a module intended for mixing-in to classes defined
324
+ # to assist a project-specific Systir::LanguageDriver.
325
+ #
326
+ #
327
+ module Helper
328
+ include Test::Unit::Assertions
329
+
330
+ #
331
+ # Construct a new Helper with a back reference to the language driver.
332
+ # NOTE: the +driver+ argument is optional if you utilize <code>driver=</code>
333
+ # or Systir::LanguageDriver.associate_helper
334
+ #
335
+ def initialize(driver=nil)
336
+ @_driver = driver
337
+ end
338
+
339
+ #
340
+ # Returns a reference to our owning LanguageDriver instance.
341
+ #
342
+ def driver
343
+ unless @_driver
344
+ raise "Implementation error: helper has no back reference to the language driver!"
345
+ end
346
+ return @_driver
347
+ end
348
+
349
+ #
350
+ # Sets the owning reference to a LanguageDriver.
351
+ # This method is used by Systir::LanguageDriver#associate_helper.
352
+ #
353
+ def driver=(dr)
354
+ @_driver = dr
355
+ end
356
+
357
+ # == Description
358
+ # Installs a back-reference from this Driver instance into the specified Helper
359
+ # and returns a reference to that Helper. Typically thismethod is called
360
+ # on the same line you return the helper from once it's built.
361
+ #
362
+ # == Params
363
+ # +helper+ :: The Helper instance you're handing control over to
364
+ #
365
+ # == Return
366
+ # The same +helper+ reference that was sent in as a parameter.
367
+ #
368
+ # == Details
369
+ #
370
+ # Since Helpers are usually built as support for domain-level syntax,
371
+ # they usually require a direct reference to macro functions built into
372
+ # the driver. Additionally, the Helper may need to make assertions
373
+ # defined in the driver, or test/unit itself, and only the Driver may
374
+ # count assertions; the Helper must use a special internal implementation
375
+ # of 'add_assertion' in order to increment the test's assertion count.
376
+ #
377
+ # Some aliases have been added to aid readability
378
+ #
379
+ def associate_helper(helper)
380
+ unless helper.respond_to? :driver=
381
+ raise "helper doesn't support 'driver=' method"
382
+ end
383
+ helper.driver = self.driver
384
+ return helper
385
+ end
386
+ alias_method :return_helper, :associate_helper
387
+ alias_method :hand_off_to, :associate_helper
388
+
389
+ #
390
+ # Redirects assertion counting into our owning LanguageDriver.
391
+ # Assertions module will automatically attempt to store the count
392
+ # within a Helper otherwise, leading to incorrect results.
393
+ #
394
+ private
395
+ def add_assertion
396
+ unless driver.respond_to? :collect_assertion
397
+ raise "Implementation error: driver needs a 'collect_assertion' method"
398
+ end
399
+ driver.collect_assertion
400
+ end
401
+ end
402
+ end
403
+