test-spec 0.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,38 @@
1
+ # Copied without code changes from RSpec.
2
+
3
+ class StackUnderflowError < RuntimeError
4
+ end
5
+
6
+ class StackOverflowError < RuntimeError
7
+ end
8
+
9
+ class Stack
10
+
11
+ def initialize
12
+ @items = []
13
+ end
14
+
15
+ def push object
16
+ raise StackOverflowError if @items.length == 10
17
+ @items.push object
18
+ end
19
+
20
+ def pop
21
+ raise StackUnderflowError if @items.empty?
22
+ @items.delete @items.last
23
+ end
24
+
25
+ def peek
26
+ raise StackUnderflowError if @items.empty?
27
+ @items.last
28
+ end
29
+
30
+ def empty?
31
+ @items.empty?
32
+ end
33
+
34
+ def full?
35
+ @items.length == 10
36
+ end
37
+
38
+ end
@@ -0,0 +1,119 @@
1
+ # Copied with minor code changes (should_xxx -> should.xxx) from RSpec.
2
+
3
+ require File.dirname(__FILE__) + '/../lib/test/spec'
4
+ require File.dirname(__FILE__) + "/stack"
5
+
6
+ context "A stack (in general)" do
7
+ setup do
8
+ @stack = Stack.new
9
+ ["a","b","c"].each { |x| @stack.push x }
10
+ end
11
+
12
+ specify "should add to the top when sent 'push'" do
13
+ @stack.push "d"
14
+ @stack.peek.should.equal "d"
15
+ end
16
+
17
+ specify "should return the top item when sent 'peek'" do
18
+ @stack.peek.should.equal "c"
19
+ end
20
+
21
+ specify "should NOT remove the top item when sent 'peek'" do
22
+ @stack.peek.should.equal "c"
23
+ @stack.peek.should.equal "c"
24
+ end
25
+
26
+ specify "should return the top item when sent 'pop'" do
27
+ @stack.pop.should.equal "c"
28
+ end
29
+
30
+ specify "should remove the top item when sent 'pop'" do
31
+ @stack.pop.should.equal "c"
32
+ @stack.pop.should.equal "b"
33
+ end
34
+ end
35
+
36
+ context "An empty stack" do
37
+ setup do
38
+ @stack = Stack.new
39
+ end
40
+
41
+ specify "should be empty" do
42
+ @stack.should.be.empty
43
+ end
44
+
45
+ specify "should no longer be empty after 'push'" do
46
+ @stack.push "anything"
47
+ @stack.should.not.be.empty
48
+ end
49
+
50
+ specify "should complain when sent 'peek'" do
51
+ lambda { @stack.peek }.should.raise StackUnderflowError
52
+ end
53
+
54
+ specify "should complain when sent 'pop'" do
55
+ lambda { @stack.pop }.should.raise StackUnderflowError
56
+ end
57
+ end
58
+
59
+ context "An almost empty stack (with one item)" do
60
+ setup do
61
+ @stack = Stack.new
62
+ @stack.push 3
63
+ end
64
+
65
+ specify "should not be empty" do
66
+ @stack.should.not.be.empty
67
+ end
68
+
69
+ specify "should remain not empty after 'peek'" do
70
+ @stack.peek
71
+ @stack.should.not.be.empty
72
+ end
73
+
74
+ specify "should become empty after 'pop'" do
75
+ @stack.pop
76
+ @stack.should.be.empty
77
+ end
78
+ end
79
+
80
+ context "An almost full stack (with one item less than capacity)" do
81
+ setup do
82
+ @stack = Stack.new
83
+ (1..9).each { |i| @stack.push i }
84
+ end
85
+
86
+ specify "should not be full" do
87
+ @stack.should.not.be.full
88
+ end
89
+
90
+ specify "should become full when sent 'push'" do
91
+ @stack.push Object.new
92
+ @stack.should.be.full
93
+ end
94
+ end
95
+
96
+ context "A full stack" do
97
+ setup do
98
+ @stack = Stack.new
99
+ (1..10).each { |i| @stack.push i }
100
+ end
101
+
102
+ specify "should be full" do
103
+ @stack.should.be.full
104
+ end
105
+
106
+ specify "should remain full after 'peek'" do
107
+ @stack.peek
108
+ @stack.should.be.full
109
+ end
110
+
111
+ specify "should no longer be full after 'pop'" do
112
+ @stack.pop
113
+ @stack.should.not.be.full
114
+ end
115
+
116
+ specify "should complain on 'push'" do
117
+ lambda { @stack.push Object.new }.should.raise StackOverflowError
118
+ end
119
+ end
@@ -1,7 +1,7 @@
1
1
  #
