jordi-xml_struct 0.1.2 → 0.1.3
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.
- data/README.markdown +18 -4
- data/TODO +1 -0
- data/WHATSNEW +9 -1
- data/lib/xml_struct.rb +15 -5
- data/test/test_helper.rb +8 -8
- data/test/vendor/test-spec/README +378 -0
- data/test/vendor/test-spec/ROADMAP +1 -0
- data/test/vendor/test-spec/Rakefile +146 -0
- data/test/vendor/test-spec/SPECS +161 -0
- data/test/vendor/test-spec/TODO +2 -0
- data/test/vendor/test-spec/bin/specrb +107 -0
- data/test/vendor/test-spec/examples/stack.rb +38 -0
- data/test/vendor/test-spec/examples/stack_spec.rb +119 -0
- data/test/vendor/test-spec/lib/test/spec/dox.rb +148 -0
- data/test/vendor/test-spec/lib/test/spec/rdox.rb +25 -0
- data/test/vendor/test-spec/lib/test/spec/should-output.rb +49 -0
- data/test/vendor/test-spec/lib/test/spec/version.rb +8 -0
- data/test/vendor/test-spec/lib/test/spec.rb +660 -0
- data/test/vendor/test-spec/test/spec_dox.rb +39 -0
- data/test/vendor/test-spec/test/spec_flexmock.rb +209 -0
- data/test/vendor/test-spec/test/spec_mocha.rb +104 -0
- data/test/vendor/test-spec/test/spec_nestedcontexts.rb +26 -0
- data/test/vendor/test-spec/test/spec_new_style.rb +80 -0
- data/test/vendor/test-spec/test/spec_should-output.rb +26 -0
- data/test/vendor/test-spec/test/spec_testspec.rb +699 -0
- data/test/vendor/test-spec/test/spec_testspec_order.rb +26 -0
- data/test/vendor/test-spec/test/test_testunit.rb +22 -0
- data/test/xml_struct_test.rb +60 -54
- data/xml_struct.gemspec +41 -11
- metadata +33 -3
@@ -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
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'test/unit/ui/console/testrunner'
|
2
|
+
|
3
|
+
module Test::Unit::UI # :nodoc:
|
4
|
+
module SpecDox # :nodoc:
|
5
|
+
class TestRunner < Test::Unit::UI::Console::TestRunner
|
6
|
+
protected
|
7
|
+
def setup_mediator
|
8
|
+
@mediator = create_mediator(@suite)
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_fault(fault)
|
12
|
+
if fault.kind_of? Test::Spec::Disabled
|
13
|
+
@disabled += 1
|
14
|
+
output_no_nl " (disabled)"
|
15
|
+
elsif fault.kind_of? Test::Spec::Empty
|
16
|
+
@empty += 1
|
17
|
+
output_no_nl " (empty)"
|
18
|
+
else
|
19
|
+
@faults << fault
|
20
|
+
word = fault.class.name[/(.*::)?(.*)/, 2].upcase
|
21
|
+
output_no_nl " (#{word} - #{@faults.size})"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def started(result)
|
26
|
+
@result = result
|
27
|
+
@context = nil
|
28
|
+
@contexts = []
|
29
|
+
@disabled = 0
|
30
|
+
@empty = 0
|
31
|
+
indent 0
|
32
|
+
end
|
33
|
+
|
34
|
+
def finished(elapsed_time)
|
35
|
+
nl
|
36
|
+
output "Finished in #{elapsed_time} seconds."
|
37
|
+
@faults.each_with_index do |fault, index|
|
38
|
+
nl
|
39
|
+
output("%3d) %s" % [index + 1, fault.long_display])
|
40
|
+
end
|
41
|
+
nl
|
42
|
+
output_result
|
43
|
+
end
|
44
|
+
|
45
|
+
def output_result
|
46
|
+
if @disabled > 0
|
47
|
+
disabled = ", #{@disabled} disabled"
|
48
|
+
else
|
49
|
+
disabled = ""
|
50
|
+
end
|
51
|
+
|
52
|
+
if @empty > 0
|
53
|
+
empty = ", #{@empty} empty"
|
54
|
+
else
|
55
|
+
empty = ""
|
56
|
+
end
|
57
|
+
|
58
|
+
r = ("%d specifications#{disabled}#{empty} " +
|
59
|
+
"(%d requirements), %d failures") % [
|
60
|
+
@result.run_count, @result.assertion_count, @result.failure_count]
|
61
|
+
r << ", #{@result.error_count} errors" if @result.error_count > 0
|
62
|
+
output r
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_started(name)
|
66
|
+
return if special_test? name
|
67
|
+
|
68
|
+
contextname, @specname = unmangle name
|
69
|
+
return if contextname.nil? || @specname.nil?
|
70
|
+
|
71
|
+
if @context != contextname
|
72
|
+
@context = contextname
|
73
|
+
|
74
|
+
@old_contexts = @contexts
|
75
|
+
@contexts = @context.split("\t")
|
76
|
+
|
77
|
+
common = 0
|
78
|
+
@contexts.zip(@old_contexts) { |a, b|
|
79
|
+
break if a != b
|
80
|
+
common += 1
|
81
|
+
}
|
82
|
+
|
83
|
+
nl if common == 0
|
84
|
+
|
85
|
+
@contexts[common..-1].each_with_index { |head, i|
|
86
|
+
indent common + i
|
87
|
+
output_heading head
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
@assertions = @result.assertion_count
|
92
|
+
@prevdisabled = @disabled
|
93
|
+
output_item @specname
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_finished(name)
|
97
|
+
return if special_test? name
|
98
|
+
|
99
|
+
# Did any assertion run?
|
100
|
+
if @assertions == @result.assertion_count && @prevdisabled == @disabled
|
101
|
+
add_fault Test::Spec::Empty.new(@specname)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Don't let empty contexts clutter up the output.
|
105
|
+
nl unless name =~ /\Adefault_test\(/
|
106
|
+
end
|
107
|
+
|
108
|
+
def output_no_nl(something, level=NORMAL)
|
109
|
+
@io.write(something) if (output?(level))
|
110
|
+
@io.flush
|
111
|
+
end
|
112
|
+
|
113
|
+
def output_item(item)
|
114
|
+
output_no_nl "#{@prefix}- #{item}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def output_heading(heading)
|
118
|
+
output "#{@prefix}#{heading}"
|
119
|
+
end
|
120
|
+
|
121
|
+
def unmangle(name)
|
122
|
+
if name =~ /\Atest_spec \{(.*?)\} \d+ \[(.*)\]/
|
123
|
+
contextname = $1
|
124
|
+
specname = $2
|
125
|
+
elsif name =~ /test_(.*?)\((.*)\)$/
|
126
|
+
specname = $1
|
127
|
+
contextname = $2
|
128
|
+
|
129
|
+
contextname.gsub!(/^Test\B|\BTest$/, '')
|
130
|
+
specname.gsub!(/_/, ' ')
|
131
|
+
else
|
132
|
+
contextname = specname = nil
|
133
|
+
end
|
134
|
+
|
135
|
+
[contextname, specname]
|
136
|
+
end
|
137
|
+
|
138
|
+
def indent(depth)
|
139
|
+
@indent = depth
|
140
|
+
@prefix = " " * depth
|
141
|
+
end
|
142
|
+
|
143
|
+
def special_test?(name)
|
144
|
+
name =~ /\Atest_spec \{.*?\} (-1 BEFORE|AFTER) ALL\(/
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test/spec/dox'
|
2
|
+
|
3
|
+
module Test::Unit::UI # :nodoc:
|
4
|
+
module RDox # :nodoc:
|
5
|
+
class TestRunner < Test::Unit::UI::SpecDox::TestRunner
|
6
|
+
def output_heading(heading)
|
7
|
+
output "#{@headprefix} #{heading}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def output_item(item)
|
11
|
+
output_no_nl "* #{item}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def finished(elapsed_time)
|
15
|
+
nl
|
16
|
+
output_result
|
17
|
+
end
|
18
|
+
|
19
|
+
def indent(depth)
|
20
|
+
@prefix = ""
|
21
|
+
@headprefix = "==" + "=" * depth
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Code adapted from rs, written by Eero Saynatkari.
|
2
|
+
require 'fileutils'
|
3
|
+
require 'tmpdir'
|
4
|
+
|
5
|
+
class Test::Spec::Should
|
6
|
+
# Captures output from the IO given as
|
7
|
+
# the second argument (STDIN by default)
|
8
|
+
# and matches it against a String or
|
9
|
+
# Regexp given as the first argument.
|
10
|
+
def output(expected, to = STDOUT)
|
11
|
+
# Store the old stream
|
12
|
+
old_to = to.dup
|
13
|
+
|
14
|
+
# Obtain a filehandle to replace (works with Readline)
|
15
|
+
to.reopen File.open(File.join(Dir.tmpdir, "should_output_#{$$}"), "w+")
|
16
|
+
|
17
|
+
# Execute
|
18
|
+
@object.call
|
19
|
+
|
20
|
+
# Restore
|
21
|
+
out = to.dup
|
22
|
+
to.reopen old_to
|
23
|
+
|
24
|
+
# Grab the data
|
25
|
+
out.rewind
|
26
|
+
output = out.read
|
27
|
+
|
28
|
+
# Match up
|
29
|
+
case expected
|
30
|
+
when Regexp
|
31
|
+
output.should.match expected
|
32
|
+
else
|
33
|
+
output.should.equal expected
|
34
|
+
end # case expected
|
35
|
+
|
36
|
+
# Clean up
|
37
|
+
ensure
|
38
|
+
out.close
|
39
|
+
|
40
|
+
# STDIO redirection will break else
|
41
|
+
begin
|
42
|
+
to.seek 0, IO::SEEK_END
|
43
|
+
rescue Errno::ESPIPE
|
44
|
+
rescue Errno::EPIPE
|
45
|
+
end
|
46
|
+
|
47
|
+
FileUtils.rm_f out.path
|
48
|
+
end # output
|
49
|
+
end # Test::Spec::Should
|
@@ -0,0 +1,660 @@
|
|
1
|
+
#
|
2
|
+
# test/spec -- a BDD interface for Test::Unit
|
3
|
+
#
|
4
|
+
# Copyright (C) 2006, 2007, 2008 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
|
+
raise ArgumentError, "specify needs a block" 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
|