minitest 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ Autotest.add_hook :initialize do |at|
6
+ at.extra_class_map["MiniSpec"] = "test/test_mini_spec.rb"
7
+ at.extra_class_map["TestMiniTestTestCase"] = "test/test_mini_test.rb"
8
+
9
+ at.add_exception 'coverage.info'
10
+ at.add_exception 'coverage'
11
+ end
12
+
13
+ require 'autotest/rcov'
14
+ Autotest::RCov.command = 'rcov_info'
15
+
@@ -0,0 +1,114 @@
1
+ === 1.3.0 / 2008-10-09
2
+
3
+ * 2 major enhancements:
4
+
5
+ * renamed to minitest and pulled out test/unit compatibility.
6
+ * mini/test.rb is now minitest/unit.rb, everything else maps directly.
7
+
8
+ * 12 minor enhancements:
9
+
10
+ * assert_match now checks that act can call =~ and converts exp to a
11
+ regexp only if needed.
12
+ * Added assert_send... seems useless to me tho.
13
+ * message now forces to string... ruby-core likes to pass classes and arrays :(
14
+ * Added -v handling and switched to @verbose from $DEBUG.
15
+ * Verbose output now includes test class name and adds a sortable running time!
16
+ * Switched message generation into procs for message deferment.
17
+ * Added skip and renamed fail to flunk.
18
+ * Improved output failure messages for assert_instance_of, assert_kind_of
19
+ * Improved output for assert_respond_to, assert_same.
20
+ * at_exit now exits false instead of errors+failures.
21
+ * Made the tests happier and more readable imhfo.
22
+ * Switched index(s) == 0 to rindex(s, 0) on nobu's suggestion. Faster.
23
+
24
+ * 5 bug fixes:
25
+
26
+ * 1.9: Added encoding normalization in mu_pp.
27
+ * 1.9: Fixed backtrace filtering (BTs are expanded now)
28
+ * Added back exception_details to assert_raises. DOH.
29
+ * Fixed shadowed variable in mock.rb
30
+ * Fixed stupid muscle memory message bug in assert_send.
31
+
32
+ === 1.2.1 / 2008-06-10
33
+
34
+ * 7 minor enhancements:
35
+
36
+ * Added deprecations everywhere in test/unit.
37
+ * Added test_order to TestCase. :random on mini, :sorted on test/unit (for now).
38
+ * Big cleanup in test/unit for rails. Thanks Jeremy Kemper!
39
+ * Minor readability cleanup.
40
+ * Pushed setup/run/teardown down to testcase allowing specialized testcases.
41
+ * Removed pp. Tests run 2x faster. :/
42
+ * Renamed deprecation methods and moved to test/unit/deprecate.rb.
43
+
44
+ === 1.2.0 / 2008-06-09
45
+
46
+ * 2 major enhancements:
47
+
48
+ * Added Mini::Spec.
49
+ * Added Mini::Mock. Thanks Steven Baker!!
50
+
51
+ * 23 minor enhancements:
52
+
53
+ * Added bin/use_miniunit to make it easy to test out miniunit.
54
+ * Added -n filtering, thanks to Phil Hagelberg!
55
+ * Added args argument to #run, takes ARGV from at_exit.
56
+ * Added test name output if $DEBUG.
57
+ * Added a refute (was deny) for every assert.
58
+ * Added capture_io and a bunch of nice assertions from zentest.
59
+ * Added deprecation mechanism for assert_no/not methods to test/unit/assertions.
60
+ * Added pp output when available.
61
+ * Added tests for all assertions. Pretty much maxed out coverage.
62
+ * Added tests to verify consistency and good naming.
63
+ * Aliased and deprecated all ugly assertions.
64
+ * Cleaned out test/unit. Moved autorun there.
65
+ * Code cleanup to make extensions easier. Thanks Chad!
66
+ * Got spec args reversed in all but a couple assertions. Much more readable.
67
+ * Improved error messages across the board. Adds your message to the default.
68
+ * Moved into Mini namespace, renamed to Mini::Test and Mini::Spec.
69
+ * Pulled the assertions into their own module...
70
+ * Removed as much code as I could while still maintaining full functionality.
71
+ * Moved filter_backtrace into MiniTest.
72
+ * Removed MiniTest::Unit::run. Unnecessary.
73
+ * Removed location_of_failure. Unnecessary.
74
+ * Rewrote test/unit's filter_backtrace. Flog from 37.0 to 18.1
75
+ * Removed assert_send. Google says it is never used.
76
+ * Renamed MiniTest::Unit.autotest to #run.
77
+ * Renamed deny to refute.
78
+ * Rewrote some ugly/confusing default assertion messages.
79
+ * assert_in_delta now defaults to 0.001 precision. Makes specs prettier.
80
+
81
+ * 9 bug fixes:
82
+
83
+ * Fixed assert_raises to raise outside of the inner-begin/rescue.
84
+ * Fixed for ruby 1.9 and rubinius.
85
+ * No longer exits 0 if exception in code PRE-test run causes early exit.
86
+ * Removed implementors method list from mini/test.rb - too stale.
87
+ * assert_nothing_raised takes a class as an arg. wtf? STUPID
88
+ * ".EF" output is now unbuffered.
89
+ * Bunch of changes to get working with rails... UGH.
90
+ * Added stupid hacks to deal with rails not requiring their dependencies.
91
+ * Now bitch loudly if someone defines one of my classes instead of requiring.
92
+ * Fixed infect method to work better on 1.9.
93
+ * Fixed all shadowed variable warnings in 1.9.
94
+
95
+ === 1.1.0 / 2007-11-08
96
+
97
+ * 4 major enhancements:
98
+
99
+ * Finished writing all missing assertions.
100
+ * Output matches original test/unit.
101
+ * Documented every method needed by language implementor.
102
+ * Fully switched over to self-testing setup.
103
+
104
+ * 2 minor enhancements:
105
+
106
+ * Added deny (assert ! test), our favorite extension to test/unit.
107
+ * Added .autotest and fairly complete unit tests. (thanks Chad for help here)
108
+
109
+ === 1.0.0 / 2006-10-30
110
+
111
+ * 1 major enhancement
112
+
113
+ * Birthday!
114
+
@@ -0,0 +1,11 @@
1
+ .autotest
2
+ History.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ lib/minitest/mock.rb
7
+ lib/minitest/spec.rb
8
+ lib/minitest/unit.rb
9
+ test/test_mini_mock.rb
10
+ test/test_mini_spec.rb
11
+ test/test_mini_test.rb
@@ -0,0 +1,56 @@
1
+ = minitest/{unit,spec,mock}
2
+
3
+ * http://rubyforge.org/projects/bfts
4
+
5
+ == DESCRIPTION:
6
+
7
+ minitest/unit is a small and fast replacement for ruby's huge and slow
8
+ test/unit. This is meant to be clean and easy to use both as a regular
9
+ test writer and for language implementors that need a minimal set of
10
+ methods to bootstrap a working unit test suite.
11
+
12
+ mini/spec is a functionally complete spec engine.
13
+
14
+ mini/mock, by Steven Baker, is a beautifully tiny mock object framework.
15
+
16
+ (This package was called miniunit once upon a time)
17
+
18
+ == FEATURES/PROBLEMS:
19
+
20
+ * Contains minitest/unit - a simple and clean test system (301 lines!).
21
+ * Contains minitest/spec - a simple and clean spec system (52 lines!).
22
+ * Contains minitest/mock - a simple and clean mock system (35 lines!).
23
+ * Incredibly small and fast runner, but no bells and whistles.
24
+
25
+ == REQUIREMENTS:
26
+
27
+ + Ruby 1.8, maybe even 1.6 or lower. No magic is involved.
28
+
29
+ == INSTALL:
30
+
31
+ + sudo gem install minitest
32
+
33
+ == LICENSE:
34
+
35
+ (The MIT License)
36
+
37
+ Copyright (c) Ryan Davis, Seattle.rb
38
+
39
+ Permission is hereby granted, free of charge, to any person obtaining
40
+ a copy of this software and associated documentation files (the
41
+ 'Software'), to deal in the Software without restriction, including
42
+ without limitation the rights to use, copy, modify, merge, publish,
43
+ distribute, sublicense, and/or sell copies of the Software, and to
44
+ permit persons to whom the Software is furnished to do so, subject to
45
+ the following conditions:
46
+
47
+ The above copyright notice and this permission notice shall be
48
+ included in all copies or substantial portions of the Software.
49
+
50
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
51
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
52
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
53
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
54
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
55
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
56
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,75 @@
1
+ # -*- ruby -*-
2
+
3
+ $TESTING_MINIUNIT = true
4
+
5
+ require 'rubygems'
6
+ require 'hoe'
7
+ require './lib/minitest/unit.rb'
8
+
9
+ Hoe.new('minitest', MiniTest::Unit::VERSION) do |miniunit|
10
+ miniunit.rubyforge_name = "bfts"
11
+
12
+ miniunit.developer('Ryan Davis', 'ryand-ruby@zenspider.com')
13
+ end
14
+
15
+ class Hoe # TODO: fix - I shouldn't need this
16
+ def run_tests(multi=false) # :nodoc:
17
+ tests = test_globs.map { |g| Dir.glob(g) }.flatten
18
+ tests.map! {|f| %Q(require "#{f}")}
19
+ cmd = "#{RUBY_FLAGS} -e '#{tests.join("; ")}' #{FILTER}"
20
+
21
+ send :ruby, cmd
22
+ end
23
+ end
24
+
25
+ begin
26
+ require 'rcov/rcovtask'
27
+ Rcov::RcovTask.new do |t|
28
+ t.verbose = true
29
+ t.rcov_opts << "--include-file lib/test"
30
+ t.rcov_opts << "--no-color"
31
+ end
32
+
33
+ task :rcov_info do
34
+ pattern = ENV['PATTERN'] || "test/test_*.rb"
35
+ ruby "-Ilib -S rcov --text-report --include-file lib/test --save coverage.info #{pattern}"
36
+ end
37
+
38
+ task :rcov_overlay do
39
+ rcov, eol = Marshal.load(File.read("coverage.info")).last[ENV["FILE"]], 1
40
+ puts rcov[:lines].zip(rcov[:coverage]).map { |line, coverage|
41
+ bol, eol = eol, eol + line.length
42
+ [bol, eol, "#ffcccc"] unless coverage
43
+ }.compact.inspect
44
+ end
45
+ rescue LoadError
46
+ # skip
47
+ end
48
+
49
+ def loc dir
50
+ system "find #{dir} -name \\*.rb | xargs wc -l | tail -1"
51
+ end
52
+
53
+ desc "stupid line count"
54
+ task :dickwag do
55
+ puts
56
+ puts "miniunit"
57
+ puts
58
+ print " lib loc"; loc "lib"
59
+ print " test loc"; loc "test"
60
+ print " totl loc"; loc "lib test"
61
+ print " flog = "; system "flog -s lib"
62
+
63
+ puts
64
+ puts "test/unit"
65
+ puts
66
+ Dir.chdir File.expand_path("~/Work/svn/ruby/ruby_1_8") do
67
+ print " lib loc"; loc "lib/test"
68
+ print " test loc"; loc "test/testunit"
69
+ print " totl loc"; loc "lib/test test/testunit"
70
+ print " flog = "; system "flog -s lib/test"
71
+ end
72
+ puts
73
+ end
74
+
75
+ # vim: syntax=Ruby
@@ -0,0 +1,31 @@
1
+ class MockExpectationError < StandardError; end
2
+
3
+ module MiniTest
4
+ class Mock
5
+ def initialize
6
+ @expected_calls = {}
7
+ @actual_calls = Hash.new {|h,k| h[k] = [] }
8
+ end
9
+
10
+ def expect(name, retval, args=[])
11
+ n, r, a = name, retval, args # for the closure below
12
+ @expected_calls[name] = { :retval => retval, :args => args }
13
+ self.class.__send__(:define_method, name) { |*x|
14
+ raise ArgumentError unless @expected_calls[n][:args].size == x.size
15
+ @actual_calls[n] << { :retval => r, :args => x }
16
+ retval
17
+ }
18
+ self
19
+ end
20
+
21
+ def verify
22
+ @expected_calls.each_key do |name|
23
+ expected = @expected_calls[name]
24
+ msg = "expected #{name}, #{expected.inspect}"
25
+ raise MockExpectationError, msg unless
26
+ @actual_calls.has_key? name and @actual_calls[name].include?(expected)
27
+ end
28
+ true
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/ruby -w
2
+
3
+ require 'minitest/unit'
4
+
5
+ class Module
6
+ def infect_with_assertions pos_prefix, neg_prefix, skip_re, map = {}
7
+ MiniTest::Assertions.public_instance_methods(false).each do |meth|
8
+ meth = meth.to_s
9
+
10
+ new_name = case meth
11
+ when /^assert/ then
12
+ meth.sub(/^assert/, pos_prefix.to_s)
13
+ when /^refute/ then
14
+ meth.sub(/^refute/, neg_prefix.to_s)
15
+ end
16
+ next unless new_name
17
+ next if new_name =~ skip_re
18
+
19
+ regexp, replacement = map.find { |re, _| new_name =~ re }
20
+ new_name.sub! regexp, replacement if replacement
21
+
22
+ # warn "%-22p -> %p %p" % [meth, new_name, regexp]
23
+ self.class_eval <<-EOM
24
+ def #{new_name} *args, &block
25
+ return MiniTest::Spec.current.#{meth}(*args, &self) if Proc === self
26
+ return MiniTest::Spec.current.#{meth}(args.first, self) if args.size == 1
27
+ return MiniTest::Spec.current.#{meth}(self, *args)
28
+ end
29
+ EOM
30
+ end
31
+ end
32
+ end
33
+
34
+ Object.infect_with_assertions(:must, :wont,
35
+ /^(must|wont)$|wont_(throw)|
36
+ must_(block|not?_|nothing|raise$)/x,
37
+ /(must_throw)s/ => '\1',
38
+ /(?!not)_same/ => '_be_same_as',
39
+ /_in_/ => '_be_within_',
40
+ /_operator/ => '_be',
41
+ /_includes/ => '_include',
42
+ /(must|wont)_(.*_of|nil|empty)/ => '\1_be_\2',
43
+ /must_raises/ => 'must_raise')
44
+
45
+ class Object
46
+ alias :must_be_close_to :must_be_within_delta
47
+ alias :wont_be_close_to :wont_be_within_delta
48
+ end
49
+
50
+ module Kernel
51
+ def describe desc, &block
52
+ cls = Class.new(MiniTest::Spec)
53
+ Object.const_set desc.to_s.split(/\W+/).map { |s| s.capitalize }.join, cls
54
+
55
+ cls.class_eval(&block)
56
+ end
57
+ end
58
+
59
+ class MiniTest::Spec < MiniTest::Unit::TestCase
60
+ def self.current
61
+ @@current_spec
62
+ end
63
+
64
+ def initialize name
65
+ super
66
+ @@current_spec = self
67
+ end
68
+
69
+ def self.before(type = :each, &block)
70
+ raise "unsupported before type: #{type}" unless type == :each
71
+ define_method :setup, &block
72
+ end
73
+
74
+ def self.after(type = :each, &block)
75
+ raise "unsupported after type: #{type}" unless type == :each
76
+ define_method :teardown, &block
77
+ end
78
+
79
+ def self.it desc, &block
80
+ define_method "test_#{desc.gsub(/\W+/, '_').downcase}", &block
81
+ end
82
+ end
@@ -0,0 +1,482 @@
1
+ ##
2
+ #
3
+ # Totally minimal drop-in replacement for test-unit
4
+ #
5
+ # TODO: refute -> debunk, prove/rebut, show/deny... lots of possibilities
6
+
7
+ module MiniTest
8
+ class Assertion < Exception; end
9
+ class Skip < Assertion; end
10
+
11
+ file = if RUBY_VERSION =~ /^1\.9/ then # bt's expanded, but __FILE__ isn't :(
12
+ File.expand_path __FILE__
13
+ elsif __FILE__ =~ /^[^\.]/ then # assume both relative
14
+ require 'pathname'
15
+ pwd = Pathname.new Dir.pwd
16
+ pn = Pathname.new File.expand_path(__FILE__)
17
+ pn = File.join(".", pn.relative_path_from(pwd)) unless pn.relative?
18
+ pn.to_s
19
+ else # assume both are expanded
20
+ __FILE__
21
+ end
22
+
23
+ # './lib' in project dir, or '/usr/local/blahblah' if installed
24
+ MINI_DIR = File.dirname(File.dirname(file))
25
+
26
+ def self.filter_backtrace bt
27
+ return ["No backtrace"] unless bt
28
+
29
+ new_bt = []
30
+ bt.each do |line|
31
+ break if line.rindex(MINI_DIR, 0)
32
+ new_bt << line
33
+ end
34
+
35
+ new_bt = bt.reject { |line| line.rindex(MINI_DIR, 0) } if new_bt.empty?
36
+ new_bt = bt.dup if new_bt.empty?
37
+ new_bt
38
+ end
39
+
40
+ module Assertions
41
+ def mu_pp(obj)
42
+ s = obj.inspect
43
+ s = s.force_encoding(Encoding.default_external) if defined? Encoding
44
+ s
45
+ end
46
+
47
+ def _assertions= n
48
+ @_assertions = n
49
+ end
50
+
51
+ def _assertions
52
+ @_assertions ||= 0
53
+ end
54
+
55
+ def assert test, msg = nil
56
+ msg ||= "Failed assertion, no message given."
57
+ self._assertions += 1
58
+ unless test then
59
+ msg = msg.call if Proc === msg
60
+ raise MiniTest::Assertion, msg
61
+ end
62
+ true
63
+ end
64
+
65
+ def assert_block msg = nil
66
+ msg = message(msg) { "Expected block to return true value" }
67
+ assert yield, msg
68
+ end
69
+
70
+ def assert_empty obj, msg = nil
71
+ msg = message(msg) { "Expected #{obj.inspect} to be empty" }
72
+ assert_respond_to obj, :empty?
73
+ assert obj.empty?, msg
74
+ end
75
+
76
+ def assert_equal exp, act, msg = nil
77
+ msg = message(msg) { "Expected #{mu_pp(exp)}, not #{mu_pp(act)}" }
78
+ assert(exp == act, msg)
79
+ end
80
+
81
+ def assert_in_delta exp, act, delta = 0.001, msg = nil
82
+ n = (exp - act).abs
83
+ msg = message(msg) { "Expected #{exp} - #{act} (#{n}) to be < #{delta}" }
84
+ assert delta > n, msg
85
+ end
86
+
87
+ def assert_in_epsilon a, b, epsilon = 0.001, msg = nil
88
+ assert_in_delta a, b, [a, b].min * epsilon, msg
89
+ end
90
+
91
+ def assert_includes collection, obj, msg = nil
92
+ msg = message(msg) { "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}" }
93
+ assert_respond_to collection, :include?
94
+ assert collection.include?(obj), msg
95
+ end
96
+
97
+ def assert_instance_of cls, obj, msg = nil
98
+ msg = message(msg) { "Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}" }
99
+ flip = (Module === obj) && ! (Module === cls) # HACK for specs
100
+ obj, cls = cls, obj if flip
101
+ assert cls === obj, msg
102
+ end
103
+
104
+ def assert_kind_of cls, obj, msg = nil # TODO: merge with instance_of
105
+ msg = message(msg) {
106
+ "Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" }
107
+ flip = (Module === obj) && ! (Module === cls) # HACK for specs
108
+ obj, cls = cls, obj if flip
109
+ assert obj.kind_of?(cls), msg
110
+ end
111
+
112
+ def assert_match exp, act, msg = nil
113
+ msg = message(msg) { "Expected #{mu_pp(act)} to match #{mu_pp(exp)}" }
114
+ assert_respond_to act, :"=~"
115
+ (exp = /#{exp}/) if String === exp && String === act
116
+ assert act =~ exp, msg
117
+ end
118
+
119
+ def assert_nil obj, msg = nil
120
+ msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" }
121
+ assert obj.nil?, msg
122
+ end
123
+
124
+ def assert_operator o1, op, o2, msg = nil
125
+ msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" }
126
+ assert o1.__send__(op, o2), msg
127
+ end
128
+
129
+ def assert_raises *exp
130
+ msg = String === exp.last ? exp.pop : nil
131
+ should_raise = false
132
+ begin
133
+ yield
134
+ should_raise = true
135
+ rescue Exception => e
136
+ assert_includes(exp, e.class, exception_details(e, "<#{mu_pp(exp)}> exception expected, not"))
137
+ return e
138
+ end
139
+
140
+ exp = exp.first if exp.size == 1
141
+ flunk "#{mu_pp(exp)} expected but nothing was raised." if should_raise
142
+ end
143
+
144
+ def assert_respond_to obj, meth, msg = nil
145
+ msg = message(msg) {
146
+ "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}"
147
+ }
148
+ flip = (Symbol === obj) && ! (Symbol === meth) # HACK for specs
149
+ obj, meth = meth, obj if flip
150
+ assert obj.respond_to?(meth), msg
151
+ end
152
+
153
+ def assert_same exp, act, msg = nil
154
+ msg = message(msg) {
155
+ data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
156
+ "Expected %s (0x%x) to be the same as %s (0x%x)" % data
157
+ }
158
+ assert exp.equal?(act), msg
159
+ end
160
+
161
+ def assert_send send_ary, m = nil
162
+ recv, msg, *args = send_ary
163
+ m = message(m) {
164
+ "Expected #{mu_pp(recv)}.#{msg}(*#{mu_pp(args)}) to return true" }
165
+ assert recv.__send__(msg, *args), m
166
+ end
167
+
168
+ def assert_throws sym, msg = nil
169
+ default = "Expected #{mu_pp(sym)} to have been thrown"
170
+ caught = true
171
+ catch(sym) do
172
+ begin
173
+ yield
174
+ rescue ArgumentError => e # 1.9 exception
175
+ default += ", not #{e.message.split(/ /).last}"
176
+ rescue NameError => e # 1.8 exception
177
+ default += ", not #{e.name.inspect}"
178
+ end
179
+ caught = false
180
+ end
181
+
182
+ assert caught, message(msg) { default }
183
+ end
184
+
185
+ def capture_io
186
+ require 'stringio'
187
+
188
+ orig_stdout, orig_stderr = $stdout.dup, $stderr.dup
189
+ captured_stdout, captured_stderr = StringIO.new, StringIO.new
190
+ $stdout, $stderr = captured_stdout, captured_stderr
191
+
192
+ yield
193
+
194
+ return captured_stdout.string, captured_stderr.string
195
+ ensure
196
+ $stdout = orig_stdout
197
+ $stderr = orig_stderr
198
+ end
199
+
200
+ def exception_details e, msg
201
+ "#{msg}\nClass: <#{e.class}>\nMessage: <#{e.message.inspect}>\n---Backtrace---\n#{MiniTest::filter_backtrace(e.backtrace).join("\n")}\n---------------"
202
+ end
203
+
204
+ def flunk msg = nil
205
+ msg ||= "Epic Fail!"
206
+ assert false, msg
207
+ end
208
+
209
+ def message msg = nil, &default
210
+ proc {
211
+ if msg then
212
+ msg = msg.to_s unless String === msg
213
+ msg += '.' unless msg.empty?
214
+ msg += "\n#{default.call}."
215
+ msg.strip
216
+ else
217
+ "#{default.call}."
218
+ end
219
+ }
220
+ end
221
+
222
+ # used for counting assertions
223
+ def pass msg = nil
224
+ assert true
225
+ end
226
+
227
+ def refute test, msg = nil
228
+ msg ||= "Failed refutation, no message given"
229
+ not assert(! test, msg)
230
+ end
231
+
232
+ def refute_empty obj, msg = nil
233
+ msg = message(msg) { "Expected #{obj.inspect} to not be empty" }
234
+ assert_respond_to obj, :empty?
235
+ refute obj.empty?, msg
236
+ end
237
+
238
+ def refute_equal exp, act, msg = nil
239
+ msg = message(msg) { "Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}" }
240
+ refute exp == act, msg
241
+ end
242
+
243
+ def refute_in_delta exp, act, delta = 0.001, msg = nil
244
+ n = (exp - act).abs
245
+ msg = message(msg) { "Expected #{exp} - #{act} (#{n}) to not be < #{delta}" }
246
+ refute delta > n, msg
247
+ end
248
+
249
+ def refute_in_epsilon a, b, epsilon = 0.001, msg = nil
250
+ refute_in_delta a, b, a * epsilon, msg
251
+ end
252
+
253
+ def refute_includes collection, obj, msg = nil
254
+ msg = message(msg) { "Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}" }
255
+ assert_respond_to collection, :include?
256
+ refute collection.include?(obj), msg
257
+ end
258
+
259
+ def refute_instance_of cls, obj, msg = nil
260
+ msg = message(msg) { "Expected #{mu_pp(obj)} to not be an instance of #{cls}" }
261
+ flip = (Module === obj) && ! (Module === cls) # HACK for specs
262
+ obj, cls = cls, obj if flip
263
+ refute cls === obj, msg
264
+ end
265
+
266
+ def refute_kind_of cls, obj, msg = nil # TODO: merge with instance_of
267
+ msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" }
268
+ flip = (Module === obj) && ! (Module === cls) # HACK for specs
269
+ obj, cls = cls, obj if flip
270
+ refute obj.kind_of?(cls), msg
271
+ end
272
+
273
+ def refute_match exp, act, msg = nil
274
+ msg = message(msg) { "Expected #{mu_pp(act)} to not match #{mu_pp(exp)}" }
275
+ refute act =~ exp, msg
276
+ end
277
+
278
+ def refute_nil obj, msg = nil
279
+ msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" }
280
+ refute obj.nil?, msg
281
+ end
282
+
283
+ def refute_operator o1, op, o2, msg = nil
284
+ msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}" }
285
+ refute o1.__send__(op, o2), msg
286
+ end
287
+
288
+ def refute_respond_to obj, meth, msg = nil
289
+ msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" }
290
+ flip = (Symbol === obj) && ! (Symbol === meth) # HACK for specs
291
+ obj, meth = meth, obj if flip
292
+ refute obj.respond_to?(meth), msg
293
+ end
294
+
295
+ def refute_same exp, act, msg = nil
296
+ msg = message(msg) { "Expected #{mu_pp(act)} to not be the same as #{mu_pp(exp)}" }
297
+ refute exp.equal?(act), msg
298
+ end
299
+
300
+ def skip msg = nil
301
+ msg ||= "Skipped, no message given"
302
+ raise MiniTest::Skip, msg
303
+ end
304
+ end
305
+
306
+ class Unit
307
+ VERSION = "1.3.0"
308
+
309
+ attr_accessor :report, :failures, :errors, :skips
310
+ attr_accessor :test_count, :assertion_count
311
+
312
+ @@installed_at_exit ||= false
313
+ @@out = $stdout
314
+
315
+ def self.autorun
316
+ at_exit {
317
+ exit_code = MiniTest::Unit.new.run(ARGV)
318
+ exit false if exit_code && exit_code != 0
319
+ } unless @@installed_at_exit
320
+ @@installed_at_exit = true
321
+ end
322
+
323
+ def self.output= stream
324
+ @@out = stream
325
+ end
326
+
327
+ def location e
328
+ e.backtrace.find { |s|
329
+ s !~ /in .(assert|refute|flunk|pass|fail|raise)/
330
+ }.sub(/:in .*$/, '')
331
+ end
332
+
333
+ def puke klass, meth, e
334
+ e = case e
335
+ when MiniTest::Skip then
336
+ @skips += 1
337
+ "Skipped:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
338
+ when MiniTest::Assertion then
339
+ @failures += 1
340
+ "Failure:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
341
+ else
342
+ @errors += 1
343
+ bt = MiniTest::filter_backtrace(e.backtrace).join("\n ")
344
+ "Error:\n#{meth}(#{klass}):\n#{e.class}: #{e.message}\n #{bt}\n"
345
+ end
346
+ @report << e
347
+ e[0, 1]
348
+ end
349
+
350
+ def initialize
351
+ @report = []
352
+ @errors = @failures = @skips = 0
353
+ @verbose = false
354
+ end
355
+
356
+ ##
357
+ # Top level driver, controls all output and filtering.
358
+
359
+ def run args = []
360
+ @verbose = args.delete('-v')
361
+
362
+ filter = if args.first =~ /^(-n|--name)$/ then
363
+ args.shift
364
+ arg = args.shift
365
+ arg =~ /\/(.*)\// ? Regexp.new($1) : arg
366
+ else
367
+ /./ # anything - ^test_ already filtered by #tests
368
+ end
369
+
370
+ @@out.puts "Loaded suite #{$0.sub(/\.rb$/, '')}\nStarted"
371
+
372
+ start = Time.now
373
+ run_test_suites filter
374
+
375
+ @@out.puts
376
+ @@out.puts "Finished in #{'%.6f' % (Time.now - start)} seconds."
377
+
378
+ @report.each_with_index do |msg, i|
379
+ @@out.puts "\n%3d) %s" % [i + 1, msg]
380
+ end
381
+
382
+ @@out.puts
383
+
384
+ format = "%d tests, %d assertions, %d failures, %d errors, %d skips"
385
+ @@out.puts format % [test_count, assertion_count, failures, errors, skips]
386
+
387
+ return failures + errors if @test_count > 0 # or return nil...
388
+ end
389
+
390
+ def run_test_suites filter = /./
391
+ @test_count, @assertion_count = 0, 0
392
+ old_sync, @@out.sync = @@out.sync, true if @@out.respond_to? :sync=
393
+ TestCase.test_suites.each do |suite|
394
+ suite.test_methods.grep(filter).each do |test|
395
+ inst = suite.new test
396
+ inst._assertions = 0
397
+ @@out.print "#{suite}##{test}: " if @verbose
398
+
399
+ t = Time.now if @verbose
400
+ result = inst.run(self)
401
+
402
+ @@out.print "%.2f s: " % (Time.now - t) if @verbose
403
+ @@out.print result
404
+ @@out.puts if @verbose
405
+ @test_count += 1
406
+ @assertion_count += inst._assertions
407
+ end
408
+ end
409
+ @@out.sync = old_sync if @@out.respond_to? :sync=
410
+ [@test_count, @assertion_count]
411
+ end
412
+
413
+ class TestCase
414
+ attr_reader :name
415
+
416
+ def run runner
417
+ result = '.'
418
+ begin
419
+ @passed = nil
420
+ self.setup
421
+ self.__send__ self.name
422
+ @passed = true
423
+ rescue Exception => e
424
+ @passed = false
425
+ result = runner.puke(self.class, self.name, e)
426
+ ensure
427
+ begin
428
+ self.teardown
429
+ rescue Exception => e
430
+ result = runner.puke(self.class, self.name, e)
431
+ end
432
+ end
433
+ result
434
+ end
435
+
436
+ def initialize name
437
+ @name = name
438
+ @passed = nil
439
+ end
440
+
441
+ def self.reset
442
+ @@test_suites = {}
443
+ end
444
+
445
+ reset
446
+
447
+ def self.inherited klass
448
+ @@test_suites[klass] = true
449
+ end
450
+
451
+ def self.test_order
452
+ :random
453
+ end
454
+
455
+ def self.test_suites
456
+ @@test_suites.keys.sort_by { |ts| ts.name }
457
+ end
458
+
459
+ def self.test_methods
460
+ methods = public_instance_methods(true).grep(/^test/).map { |m|
461
+ m.to_s
462
+ }.sort
463
+
464
+ if self.test_order == :random then
465
+ max = methods.size
466
+ methods = methods.sort_by { rand(max) }
467
+ end
468
+
469
+ methods
470
+ end
471
+
472
+ def setup; end
473
+ def teardown; end
474
+
475
+ def passed?
476
+ @passed
477
+ end
478
+
479
+ include MiniTest::Assertions
480
+ end # class TestCase
481
+ end # class Test
482
+ end # module Mini