2
2
  # test/spec -- a BDD interface for Test::Unit
3
3
  #
4
- # Copyright (C) 2006 Christian Neukirchen <mailto:chneukirchen@gmail.com>
4
+ # Copyright (C) 2006, 2007 Christian Neukirchen <mailto:chneukirchen@gmail.com>
5
5
  #
6
6
  # This work is licensed under the same terms as Ruby itself.
7
7
  #
@@ -24,9 +24,9 @@ module Test # :nodoc:
24
24
  end
25
25
 
26
26
  module Test::Spec
27
- VERSION = "0.1"
27
+ VERSION = "0.3"
28
28
 
29
- CONTEXTS = {}
29
+ CONTEXTS = {} # :nodoc:
30
30
 
31
31
  class DefinitionError < StandardError
32
32
  end
@@ -34,8 +34,16 @@ module Test::Spec
34
34
  class Should
35
35
  include Test::Unit::Assertions
36
36
 
37
- def initialize(object)
37
+ def self.deprecated_alias(to, from) # :nodoc:
38
+ define_method(to) { |*args|
39
+ warn "Test::Spec::Should##{to} is deprecated and will be removed in future versions."
40
+ __send__ from, *args
41
+ }
42
+ end
43
+
44
+ def initialize(object, message=nil)
38
45
  @object = object
46
+ @message = message
39
47
  end
40
48
 
41
49
  $TEST_SPEC_TESTCASE = nil
@@ -52,96 +60,121 @@ module Test::Spec
52
60
  self
53
61
  end
54
62
 
55
- def not
56
- ShouldNot.new(@object)
63
+ def not(*args)
64
+ case args.size
65
+ when 0
66
+ ShouldNot.new(@object, @message)
67
+ when 1
68
+ ShouldNot.new(@object, @message).pass(args.first)
69
+ else
70
+ raise ArgumentError, "#not takes zero or one argument(s)."
71
+ end
57
72
  end
58
73
 
74
+ def messaging(message)
75
+ @message = message.to_s
76
+ self
77
+ end
78
+ alias blaming messaging
59
79
 
60
80
  def satisfy(&block)
