nullstyle-test-spec 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,660 @@
1
+ #
2
+ # test/spec -- a BDD interface for Test::Unit
3
+ #
4
+ # Copyright (C) 2006, 2007 Christian Neukirchen <mailto:chneukirchen@gmail.com>
5
+ #
6
+ # This work is licensed under the same terms as Ruby itself.
7
+ #
8
+
9
+ require 'test/unit'
10
+
11
+ class Test::Unit::AutoRunner # :nodoc:
12
+ RUNNERS[:specdox] = lambda {
13
+ require 'test/spec/dox'
14
+ Test::Unit::UI::SpecDox::TestRunner
15
+ }
16
+
17
+ RUNNERS[:rdox] = lambda {
18
+ require 'test/spec/rdox'
19
+ Test::Unit::UI::RDox::TestRunner
20
+ }
21
+ end
22
+
23
+ module Test # :nodoc:
24
+ end
25
+
26
+ module Test::Spec
27
+ require 'test/spec/version'
28
+
29
+ CONTEXTS = {} # :nodoc:
30
+ SHARED_CONTEXTS = Hash.new { |h,k| h[k] = [] } # :nodoc:
31
+
32
+ class DefinitionError < StandardError
33
+ end
34
+
35
+ class Should
36
+ include Test::Unit::Assertions
37
+
38
+ def self.deprecated_alias(to, from) # :nodoc:
39
+ define_method(to) { |*args|
40
+ warn "Test::Spec::Should##{to} is deprecated and will be removed in future versions."
41
+ __send__ from, *args
42
+ }
43
+ end
44
+
45
+ def initialize(object, message=nil)
46
+ @object = object
47
+ @message = message
48
+ end
49
+
50
+ $TEST_SPEC_TESTCASE = nil
51
+ def add_assertion
52
+ $TEST_SPEC_TESTCASE && $TEST_SPEC_TESTCASE.__send__(:add_assertion)
53
+ end
54
+
55
+
56
+ def an
57
+ self
58
+ end
59
+
60
+ def a
61
+ self
62
+ end
63
+
64
+ def not(*args)
65
+ case args.size
66
+ when 0
67
+ ShouldNot.new(@object, @message)
68
+ when 1
69
+ ShouldNot.new(@object, @message).pass(args.first)
70
+ else
71
+ raise ArgumentError, "#not takes zero or one argument(s)."
72
+ end
73
+ end
74
+
75
+ def messaging(message)
76
+ @message = message.to_s
77
+ self
78
+ end
79
+ alias blaming messaging
80
+
81
+ def satisfy(&block)
82
+ assert_block(@message || "satisfy block failed.") {
83
+ yield @object
84
+ }
85
+ end
86
+
87
+ def equal(value)
88
+ assert_equal value, @object, @message
89
+ end
90
+ alias == equal
91
+
92
+ def close(value, delta)
93
+ assert_in_delta value, @object, delta, @message
94
+ end
95
+ deprecated_alias :be_close, :close
96
+
97
+ def be(*value)
98
+ case value.size
99
+ when 0
100
+ self
101
+ when 1
102
+ if CustomShould === value.first
103
+ pass value.first
104
+ else
105
+ assert_same value.first, @object, @message
106
+ end
107
+ else
108
+ raise ArgumentError, "should.be needs zero or one argument"
109
+ end
110
+ end
111
+
112
+ def match(value)
113
+ assert_match value, @object, @message
114
+ end
115
+ alias =~ match
116
+
117
+ def instance_of(klass)
118
+ assert_instance_of klass, @object, @message
119
+ end
120
+ deprecated_alias :be_an_instance_of, :instance_of
121
+
122
+ def kind_of(klass)
123
+ assert_kind_of klass, @object, @message
124
+ end
125
+ deprecated_alias :be_a_kind_of, :kind_of
126
+
127
+ def respond_to(method)
128
+ assert_respond_to @object, method, @message
129
+ end
130
+
131
+ def _raise(*args, &block)
132
+ args = [RuntimeError] if args.empty?
133
+ block ||= @object
134
+ assert_raise(*(args + [@message]), &block)
135
+ end
136
+
137
+ def throw(*args)
138
+ assert_throws(*(args + [@message]), &@object)
139
+ end
140
+
141
+ def nil
142
+ assert_nil @object, @message
143
+ end
144
+ deprecated_alias :be_nil, :nil
145
+
146
+
147
+ def include(value)
148
+ msg = build_message(@message, "<?> expected to include ?, but it didn't.",
149
+ @object, value)
150
+ assert_block(msg) { @object.include?(value) }
151
+ end
152
+
153
+ def >(value)
154
+ assert_operator @object, :>, value, @message
155
+ end
156
+
157
+ def >=(value)
158
+ assert_operator @object, :>=, value, @message
159
+ end
160
+
161
+ def <(value)
162
+ assert_operator @object, :<, value, @message
163
+ end
164
+
165
+ def <=(value)
166
+ assert_operator @object, :<=, value, @message
167
+ end
168
+
169
+ def ===(value)
170
+ assert_operator @object, :===, value, @message
171
+ end
172
+
173
+ def pass(custom)
174
+ _wrap_assertion {
175
+ assert_nothing_raised(Test::Unit::AssertionFailedError,
176
+ @message || custom.failure_message) {
177
+ assert custom.matches?(@object), @message || custom.failure_message
178
+ }
179
+ }
180
+ end
181
+
182
+ def method_missing(name, *args, &block)
183
+ # This will make raise call Kernel.raise, and self.raise call _raise.
184
+ return _raise(*args, &block) if name == :raise
185
+
186
+ if @object.respond_to?("#{name}?")
187
+ assert @object.__send__("#{name}?", *args),
188
+ "#{name}? expected to be true. #{@message}"
189
+ else
190
+ if @object.respond_to?(name)
191
+ assert @object.__send__(name, *args),
192
+ "#{name} expected to be true. #{@message}"
193
+ else
194
+ super
195
+ end
196
+ end
197
+ end
198
+ end
199
+
200
+ class ShouldNot
201
+ include Test::Unit::Assertions
202
+
203
+ def initialize(object, message=nil)
204
+ @object = object
205
+ @message = message
206
+ end
207
+
208
+ def add_assertion
209
+ $TEST_SPEC_TESTCASE && $TEST_SPEC_TESTCASE.__send__(:add_assertion)
210
+ end
211
+
212
+
213
+ def satisfy(&block)
214
+ assert_block(@message || "not.satisfy block succeded.") {
215
+ not yield @object
216
+ }
217
+ end
218
+
219
+ def equal(value)
220
+ assert_not_equal value, @object, @message
221
+ end
222
+ alias == equal
223
+
224
+ def be(*value)
225
+ case value.size
226
+ when 0
227
+ self
228
+ when 1
229
+ if CustomShould === value.first
230
+ pass value.first
231
+ else
232
+ assert_not_same value.first, @object, @message
233
+ end
234
+ else
235
+ Kernel.raise ArgumentError, "should.be needs zero or one argument"
236
+ end
237
+ end
238
+
239
+ def match(value)
240
+ # Icky Regexp check
241
+ assert_no_match value, @object, @message
242
+ end
243
+ alias =~ match
244
+
245
+ def _raise(*args, &block)
246
+ block ||= @object
247
+ assert_nothing_raised(*(args+[@message]), &block)
248
+ end
249
+
250
+ def throw
251
+ assert_nothing_thrown(@message, &@object)
252
+ end
253
+
254
+ def nil
255
+ assert_not_nil @object, @message
256
+ end
257
+
258
+ def be_nil
259
+ warn "Test::Spec::ShouldNot#be_nil is deprecated and will be removed in future versions."
260
+ self.nil
261
+ end
262
+
263
+ def not(*args)
264
+ case args.size
265
+ when 0
266
+ Should.new(@object, @message)
267
+ when 1
268
+ Should.new(@object, @message).pass(args.first)
269
+ else
270
+ raise ArgumentError, "#not takes zero or one argument(s)."
271
+ end
272
+ end
273
+
274
+ def pass(custom)
275
+ _wrap_assertion {
276
+ begin
277
+ assert !custom.matches?(@object), @message || custom.failure_message
278
+ end
279
+ }
280
+ end
281
+
282
+ def method_missing(name, *args, &block)
283
+ # This will make raise call Kernel.raise, and self.raise call _raise.
284
+ return _raise(*args, &block) if name == :raise
285
+
286
+ if @object.respond_to?("#{name}?")
287
+ assert_block("#{name}? expected to be false. #{@message}") {
288
+ not @object.__send__("#{name}?", *args)
289
+ }
290
+ else
291
+ if @object.respond_to?(name)
292
+ assert_block("#{name} expected to be false. #{@message}") {
293
+ not @object.__send__("#{name}", *args)
294
+ }
295
+ else
296
+ super
297
+ end
298
+ end
299
+ end
300
+
301
+ end
302
+
303
+ class CustomShould
304
+ attr_accessor :object
305
+
306
+ def initialize(obj)
307
+ self.object = obj
308
+ end
309
+
310
+ def failure_message
311
+ "#{self.class.name} failed"
312
+ end
313
+
314
+ def matches?(*args, &block)
315
+ assumptions(*args, &block)
316
+ true
317
+ end
318
+
319
+ def assumptions(*args, &block)
320
+ raise NotImplementedError, "you need to supply a #{self.class}#matches? method"
321
+ end
322
+ end
323
+ end
324
+
325
+ class Test::Spec::TestCase
326
+ attr_reader :testcase
327
+ attr_reader :name
328
+ attr_reader :position
329
+
330
+ module InstanceMethods
331
+ def setup # :nodoc:
332
+ $TEST_SPEC_TESTCASE = self
333
+ super
334
+ call_methods_including_parents(:setups)
335
+ end
336
+
337
+ def teardown # :nodoc:
338
+ super
339
+ call_methods_including_parents(:teardowns, :reverse)
340
+ end
341
+
342
+ def before_all
343
+ call_methods_including_parents(:before_all)
344
+ end
345
+
346
+ def after_all
347
+ call_methods_including_parents(:after_all, :reverse)
348
+ end
349
+
350
+ def initialize(name)
351
+ super name
352
+
353
+ # Don't let the default_test clutter up the results and don't
354
+ # flunk if no tests given, either.
355
+ throw :invalid_test if name.to_s == "default_test"
356
+ end
357
+
358
+ def position
359
+ self.class.position
360
+ end
361
+
362
+ def context(*args)
363
+ raise Test::Spec::DefinitionError,
364
+ "context definition is not allowed inside a specify-block"
365
+ end
366
+
367
+ alias :describe :context
368
+
369
+ private
370
+
371
+ def call_methods_including_parents(method, reverse=false, klass=self.class)
372
+ return unless klass
373
+
374
+ if reverse
375
+ klass.send(method).each { |s| instance_eval(&s) }
376
+ call_methods_including_parents(method, reverse, klass.parent)
377
+ else
378
+ call_methods_including_parents(method, reverse, klass.parent)
379
+ klass.send(method).each { |s| instance_eval(&s) }
380
+ end
381
+ end
382
+ end
383
+
384
+ module ClassMethods
385
+ attr_accessor :count
386
+ attr_accessor :name
387
+ attr_accessor :position
388
+ attr_accessor :parent
389
+
390
+ attr_accessor :setups
391
+ attr_accessor :teardowns
392
+
393
+ attr_accessor :before_all
394
+ attr_accessor :after_all
395
+
396
+ # old-style (RSpec <1.0):
397
+
398
+ def context(name, superclass=Test::Unit::TestCase, klass=Test::Spec::TestCase, &block)
399
+ (Test::Spec::CONTEXTS[self.name + "\t" + name] ||= klass.new(name, self, superclass)).add(&block)
400
+ end
401
+
402
+ def xcontext(name, superclass=Test::Unit::TestCase, &block)
403
+ context(name, superclass, Test::Spec::DisabledTestCase, &block)
404
+ end
405
+
406
+ def specify(specname, &block)
407
+ xspecify(specname) and return if block.nil?
408
+
409
+ self.count += 1 # Let them run in order of definition
410
+
411
+ define_method("test_spec {%s} %03d [%s]" % [name, count, specname], &block)
412
+ end
413
+
414
+ def xspecify(specname, &block)
415
+ specify specname do
416
+ @_result.add_disabled(specname)
417
+ end
418
+ end
419
+
420
+ def setup(&block)
421
+ setups << block
422
+ end
423
+
424
+ def teardown(&block)
425
+ teardowns << block
426
+ end
427
+
428
+ def shared_context(name, &block)
429
+ Test::Spec::SHARED_CONTEXTS[self.name + "\t" + name] << block
430
+ end
431
+
432
+ def behaves_like(shared_context)
433
+ if Test::Spec::SHARED_CONTEXTS.include?(shared_context)
434
+ Test::Spec::SHARED_CONTEXTS[shared_context].each { |block|
435
+ instance_eval(&block)
436
+ }
437
+ elsif Test::Spec::SHARED_CONTEXTS.include?(self.name + "\t" + shared_context)
438
+ Test::Spec::SHARED_CONTEXTS[self.name + "\t" + shared_context].each { |block|
439
+ instance_eval(&block)
440
+ }
441
+ else
442
+ raise NameError, "Shared context #{shared_context} not found."
443
+ end
444
+ end
445
+ alias :it_should_behave_like :behaves_like
446
+
447
+ # new-style (RSpec 1.0+):
448
+
449
+ alias :describe :context
450
+ alias :describe_shared :shared_context
451
+ alias :it :specify
452
+ alias :xit :xspecify
453
+
454
+ def before(kind=:each, &block)
455
+ case kind
456
+ when :each
457
+ setup(&block)
458
+ when :all
459
+ before_all << block
460
+ else
461
+ raise ArgumentError, "invalid argument: before(#{kind.inspect})"
462
+ end
463
+ end
464
+
465
+ def after(kind=:each, &block)
466
+ case kind
467
+ when :each
468
+ teardown(&block)
469
+ when :all
470
+ after_all << block
471
+ else
472
+ raise ArgumentError, "invalid argument: after(#{kind.inspect})"
473
+ end
474
+ end
475
+
476
+
477
+ def init(name, position, parent)
478
+ self.position = position
479
+ self.parent = parent
480
+
481
+ if parent
482
+ self.name = parent.name + "\t" + name
483
+ else
484
+ self.name = name
485
+ end
486
+
487
+ self.count = 0
488
+ self.setups = []
489
+ self.teardowns = []
490
+
491
+ self.before_all = []
492
+ self.after_all = []
493
+ end
494
+ end
495
+
496
+ @@POSITION = 0
497
+
498
+ def initialize(name, parent=nil, superclass=Test::Unit::TestCase)
499
+ @testcase = Class.new(superclass) {
500
+ include InstanceMethods
501
+ extend ClassMethods
502
+ }
503
+
504
+ @@POSITION = @@POSITION + 1
505
+ @testcase.init(name, @@POSITION, parent)
506
+ end
507
+
508
+ def add(&block)
509
+ raise ArgumentError, "context needs a block" if block.nil?
510
+
511
+ @testcase.class_eval(&block)
512
+ self
513
+ end
514
+ end
515
+
516
+ (Test::Spec::DisabledTestCase = Test::Spec::TestCase.dup).class_eval do
517
+ alias :test_case_initialize :initialize
518
+
519
+ def initialize(*args, &block)
520
+ test_case_initialize(*args, &block)
521
+ @testcase.instance_eval do
522
+ alias :test_case_specify :specify
523
+
524
+ def specify(specname, &block)
525
+ test_case_specify(specname) { @_result.add_disabled(specname) }
526
+ end
527
+ alias :it :specify
528
+ end
529
+ end
530
+ end
531
+
532
+ class Test::Spec::Disabled < Test::Unit::Failure # :nodoc:
533
+ def initialize(name)
534
+ @name = name
535
+ end
536
+
537
+ def single_character_display
538
+ "D"
539
+ end
540
+
541
+ def short_display
542
+ @name
543
+ end
544
+
545
+ def long_display
546
+ @name + " is disabled"
547
+ end
548
+ end
549
+
550
+ class Test::Spec::Empty < Test::Unit::Failure # :nodoc:
551
+ def initialize(name)
552
+ @name = name
553
+ end
554
+
555
+ def single_character_display
556
+ ""
557
+ end
558
+
559
+ def short_display
560
+ @name
561
+ end
562
+
563
+ def long_display
564
+ @name + " is empty"
565
+ end
566
+ end
567
+
568
+
569
+ # Monkey-patch test/unit to run tests in an optionally specified order.
570
+ module Test::Unit # :nodoc:
571
+ class TestSuite # :nodoc:
572
+ undef run
573
+ def run(result, &progress_block)
574
+ sort!
575
+ yield(STARTED, name)
576
+ @tests.first.before_all if @tests.first.respond_to? :before_all
577
+ @tests.each do |test|
578
+ test.run(result, &progress_block)
579
+ end
580
+ @tests.last.after_all if @tests.last.respond_to? :after_all
581
+ yield(FINISHED, name)
582
+ end
583
+
584
+ def sort!
585
+ @tests = @tests.sort_by { |test|
586
+ test.respond_to?(:position) ? test.position : 0
587
+ }
588
+ end
589
+
590
+ def position
591
+ @tests.first.respond_to?(:position) ? @tests.first.position : 0
592
+ end
593
+ end
594
+
595
+ class TestResult # :nodoc:
596
+ # Records a disabled test.
597
+ def add_disabled(name)
598
+ notify_listeners(FAULT, Test::Spec::Disabled.new(name))
599
+ notify_listeners(CHANGED, self)
600
+ end
601
+ end
602
+ end
603
+
604
+
605
+ # Hide Test::Spec interna in backtraces.
606
+ module Test::Unit::Util::BacktraceFilter # :nodoc:
607
+ TESTSPEC_PREFIX = __FILE__.gsub(/spec\.rb\Z/, '')
608
+
609
+ # Vendor plugins like to be loaded several times, don't recurse
610
+ # infinitely then.
611
+ unless method_defined? "testspec_filter_backtrace"
612
+ alias :testspec_filter_backtrace :filter_backtrace
613
+ end
614
+
615
+ def filter_backtrace(backtrace, prefix=nil)
616
+ if prefix.nil?
617
+ testspec_filter_backtrace(testspec_filter_backtrace(backtrace),
618
+ TESTSPEC_PREFIX)
619
+ else
620
+ testspec_filter_backtrace(backtrace, prefix)
621
+ end
622
+ end
623
+ end
624
+
625
+
626
+ #-- Global helpers
627
+
628
+ class Object
629
+ def should(*args)
630
+ case args.size
631
+ when 0
632
+ Test::Spec::Should.new(self)
633
+ when 1
634
+ Test::Spec::Should.new(self).pass(args.first)
635
+ else
636
+ raise ArgumentError, "Object#should takes zero or one argument(s)."
637
+ end
638
+ end
639
+ end
640
+
641
+ module Kernel
642
+ def context(name, superclass=Test::Unit::TestCase, klass=Test::Spec::TestCase, &block) # :doc:
643
+ (Test::Spec::CONTEXTS[name] ||= klass.new(name, nil, superclass)).add(&block)
644
+ end
645
+
646
+ def xcontext(name, superclass=Test::Unit::TestCase, &block) # :doc:
647
+ context(name, superclass, Test::Spec::DisabledTestCase, &block)
648
+ end
649
+
650
+ def shared_context(name, &block)
651
+ Test::Spec::SHARED_CONTEXTS[name] << block
652
+ end
653
+
654
+ alias :describe :context
655
+ alias :xdescribe :xcontext
656
+ alias :describe_shared :shared_context
657
+
658
+ private :context, :xcontext, :shared_context
659
+ private :describe, :xdescribe, :describe_shared
660
+ end