test-spec 0.2
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/History.txt +0 -0
- data/Manifest.txt +11 -0
- data/README.txt +206 -0
- data/Rakefile +137 -0
- data/lib/test-spec.rb +2 -0
- data/lib/test-spec/test/spec.rb +368 -0
- data/lib/test-spec/test/spec/dox.rb +114 -0
- data/lib/test-spec/test/spec/rdox.rb +26 -0
- data/lib/test-spec/test/spec/should-output.rb +48 -0
- data/lib/test-spec/version.rb +9 -0
- data/setup.rb +1585 -0
- metadata +73 -0
data/History.txt
ADDED
File without changes
|
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
= test/spec, a BDD interface for Test::Unit
|
2
|
+
|
3
|
+
Copyright (C) 2006 Christian Neukirchen <mailto:chneukirchen@gmail.com>
|
4
|
+
|
5
|
+
|
6
|
+
== What is test/spec?
|
7
|
+
|
8
|
+
test/spec layers an RSpec-inspired interface on top of Test::Unit, so
|
9
|
+
you can mix TDD and BDD (Behavior-Driven Development).
|
10
|
+
|
11
|
+
test/spec is a clean-room implementation that maps most kinds of
|
12
|
+
Test::Unit assertions to a `should'-like syntax.
|
13
|
+
|
14
|
+
Consider this Test::Unit test case:
|
15
|
+
|
16
|
+
class TestFoo < Test::Unit::TestCase
|
17
|
+
def test_should_bar
|
18
|
+
assert_equal 5, 2 + 3
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
In test/spec, it looks like this:
|
23
|
+
|
24
|
+
require 'test/spec'
|
25
|
+
|
26
|
+
context "Foo" do
|
27
|
+
specify "should bar" do
|
28
|
+
(2 + 3).should.equal 5
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
test/spec does not include a mocking/stubbing-framework; use whichever
|
33
|
+
you like to. test/spec has been tested successfully with FlexMock and
|
34
|
+
Mocha.
|
35
|
+
|
36
|
+
test/spec has no dependencies outside Ruby 1.8.
|
37
|
+
|
38
|
+
|
39
|
+
== Mixing test/spec and test/unit
|
40
|
+
|
41
|
+
test/spec and Test::Unit contexts/test cases can be intermixed freely,
|
42
|
+
run in the same test and live in the same files. You can just add them
|
43
|
+
to your Rake::TestTask, too. test/spec allows you to leverage your
|
44
|
+
full existing Test::Unit infrastructure.
|
45
|
+
|
46
|
+
test/spec does not change Test::Unit with the exception of
|
47
|
+
monkey-patching Test::Unit::TestSuite to order the test cases before
|
48
|
+
running them. (This should not do any harm, but if you know a way
|
49
|
+
around it, please tell me.)
|
50
|
+
|
51
|
+
test/spec adds two global methods, Object#should and Kernel.context.
|
52
|
+
|
53
|
+
You can use <tt>assert_*</tt> freely in specify-blocks; Object#should
|
54
|
+
works in plain Test::Unit test cases, too, but they will not be counted.
|
55
|
+
|
56
|
+
|
57
|
+
== Wrapped assertions
|
58
|
+
|
59
|
+
+assert_equal+:: <tt>should.equal</tt>, <tt>should ==</tt>
|
60
|
+
+assert_not_equal+:: <tt>should.not.equal</tt>, <tt>should.not ==</tt>
|
61
|
+
+assert_same+:: <tt>should.be</tt>
|
62
|
+
+assert_not_same+:: <tt>should.not.be</tt>
|
63
|
+
+assert_nil+:: <tt>should.be.nil</tt>
|
64
|
+
+assert_not_nil+:: <tt>should.not.be.nil</tt>
|
65
|
+
+assert_in_delta+:: <tt>should.be.close</tt>
|
66
|
+
+assert_match+:: <tt>should.match</tt>, <tt>should =~</tt>
|
67
|
+
+assert_no_match+:: <tt>should.not.match</tt>, <tt>should.not =~</tt>
|
68
|
+
|
69
|
+
+assert_instance_of+:: <tt>should.be.an.instance_of</tt>
|
70
|
+
+assert_kind_of+:: <tt>should.be.a.kind_of</tt>
|
71
|
+
+assert_respond_to+:: <tt>should.respond_to</tt>
|
72
|
+
+assert_raise+:: <tt>should.raise</tt>
|
73
|
+
+assert_nothing_raised+:: <tt>should.not.raise</tt>
|
74
|
+
+assert_throws+:: <tt>should.throw</tt>
|
75
|
+
+assert_nothing_thrown+:: <tt>should.not.throw</tt>
|
76
|
+
|
77
|
+
+assert_block+:: <tt>should.satisfy</tt>
|
78
|
+
|
79
|
+
(+a+, +an+ and +be+ without arguments are optional and no-ops.)
|
80
|
+
|
81
|
+
|
82
|
+
== Additional assertions
|
83
|
+
|
84
|
+
These assertions are not included in Test::Unit, but have been added
|
85
|
+
to test/spec for convenience:
|
86
|
+
|
87
|
+
* <tt>should.not.satisfy</tt>
|
88
|
+
* <tt>should.include</tt>
|
89
|
+
* <tt>a.should.</tt>_predicate_ (works like <tt>assert
|
90
|
+
a.</tt>_predicate_<tt>?</tt>)
|
91
|
+
* <tt>a.should.be </tt>_operator_ (where _operator_ is one of <tt>></tt>, <tt>>=</tt>, <tt><</tt>, <tt><=</tt> or <tt>===</tt>)
|
92
|
+
* <tt>should.output</tt> (require test/spec/should-output)
|
93
|
+
|
94
|
+
If you write an useful general-purpose assertion, I'd like to hear of
|
95
|
+
it and may add it to the test/spec distribution.
|
96
|
+
|
97
|
+
|
98
|
+
== SpecDox and RDox
|
99
|
+
|
100
|
+
test/spec adds two additional test runners to Test::Unit, based on the
|
101
|
+
console runner but with a different output format.
|
102
|
+
|
103
|
+
SpecDox, run with <tt>--runner=specdox</tt> (or <tt>-rs</tt>) looks
|
104
|
+
like RSpec's output:
|
105
|
+
|
106
|
+
should.output
|
107
|
+
- works for print
|
108
|
+
- works for puts
|
109
|
+
- works with readline
|
110
|
+
|
111
|
+
RDox, run with <tt>--runner=rdox</tt> (or <tt>-rr</tt>) can be
|
112
|
+
included for RDoc documentation (e.g. see SPECS):
|
113
|
+
|
114
|
+
== should.output
|
115
|
+
* works for print
|
116
|
+
* works for puts
|
117
|
+
* works with readline
|
118
|
+
|
119
|
+
SpecDox and RDox work for Test::Unit too:
|
120
|
+
|
121
|
+
$ ruby -r test/spec test/testunit/test_testresult.rb -rs
|
122
|
+
|
123
|
+
Test::Unit::TC_TestResult
|
124
|
+
- fault notification
|
125
|
+
- passed?
|
126
|
+
- result changed notification
|
127
|
+
|
128
|
+
Finished in 0.106647 seconds.
|
129
|
+
|
130
|
+
3 specifications (30 requirements), 0 failures
|
131
|
+
|
132
|
+
|
133
|
+
== specrb
|
134
|
+
|
135
|
+
Since version 0.2, test/spec features a standalone test runner called
|
136
|
+
specrb. specrb is like an extended version of testrb, Test::Unit's
|
137
|
+
test runner, but has additional options. It can be used for
|
138
|
+
plain Test::Unit suites, too.
|
139
|
+
|
140
|
+
$ specrb -a -s -n should.output
|
141
|
+
|
142
|
+
should.output
|
143
|
+
- works for print
|
144
|
+
- works for puts
|
145
|
+
- works with readline
|
146
|
+
|
147
|
+
Finished in 0.162571 seconds.
|
148
|
+
|
149
|
+
3 specifications (6 requirements), 0 failures
|
150
|
+
|
151
|
+
Run <tt>specrb --help</tt> for the usage.
|
152
|
+
|
153
|
+
|
154
|
+
== History
|
155
|
+
|
156
|
+
* September 29th, 2006: First public release 0.1.
|
157
|
+
|
158
|
+
* October 18th, 2006: Second public release 0.2.
|
159
|
+
* Better, module-based implementation
|
160
|
+
* Official support for FlexMock and Mocha
|
161
|
+
* More robust Should#output
|
162
|
+
* Should#_operator_
|
163
|
+
* Nested contexts
|
164
|
+
* Standalone test/spec runner, specrb
|
165
|
+
|
166
|
+
|
167
|
+
== Contact
|
168
|
+
|
169
|
+
Please mail bugs, suggestions and patches to
|
170
|
+
<mailto:chneukirchen@gmail.com>.
|
171
|
+
|
172
|
+
Darcs repository ("darcs send" is welcome for patches):
|
173
|
+
http://chneukirchen.org/repos/testspec
|
174
|
+
|
175
|
+
|
176
|
+
== Thanks to
|
177
|
+
|
178
|
+
* Eero Saynatkari for writing <tt>should.output</tt>.
|
179
|
+
* Thomas Fuchs for script.aculo.us BDD testing which convinced me.
|
180
|
+
* Dave Astels for BDD.
|
181
|
+
* The RSpec team for API inspiration.
|
182
|
+
* Nathaniel Talbott for Test::Unit.
|
183
|
+
|
184
|
+
|
185
|
+
== Copying
|
186
|
+
|
187
|
+
Copyright (C) 2006 Christian Neukirchen <http://purl.org/net/chneukirchen>
|
188
|
+
|
189
|
+
test/spec is licensed under the same terms as Ruby itself.
|
190
|
+
|
191
|
+
Please mail bugs, feature requests or patches to the mail addresses
|
192
|
+
found above or use IRC[irc://freenode.net/#ruby-lang] to contact the
|
193
|
+
developer.
|
194
|
+
|
195
|
+
|
196
|
+
== Links
|
197
|
+
|
198
|
+
Behavior-Driven Development:: <http://behaviour-driven.org/>
|
199
|
+
RSpec:: <http://rspec.rubyforge.org/>
|
200
|
+
script.aculo.us testing:: <http://mir.aculo.us/articles/2006/08/29/bdd-style-javascript-testing>
|
201
|
+
|
202
|
+
FlexMock:: <http://onestepback.org/software/flexmock/>
|
203
|
+
Mocha:: <http://mocha.rubyforge.org/>
|
204
|
+
|
205
|
+
Christian Neukirchen:: <http://chneukirchen.org/>
|
206
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
# Rakefile for testspec. -*-ruby-*-
|
2
|
+
#
|
3
|
+
#
|
4
|
+
#
|
5
|
+
require 'rubygems'
|
6
|
+
require 'rake'
|
7
|
+
require 'rake/clean'
|
8
|
+
require 'rake/testtask'
|
9
|
+
require 'rake/packagetask'
|
10
|
+
require 'rake/gempackagetask'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
require 'rake/contrib/rubyforgepublisher'
|
13
|
+
require 'fileutils'
|
14
|
+
require 'hoe'
|
15
|
+
include FileUtils
|
16
|
+
require File.join(File.dirname(__FILE__), 'lib', 'test-spec', 'version')
|
17
|
+
|
18
|
+
AUTHOR = "Christian Neukirchen" # can also be an array of Authors
|
19
|
+
EMAIL = "chneukirchen@gmail.com"
|
20
|
+
DESCRIPTION = "Behaviour Driven Development with Test::Unit"
|
21
|
+
GEM_NAME = "test-spec" # what ppl will type to install your gem
|
22
|
+
RUBYFORGE_PROJECT = "test-spec" # The unix name for your project
|
23
|
+
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
24
|
+
RELEASE_TYPES = %w( gem ) # can use: gem, tar, zip
|
25
|
+
|
26
|
+
|
27
|
+
NAME = "test-spec"
|
28
|
+
REV = nil # UNCOMMENT IF REQUIRED: File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
|
29
|
+
VERS = ENV['VERSION'] || (TestSpec::VERSION::STRING + (REV ? ".#{REV}" : ""))
|
30
|
+
CLEAN.include ['**/.*.sw?', '*.gem', '.config']
|
31
|
+
RDOC_OPTS = ['--quiet', '--title', "test_spec documentation",
|
32
|
+
"--opname", "index.html",
|
33
|
+
"--line-numbers",
|
34
|
+
"--main", "README",
|
35
|
+
"--inline-source"]
|
36
|
+
|
37
|
+
# Generate all the Rake tasks
|
38
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
39
|
+
hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
40
|
+
p.author = AUTHOR
|
41
|
+
p.description = DESCRIPTION
|
42
|
+
p.email = EMAIL
|
43
|
+
p.summary = DESCRIPTION
|
44
|
+
p.url = HOMEPATH
|
45
|
+
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
46
|
+
p.test_globs = ["test/**/*_test.rb"]
|
47
|
+
p.clean_globs = CLEAN #An array of file patterns to delete on clean.
|
48
|
+
p.extra_deps = ['flexmock','>= 0.4.3'],['mocha','>= 0.3.2']
|
49
|
+
# == Optional
|
50
|
+
#p.changes - A description of the release's latest changes.
|
51
|
+
#p.spec_extras - A hash of extra values to set in the gemspec.
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
desc "Run all the tests"
|
56
|
+
task :default => [:test]
|
57
|
+
|
58
|
+
desc "Do predistribution stuff"
|
59
|
+
task :predist => [:chmod, :changelog, :rdoc]
|
60
|
+
|
61
|
+
|
62
|
+
desc "Run all the tests"
|
63
|
+
task :test => :chmod do
|
64
|
+
ruby "bin/specrb -Ilib:test -w #{ENV['TEST'] || '-a'} #{ENV['TESTOPTS']}"
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "Make an archive as .tar.gz"
|
68
|
+
task :dist => :test do
|
69
|
+
system "export DARCS_REPO=#{File.expand_path "."}; " +
|
70
|
+
"darcs dist -d testspec#{get_darcs_tree_version}"
|
71
|
+
end
|
72
|
+
|
73
|
+
desc "Make binaries executable"
|
74
|
+
task :chmod do
|
75
|
+
Dir["bin/*"].each { |binary| File.chmod(0775, binary) }
|
76
|
+
end
|
77
|
+
|
78
|
+
desc "Generate a ChangeLog"
|
79
|
+
task :changelog do
|
80
|
+
system "darcs changes --repo=#{ENV["DARCS_REPO"] || "."} >ChangeLog"
|
81
|
+
end
|
82
|
+
|
83
|
+
desc "Generate RDoc documentation"
|
84
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
85
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
86
|
+
rdoc.rdoc_dir = "rdoc"
|
87
|
+
rdoc.rdoc_files.include 'README'
|
88
|
+
rdoc.rdoc_files.include 'ROADMAP'
|
89
|
+
rdoc.rdoc_files.include 'SPECS'
|
90
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
91
|
+
end
|
92
|
+
task :rdoc => "SPECS"
|
93
|
+
|
94
|
+
desc "Generate RDox"
|
95
|
+
task "SPECS" do
|
96
|
+
ruby "bin/specrb -Ilib:test -a --rdox >SPECS"
|
97
|
+
end
|
98
|
+
|
99
|
+
begin
|
100
|
+
require 'rcov/rcovtask'
|
101
|
+
|
102
|
+
Rcov::RcovTask.new do |t|
|
103
|
+
t.test_files = FileList['test/spec_*.rb'] + ['--', '-rs'] # evil
|
104
|
+
t.verbose = true # uncomment to see the executed command
|
105
|
+
t.rcov_opts = ["--text-report", "--include-file", "^lib\\|^test"]
|
106
|
+
end
|
107
|
+
rescue LoadError
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
# Helper to retrieve the "revision number" of the darcs tree.
|
112
|
+
def get_darcs_tree_version
|
113
|
+
return "" unless File.directory? "_darcs"
|
114
|
+
|
115
|
+
changes = `darcs changes`
|
116
|
+
count = 0
|
117
|
+
tag = "0.0"
|
118
|
+
|
119
|
+
changes.each("\n\n") { |change|
|
120
|
+
head, title, desc = change.split("\n", 3)
|
121
|
+
|
122
|
+
if title =~ /^ \*/
|
123
|
+
# Normal change.
|
124
|
+
count += 1
|
125
|
+
elsif title =~ /tagged (.*)/
|
126
|
+
# Tag. We look for these.
|
127
|
+
tag = $1
|
128
|
+
break
|
129
|
+
else
|
130
|
+
warn "Unparsable change: #{change}"
|
131
|
+
end
|
132
|
+
}
|
133
|
+
|
134
|
+
"-" + tag + "." + count.to_s
|
135
|
+
end
|
136
|
+
|
137
|
+
|
data/lib/test-spec.rb
ADDED
@@ -0,0 +1,368 @@
|
|
1
|
+
#
|
2
|
+
# test/spec -- a BDD interface for Test::Unit
|
3
|
+
#
|
4
|
+
# Copyright (C) 2006 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
|
+
VERSION = "0.1"
|
28
|
+
|
29
|
+
CONTEXTS = {}
|
30
|
+
|
31
|
+
class DefinitionError < StandardError
|
32
|
+
end
|
33
|
+
|
34
|
+
class Should
|
35
|
+
include Test::Unit::Assertions
|
36
|
+
|
37
|
+
def initialize(object)
|
38
|
+
@object = object
|
39
|
+
end
|
40
|
+
|
41
|
+
$TEST_SPEC_TESTCASE = nil
|
42
|
+
def add_assertion
|
43
|
+
$TEST_SPEC_TESTCASE && $TEST_SPEC_TESTCASE.__send__(:add_assertion)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def an
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def a
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def not
|
56
|
+
ShouldNot.new(@object)
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
def satisfy(&block)
|
61
|
+
assert_block("satisfy block failed.") {
|
62
|
+
yield @object
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def equal(value)
|
67
|
+
assert_equal value, @object
|
68
|
+
end
|
69
|
+
alias == equal
|
70
|
+
|
71
|
+
def close(value, delta)
|
72
|
+
assert_in_delta value, @object, delta
|
73
|
+
end
|
74
|
+
alias be_close close
|
75
|
+
|
76
|
+
def be(*value)
|
77
|
+
case value.size
|
78
|
+
when 0
|
79
|
+
self
|
80
|
+
when 1
|
81
|
+
assert_same value.first, @object
|
82
|
+
else
|
83
|
+
raise ArgumentError, "should.be needs zero or one argument"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def match(value)
|
88
|
+
assert_match value, @object
|
89
|
+
end
|
90
|
+
alias =~ match
|
91
|
+
|
92
|
+
def instance_of(klass)
|
93
|
+
assert_instance_of klass, @object
|
94
|
+
end
|
95
|
+
alias be_an_instance_of instance_of
|
96
|
+
|
97
|
+
def kind_of(klass)
|
98
|
+
assert_kind_of klass, @object
|
99
|
+
end
|
100
|
+
alias be_a_kind_of kind_of
|
101
|
+
|
102
|
+
def respond_to(method)
|
103
|
+
assert_respond_to @object, method
|
104
|
+
end
|
105
|
+
|
106
|
+
def _raise(*args)
|
107
|
+
args = [RuntimeError] if args.empty?
|
108
|
+
assert_raise(*args, &@object)
|
109
|
+
end
|
110
|
+
|
111
|
+
def throw(*args)
|
112
|
+
assert_throws(*args, &@object)
|
113
|
+
end
|
114
|
+
|
115
|
+
def nil
|
116
|
+
assert_nil @object
|
117
|
+
end
|
118
|
+
alias be_nil nil
|
119
|
+
|
120
|
+
|
121
|
+
def include(value)
|
122
|
+
msg = build_message(nil, "<?> expected to include ?, but it didn't.",
|
123
|
+
@object, value)
|
124
|
+
assert_block(msg) { @object.include?(value) }
|
125
|
+
end
|
126
|
+
|
127
|
+
def >(value)
|
128
|
+
assert_operator @object, :>, value
|
129
|
+
end
|
130
|
+
|
131
|
+
def >=(value)
|
132
|
+
assert_operator @object, :>=, value
|
133
|
+
end
|
134
|
+
|
135
|
+
def <(value)
|
136
|
+
assert_operator @object, :<, value
|
137
|
+
end
|
138
|
+
|
139
|
+
def <=(value)
|
140
|
+
assert_operator @object, :<=, value
|
141
|
+
end
|
142
|
+
|
143
|
+
def ===(value)
|
144
|
+
assert_operator @object, :===, value
|
145
|
+
end
|
146
|
+
|
147
|
+
def method_missing(name, *args)
|
148
|
+
# This will make raise call Kernel.raise, and self.raise call _raise.
|
149
|
+
return _raise(*args) if name == :raise
|
150
|
+
|
151
|
+
if @object.respond_to?("#{name}?")
|
152
|
+
assert @object.__send__("#{name}?", *args),
|
153
|
+
"#{name}? expected to be true."
|
154
|
+
else
|
155
|
+
super
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class ShouldNot
|
161
|
+
include Test::Unit::Assertions
|
162
|
+
|
163
|
+
def initialize(object)
|
164
|
+
@object = object
|
165
|
+
end
|
166
|
+
|
167
|
+
def equal(value)
|
168
|
+
assert_not_equal value, @object
|
169
|
+
end
|
170
|
+
alias == equal
|
171
|
+
|
172
|
+
def be(*value)
|
173
|
+
case value.size
|
174
|
+
when 0
|
175
|
+
self
|
176
|
+
when 1
|
177
|
+
assert_not_same value.first, @object
|
178
|
+
else
|
179
|
+
Kernel.raise ArgumentError, "should.be needs zero or one argument"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def match(value)
|
184
|
+
# Icky Regexp check
|
185
|
+
assert_no_match value, @object
|
186
|
+
end
|
187
|
+
alias =~ match
|
188
|
+
|
189
|
+
def _raise(*args)
|
190
|
+
assert_nothing_raised(*args, &@object)
|
191
|
+
end
|
192
|
+
|
193
|
+
def throw
|
194
|
+
assert_nothing_thrown(&@object)
|
195
|
+
end
|
196
|
+
|
197
|
+
def nil
|
198
|
+
assert_not_nil @object
|
199
|
+
end
|
200
|
+
alias be_nil nil
|
201
|
+
|
202
|
+
|
203
|
+
def not
|
204
|
+
Should.new(@object)
|
205
|
+
end
|
206
|
+
|
207
|
+
|
208
|
+
def method_missing(name, *args)
|
209
|
+
# This will make raise call Kernel.raise, and self.raise call _raise.
|
210
|
+
return _raise(*args) if name == :raise
|
211
|
+
|
212
|
+
if @object.respond_to?("#{name}?")
|
213
|
+
assert_block("#{name}? expected to be false.") {
|
214
|
+
not @object.__send__("#{name}?", *args)
|
215
|
+
}
|
216
|
+
else
|
217
|
+
super
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
class Test::Spec::TestCase
|
225
|
+
attr_reader :testcase
|
226
|
+
attr_reader :name
|
227
|
+
attr_reader :position
|
228
|
+
|
229
|
+
module InstanceMethods
|
230
|
+
def setup # :nodoc:
|
231
|
+
$TEST_SPEC_TESTCASE = self
|
232
|
+
super
|
233
|
+
self.class.setups.each { |s| instance_eval(&s) }
|
234
|
+
end
|
235
|
+
|
236
|
+
def teardown # :nodoc:
|
237
|
+
super
|
238
|
+
self.class.teardowns.each { |t| instance_eval(&t) }
|
239
|
+
end
|
240
|
+
|
241
|
+
def initialize(name)
|
242
|
+
super name
|
243
|
+
|
244
|
+
# Don't let the default_test clutter up the results and don't
|
245
|
+
# flunk if no tests given, either.
|
246
|
+
throw :invalid_test if name == :default_test
|
247
|
+
end
|
248
|
+
|
249
|
+
def position
|
250
|
+
self.class.position
|
251
|
+
end
|
252
|
+
|
253
|
+
def context(*args)
|
254
|
+
raise Test::Spec::DefinitionError,
|
255
|
+
"context definition is not allowed inside a specify-block"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
module ClassMethods
|
260
|
+
attr_accessor :count
|
261
|
+
attr_accessor :name
|
262
|
+
attr_accessor :position
|
263
|
+
attr_accessor :parent
|
264
|
+
|
265
|
+
attr_accessor :setups
|
266
|
+
attr_accessor :teardowns
|
267
|
+
|
268
|
+
def context(name, &block)
|
269
|
+
(Test::Spec::CONTEXTS[self.name + "\t" + name] ||=
|
270
|
+
Test::Spec::TestCase.new(name, self)).add(&block)
|
271
|
+
end
|
272
|
+
|
273
|
+
def specify(specname, &block)
|
274
|
+
raise ArgumentError, "specify needs a block" if block.nil?
|
275
|
+
|
276
|
+
self.count += 1 # Let them run in order of definition
|
277
|
+
|
278
|
+
# TODO Changed by Jean-Michel
|
279
|
+
# define_method("test_%03d: %s" % [count, specname], &block)
|
280
|
+
define_method("test_spec {%s} %03d [%s]" % [name, count, specname], &block)
|
281
|
+
end
|
282
|
+
|
283
|
+
def setup(&block)
|
284
|
+
setups << block
|
285
|
+
end
|
286
|
+
|
287
|
+
def teardown(&block)
|
288
|
+
teardowns << block
|
289
|
+
end
|
290
|
+
|
291
|
+
def init(name, position, parent)
|
292
|
+
self.position = position
|
293
|
+
self.parent = parent
|
294
|
+
|
295
|
+
if parent
|
296
|
+
self.name = parent.name + "\t" + name
|
297
|
+
else
|
298
|
+
self.name = name
|
299
|
+
end
|
300
|
+
|
301
|
+
self.count = 0
|
302
|
+
self.setups = []
|
303
|
+
self.teardowns = []
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
@@POSITION = 0
|
308
|
+
|
309
|
+
def initialize(name, parent=nil)
|
310
|
+
@testcase = Class.new(Test::Unit::TestCase) {
|
311
|
+
include InstanceMethods
|
312
|
+
extend ClassMethods
|
313
|
+
}
|
314
|
+
|
315
|
+
@@POSITION = @@POSITION + 1
|
316
|
+
@testcase.init(name, @@POSITION, parent)
|
317
|
+
end
|
318
|
+
|
319
|
+
def add(&block)
|
320
|
+
raise ArgumentError, "context needs a block" if block.nil?
|
321
|
+
|
322
|
+
@testcase.class_eval(&block)
|
323
|
+
self
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
|
328
|
+
# Monkey-patch test/unit to run tests in an optionally specified order.
|
329
|
+
module Test::Unit # :nodoc:
|
330
|
+
class TestSuite # :nodoc:
|
331
|
+
undef run
|
332
|
+
def run(result, &progress_block)
|
333
|
+
sort!
|
334
|
+
yield(STARTED, name)
|
335
|
+
@tests.each do |test|
|
336
|
+
test.run(result, &progress_block)
|
337
|
+
end
|
338
|
+
yield(FINISHED, name)
|
339
|
+
end
|
340
|
+
|
341
|
+
def sort!
|
342
|
+
@tests = @tests.sort_by { |test|
|
343
|
+
test.respond_to?(:position) ? test.position : 0
|
344
|
+
}
|
345
|
+
end
|
346
|
+
|
347
|
+
def position
|
348
|
+
@tests.first.respond_to?(:position) ? @tests.first.position : 0
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
|
354
|
+
# Global helpers
|
355
|
+
|
356
|
+
class Object
|
357
|
+
def should
|
358
|
+
Test::Spec::Should.new(self)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
module Kernel
|
363
|
+
def context(name, &block)
|
364
|
+
(Test::Spec::CONTEXTS[name] ||= Test::Spec::TestCase.new(name)).add(&block)
|
365
|
+
end
|
366
|
+
|
367
|
+
private :context
|
368
|
+
end
|