minilab 1.0.0-mswin32

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.
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
+