61
- assert_block("satisfy block failed.") {
81
+ assert_block(@message || "satisfy block failed.") {
62
82
  yield @object
63
83
  }
64
84
  end
65
85
 
66
86
  def equal(value)
67
- assert_equal value, @object
87
+ assert_equal value, @object, @message
68
88
  end
69
89
  alias == equal
70
90
 
71
91
  def close(value, delta)
72
- assert_in_delta value, @object, delta
92
+ assert_in_delta value, @object, delta, @message
73
93
  end
74
- alias be_close close
94
+ deprecated_alias :be_close, :close
75
95
 
76
96
  def be(*value)
77
97
  case value.size
78
98
  when 0
79
99
  self
80
100
  when 1
81
- assert_same value.first, @object
101
+ if CustomShould === value.first
102
+ pass value.first
103
+ else
104
+ assert_same value.first, @object, @message
105
+ end
82
106
  else
83
107
  raise ArgumentError, "should.be needs zero or one argument"
84
108
  end
85
109
  end
86
110
 
87
111
  def match(value)
88
- assert_match value, @object
112
+ assert_match value, @object, @message
89
113
  end
90
114
  alias =~ match
91
115
 
92
116
  def instance_of(klass)
93
- assert_instance_of klass, @object
117
+ assert_instance_of klass, @object, @message
94
118
  end
95
- alias be_an_instance_of instance_of
119
+ deprecated_alias :be_an_instance_of, :instance_of
96
120
 
97
121
  def kind_of(klass)
98
- assert_kind_of klass, @object
122
+ assert_kind_of klass, @object, @message
99
123
  end
100
- alias be_a_kind_of kind_of
124
+ deprecated_alias :be_a_kind_of, :kind_of
101
125
 
102
126
  def respond_to(method)
103
- assert_respond_to @object, method
127
+ assert_respond_to @object, method, @message
104
128
  end
105
129
 
106
130
  def _raise(*args)
107
131
  args = [RuntimeError] if args.empty?
108
- assert_raise(*args, &@object)
132
+ assert_raise(*(args + [@message]), &@object)
109
133
  end
110
134
 
111
135
  def throw(*args)
112
- assert_throws(*args, &@object)
136
+ assert_throws(*(args + [@message]), &@object)
113
137
  end
114
138
 
115
139
  def nil
116
- assert_nil @object
140
+ assert_nil @object, @message
117
141
  end
118
- alias be_nil nil
142
+ deprecated_alias :be_nil, :nil
119
143
 
120
144
 
121
145
  def include(value)
122
- msg = build_message(nil, "<?> expected to include ?, but it didn't.",
146
+ msg = build_message(@message, "<?> expected to include ?, but it didn't.",
123
147
  @object, value)
124
148
  assert_block(msg) { @object.include?(value) }
125
149
  end
126
150
 
127
151
  def >(value)
128
- assert_operator @object, :>, value
152
+ assert_operator @object, :>, value, @message
129
153
  end
130
154
 
131
155
  def >=(value)
132
- assert_operator @object, :>=, value
156
+ assert_operator @object, :>=, value, @message
133
157
  end
134
158
 
135
159
  def <(value)
136
- assert_operator @object, :<, value
160
+ assert_operator @object, :<, value, @message
137
161
  end
138
162
 
139
163
  def <=(value)
140
- assert_operator @object, :<=, value
164
+ assert_operator @object, :<=, value, @message
141
165
  end
142
166
 
143
167
  def ===(value)
144
- assert_operator @object, :===, value
168
+ assert_operator @object, :===, value, @message
169
+ end
170
+
171
+ def pass(custom)
172
+ _wrap_assertion {
173
+ assert_nothing_raised(Test::Unit::AssertionFailedError,
174
+ @message || custom.failure_message) {
175
+ assert custom.matches?(@object), @message || custom.failure_message
176
+ }
177
+ }
145
178
  end
146
179
 
147
180
  def method_missing(name, *args)
@@ -150,7 +183,7 @@ module Test::Spec
150
183
 
151
184
  if @object.respond_to?("#{name}?")
152
185
  assert @object.__send__("#{name}?", *args),
153
- "#{name}? expected to be true."
186
+ "#{name}? expected to be true. #{@message}"
154
187
  else
155
188
  super
156
189
  end
@@ -160,12 +193,19 @@ module Test::Spec
160
193
  class ShouldNot
161
194
  include Test::Unit::Assertions
162
195
 
163
- def initialize(object)
196
+ def initialize(object, message=nil)
164
197
  @object = object
198
+ @message = message
199
+ end
200
+
201
+ def satisfy(&block)
202
+ assert_block(@message || "not.satisfy block succeded.") {
203
+ not yield @object
204
+ }
165
205
  end
166
206
 
167
207
  def equal(value)
168
- assert_not_equal value, @object
208
+ assert_not_equal value, @object, @message
169
209
  end
170
210
  alias == equal
171
211
 
@@ -174,7 +214,11 @@ module Test::Spec
174
214
  when 0
175
215
  self
176
216
  when 1
177
- assert_not_same value.first, @object
217
+ if CustomShould === value.first
218
+ pass value.first
219
+ else
220
+ assert_not_same value.first, @object, @message
221
+ end
178
222
  else
179
223
  Kernel.raise ArgumentError, "should.be needs zero or one argument"
180
224
  end
@@ -182,42 +226,80 @@ module Test::Spec
182
226
 
183
227
  def match(value)
184
228
  # Icky Regexp check
185
- assert_no_match value, @object
229
+ assert_no_match value, @object, @message
186
230
  end
187
231
  alias =~ match
188
232
 
189
233
  def _raise(*args)
190
- assert_nothing_raised(*args, &@object)
234
+ assert_nothing_raised(*(args+[@message]), &@object)
191
235
  end
192
236
 
193
237
  def throw
194
- assert_nothing_thrown(&@object)
238
+ assert_nothing_thrown(@message, &@object)
195
239
  end
196
240
 
197
241
  def nil
198
- assert_not_nil @object
242
+ assert_not_nil @object, @message
199
243
  end
200
- alias be_nil nil
201
244
 
245
+ def be_nil
246
+ warn "Test::Spec::ShouldNot#be_nil is deprecated and will be removed in future versions."
247
+ self.nil
248
+ end
202
249
 
203
- def not
204
- Should.new(@object)
250
+ def not(*args)
251
+ case args.size
252
+ when 0
253
+ Should.new(@object, @message)
254
+ when 1
255
+ Should.new(@object, @message).pass(args.first)
256
+ else
257
+ raise ArgumentError, "#not takes zero or one argument(s)."
258
+ end
205
259
  end
206
260
 
261
+ def pass(custom)
262
+ _wrap_assertion {
263
+ begin
264
+ assert !custom.matches?(@object), @message || custom.failure_message
265
+ end
266
+ }
267
+ end
207
268
 
208
269
  def method_missing(name, *args)
209
270
  # This will make raise call Kernel.raise, and self.raise call _raise.
210
271
  return _raise(*args) if name == :raise
211
272
 
212
273
  if @object.respond_to?("#{name}?")
213
- assert_block("#{name}? expected to be false.") {
274
+ assert_block("#{name}? expected to be false. #{@message}") {
214
275
  not @object.__send__("#{name}?", *args)
215
276
  }
216
277
  else
217
278
  super
218
279
  end
219
280
  end
281
+
282
+ end
220
283
 
284
+ class CustomShould
285
+ attr_accessor :object
286
+
287
+ def initialize(obj)
288
+ self.object = obj
289
+ end
290
+
291
+ def failure_message
292
+ "#{self.class.name} failed"
293
+ end
294
+
295
+ def matches?(*args, &block)
296
+ assumptions(*args, &block)
297
+ true
298
+ end
299
+
300
+ def assumptions(*args, &block)
301
+ raise NotImplementedError, "you need to supply a #{self.class}#matches? method"
302
+ end
221
303
  end
222
304
  end
223
305
 
@@ -275,10 +357,16 @@ class Test::Spec::TestCase
275
357
 
276
358
  self.count += 1 # Let them run in order of definition
277
359
 
278
- # TODO Changed by Jean-Michel
279
- # define_method("test_%03d: %s" % [count, specname], &block)
280
360
  define_method("test_spec {%s} %03d [%s]" % [name, count, specname], &block)
281
361
  end
362
+
363
+ def xspecify(specname, &block)
364
+ raise ArgumentError, "xspecify needs a block" if block.nil?
365
+
366
+ specify specname do
367
+ @_result.add_disabled(specname)
368
+ end
369
+ end
282
370
 
283
371
  def setup(&block)
284
372
  setups << block
@@ -324,6 +412,24 @@ class Test::Spec::TestCase
324
412
  end
325
413
  end
326
414
 
415
+ class Test::Spec::Disabled < Test::Unit::Failure # :nodoc:
416
+ def initialize(name)
417
+ @name = name
418
+ end
419
+
420
+ def single_character_display
421
+ "D"
422
+ end
423
+
424
+ def short_display
425
+ @name
426
+ end
427
+
428
+ def long_display
429
+ @name + " is disabled"
430
+ end
431
+ end
432
+
327
433
 
328
434
  # Monkey-patch test/unit to run tests in an optionally specified order.
329
435
  module Test::Unit # :nodoc:
@@ -348,19 +454,35 @@ module Test::Unit # :nodoc:
348
454
  @tests.first.respond_to?(:position) ? @tests.first.position : 0
349
455
  end
350
456
  end
457
+
458
+ class TestResult # :nodoc:
459
+ # Records a disabled test.
460
+ def add_disabled(name)
461
+ notify_listeners(FAULT, Test::Spec::Disabled.new(name))
462
+ notify_listeners(CHANGED, self)
463
+ end
464
+ end
351
465
  end
352
466
 
353
467
 
354
- # Global helpers
468
+
469
+ #-- Global helpers
355
470
 
356
471
  class Object
357
- def should
358
- Test::Spec::Should.new(self)
472
+ def should(*args)
473
+ case args.size
474
+ when 0
475
+ Test::Spec::Should.new(self)
476
+ when 1
477
+ Test::Spec::Should.new(self).pass(args.first)
478
+ else
479
+ raise ArgumentError, "Object#should takes zero or one argument(s)."
480
+ end
359
481
  end
360
482
  end
361
483
 
362
484
  module Kernel
363
- def context(name, &block)
485
+ def context(name, &block) # :doc:
364
486
  (Test::Spec::CONTEXTS[name] ||= Test::Spec::TestCase.new(name)).add(&block)
365
487
  end
366
488