diff options
author | ryan <ryan@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-05-04 21:46:01 +0000 |
---|---|---|
committer | ryan <ryan@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-05-04 21:46:01 +0000 |
commit | 6af843b9cb99fb844bf866e71e9ee52be126080f (patch) | |
tree | afee639e216cf32357c2d6e76de49f2549c6d5af /lib | |
parent | 95d4b3ba4974fdb9f08900267964949e30b1c821 (diff) | |
download | ruby-6af843b9cb99fb844bf866e71e9ee52be126080f.tar.gz |
Imported minitest 2.12.1 (r7323)
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35541 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r-- | lib/minitest/README.txt | 50 | ||||
-rw-r--r-- | lib/minitest/autorun.rb | 1 | ||||
-rw-r--r-- | lib/minitest/benchmark.rb | 14 | ||||
-rw-r--r-- | lib/minitest/mock.rb | 70 | ||||
-rw-r--r-- | lib/minitest/pride.rb | 32 | ||||
-rw-r--r-- | lib/minitest/spec.rb | 54 | ||||
-rw-r--r-- | lib/minitest/unit.rb | 217 |
7 files changed, 351 insertions, 87 deletions
diff --git a/lib/minitest/README.txt b/lib/minitest/README.txt index 25c4dae1a9..8c33c0aa52 100644 --- a/lib/minitest/README.txt +++ b/lib/minitest/README.txt @@ -14,7 +14,7 @@ TDD, BDD, mocking, and benchmarking. paired up and we cracked open the code for a few test frameworks... - I MUST say that mintiest is *very* readable / understandable + I MUST say that minitest is *very* readable / understandable compared to the 'other two' options we looked at. Nicely done and thank you for helping us keep our mental sanity." @@ -44,7 +44,7 @@ implementors that need a minimal set of methods to bootstrap a working test suite. For example, there is no magic involved for test-case discovery. - "Again, I can’t praise enough the idea of a testing/specing + "Again, I can't praise enough the idea of a testing/specing framework that I can actually read in full in one sitting!" -- Piotr Szotkowski @@ -117,6 +117,10 @@ Given that you'd like to test the following class: end end +For matchers support check out: + +https://github.com/zenspider/minitest-matchers + === Benchmarks Add benchmarks to your regular unit tests. If the unit tests fail, the @@ -167,7 +171,7 @@ Output is tab-delimited to make it easy to paste into a spreadsheet. def ask(question) method = question.tr(" ","_") + "?" - @meme.send(method) + @meme.__send__(method) end end @@ -242,6 +246,46 @@ fixture loading: MiniTest::Unit.runner = MiniTestWithTransactions::Unit.new +== Known Extensions: + +minitest-capistrano :: Assertions and expectations for testing Capistrano recipes +minitest-capybara :: Capybara matchers support for minitest unit and spec +minitest-chef-handler :: Run Minitest suites as Chef report handlers +minitest-ci :: CI reporter plugin for MiniTest. +minitest-colorize :: Colorize MiniTest output and show failing tests instantly. +minitest-context :: Defines contexts for code reuse in MiniTest + specs that share common expectations. +minitest-debugger :: Wraps assert so failed assertions drop into + the ruby debugger. +minitest-display :: Patches MiniTest to allow for an easily configurable output. +minitest-emoji :: Print out emoji for your test passes, fails, and skips. +minitest-excludes :: Clean API for excluding certain tests you + don't want to run under certain conditions. +minitest-firemock :: Makes your MiniTest mocks more resilient. +minitest-growl :: Test notifier for minitest via growl. +minitest-instrument :: Instrument ActiveSupport::Notifications when + test method is executed +minitest-instrument-db :: Store information about speed of test + execution provided by minitest-instrument in database +minitest-libnotify :: Test notifier for minitest via libnotify. +minitest-macruby :: Provides extensions to minitest for macruby UI testing. +minitest-matchers :: Adds support for RSpec-style matchers to minitest. +minitest-metadata :: Annotate tests with metadata (key-value). +minitest-mongoid :: Mongoid assertion matchers for MiniTest +minitest-must_not :: Provides must_not as an alias for wont in MiniTest +minitest-predicates :: Adds support for .predicate? methods +minitest-pry :: A minitest plugin to drop into pry on assertion failure. +minitest-rails :: MiniTest integration for Rails 3.1. +minitest-reporters :: Create customizable MiniTest output formats +minitest-rg :: redgreen minitest +minitest-spec-magic :: Minitest::Spec extensions for Rails and beyond +minitest-tags :: add tags for minitest +minitest-wscolor :: Yet another test colorizer. +minitest_owrapper :: Get tests results as a TestResult object. +minitest_should :: Shoulda style syntax for minitest test::unit. +minitest_tu_shim :: minitest_tu_shim bridges between test/unit and minitest. +mongoid-minitest :: MiniTest matchers for Mongoid. + == REQUIREMENTS: * Ruby 1.8, maybe even 1.6 or lower. No magic is involved. diff --git a/lib/minitest/autorun.rb b/lib/minitest/autorun.rb index 443f2f61d4..cb4a3a0e5d 100644 --- a/lib/minitest/autorun.rb +++ b/lib/minitest/autorun.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 ###################################################################### # This file is imported from the minitest project. # DO NOT make modifications in this repo. They _will_ be reverted! diff --git a/lib/minitest/benchmark.rb b/lib/minitest/benchmark.rb index c6faa50770..02121db340 100644 --- a/lib/minitest/benchmark.rb +++ b/lib/minitest/benchmark.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 ###################################################################### # This file is imported from the minitest project. # DO NOT make modifications in this repo. They _will_ be reverted! @@ -7,9 +8,7 @@ require 'minitest/unit' require 'minitest/spec' -class MiniTest::Unit - attr_accessor :runner - +class MiniTest::Unit # :nodoc: def run_benchmarks # :nodoc: _run_anything :benchmark end @@ -318,6 +317,15 @@ class MiniTest::Spec define_method "bench_#{name.gsub(/\W+/, '_')}", &block end + ## + # Specifies the ranges used for benchmarking for that class. + # + # bench_range do + # bench_exp(2, 16, 2) + # end + # + # See Unit::TestCase.bench_range for more details. + def self.bench_range &block return super unless block diff --git a/lib/minitest/mock.rb b/lib/minitest/mock.rb index 0d86bfb847..55b0095c0b 100644 --- a/lib/minitest/mock.rb +++ b/lib/minitest/mock.rb @@ -1,10 +1,12 @@ +# encoding: utf-8 ###################################################################### # This file is imported from the minitest project. # DO NOT make modifications in this repo. They _will_ be reverted! # File a patch instead and assign it to Ryan Davis. ###################################################################### -class MockExpectationError < StandardError; end +class MockExpectationError < StandardError # :nodoc: +end # omg... worst bug ever. rdoc doesn't allow 1-liners ## # A simple and clean mock object framework. @@ -24,8 +26,8 @@ module MiniTest end def initialize # :nodoc: - @expected_calls = {} - @actual_calls = Hash.new {|h,k| h[k] = [] } + @expected_calls = Hash.new { |calls, name| calls[name] = [] } + @actual_calls = Hash.new { |calls, name| calls[name] = [] } end ## @@ -50,44 +52,70 @@ module MiniTest # @mock.verify # => raises MockExpectationError def expect(name, retval, args=[]) - @expected_calls[name] = { :retval => retval, :args => args } + raise ArgumentError, "args must be an array" unless Array === args + @expected_calls[name] << { :retval => retval, :args => args } self end + def call name, data + case data + when Hash then + "#{name}(#{data[:args].inspect[1..-2]}) => #{data[:retval].inspect}" + else + data.map { |d| call name, d }.join ", " + end + end + ## # Verify that all methods were called as expected. Raises # +MockExpectationError+ if the mock object was not called as # expected. def verify - @expected_calls.each_key do |name| - expected = @expected_calls[name] - msg1 = "expected #{name}, #{expected.inspect}" - msg2 = "#{msg1}, got #{@actual_calls[name].inspect}" - - raise MockExpectationError, msg2 if - @actual_calls.has_key? name and - not @actual_calls[name].include?(expected) - - raise MockExpectationError, msg1 unless - @actual_calls.has_key? name and @actual_calls[name].include?(expected) + @expected_calls.each do |name, calls| + calls.each do |expected| + msg1 = "expected #{call name, expected}" + msg2 = "#{msg1}, got [#{call name, @actual_calls[name]}]" + + raise MockExpectationError, msg2 if + @actual_calls.has_key? name and + not @actual_calls[name].include?(expected) + + raise MockExpectationError, msg1 unless + @actual_calls.has_key? name and @actual_calls[name].include?(expected) + end end true end def method_missing(sym, *args) # :nodoc: - expected = @expected_calls[sym] - - unless expected then + unless @expected_calls.has_key?(sym) then raise NoMethodError, "unmocked method %p, expected one of %p" % [sym, @expected_calls.keys.sort_by(&:to_s)] end - expected_args, retval = expected[:args], expected[:retval] + index = @actual_calls[sym].length + expected_call = @expected_calls[sym][index] - unless expected_args.size == args.size + unless expected_call then + raise MockExpectationError, "No more expects available for %p: %p" % + [sym, args] + end + + expected_args, retval = expected_call[:args], expected_call[:retval] + + if expected_args.size != args.size then raise ArgumentError, "mocked method %p expects %d arguments, got %d" % - [sym, expected[:args].size, args.size] + [sym, expected_args.size, args.size] + end + + fully_matched = expected_args.zip(args).all? { |mod, a| + mod === a or mod == a + } + + unless fully_matched then + raise MockExpectationError, "mocked method %p called with unexpected arguments %p" % + [sym, args] end @actual_calls[sym] << { diff --git a/lib/minitest/pride.rb b/lib/minitest/pride.rb index 9cf16fdffa..9de4e37a98 100644 --- a/lib/minitest/pride.rb +++ b/lib/minitest/pride.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 ###################################################################### # This file is imported from the minitest project. # DO NOT make modifications in this repo. They _will_ be reverted! @@ -10,12 +11,17 @@ require "minitest/unit" # Show your testing pride! class PrideIO + + # Start an escape sequence ESC = "\e[" + + # End the escape sequence NND = "#{ESC}0m" + # The IO we're going to pipe through. attr_reader :io - def initialize io + def initialize io # :nodoc: @io = io # stolen from /System/Library/Perl/5.10.0/Term/ANSIColor.pm # also reference http://en.wikipedia.org/wiki/ANSI_escape_code @@ -25,6 +31,9 @@ class PrideIO # io.sync = true end + ## + # Wrap print to colorize the output. + def print o case o when "." then @@ -36,7 +45,7 @@ class PrideIO end end - def puts(*o) + def puts(*o) # :nodoc: o.map! { |s| s.sub(/Finished tests/) { @index = 0 @@ -49,6 +58,9 @@ class PrideIO super end + ## + # Color a string. + def pride string string = "*" if string == "." c = @colors[@index % @size] @@ -56,15 +68,20 @@ class PrideIO "#{ESC}#{c}m#{string}#{NND}" end - def method_missing msg, *args + def method_missing msg, *args # :nodoc: io.send(msg, *args) end end -class PrideLOL < PrideIO # inspired by lolcat, but massively cleaned up - PI_3 = Math::PI / 3 +## +# If you thought the PrideIO was colorful... +# +# (Inspired by lolcat, but with clean math) + +class PrideLOL < PrideIO + PI_3 = Math::PI / 3 # :nodoc: - def initialize io + def initialize io # :nodoc: # walk red, green, and blue around a circle separated by equal thirds. # # To visualize, type this into wolfram-alpha: @@ -88,6 +105,9 @@ class PrideLOL < PrideIO # inspired by lolcat, but massively cleaned up super end + ## + # Make the string even more colorful. Damnit. + def pride string c = @colors[@index % @size] @index += 1 diff --git a/lib/minitest/spec.rb b/lib/minitest/spec.rb index ac28b24c4a..c0c0ae2f02 100644 --- a/lib/minitest/spec.rb +++ b/lib/minitest/spec.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 ###################################################################### # This file is imported from the minitest project. # DO NOT make modifications in this repo. They _will_ be reverted! @@ -13,11 +14,14 @@ class Module # :nodoc: # warn "%-22p -> %p %p" % [meth, new_name, dont_flip] self.class_eval <<-EOM def #{new_name} *args - return MiniTest::Spec.current.#{meth}(*args, &self) if - Proc === self - return MiniTest::Spec.current.#{meth}(args.first, self) if - args.size == 1 unless #{!!dont_flip} - return MiniTest::Spec.current.#{meth}(self, *args) + case + when Proc === self then + MiniTest::Spec.current.#{meth}(*args, &self) + when #{!!dont_flip} then + MiniTest::Spec.current.#{meth}(self, *args) + else + MiniTest::Spec.current.#{meth}(args.first, self, *args[1..-1]) + end end EOM end @@ -177,6 +181,12 @@ class MiniTest::Spec < MiniTest::Unit::TestCase add_teardown_hook {|tc| tc.instance_eval(&block) } end + NAME_RE = if RUBY_VERSION >= "1.9" + Regexp.new("[^[[:word:]]]+") + else + /\W+/u + end + ## # Define an expectation with name +desc+. Name gets morphed to a # proper test method name. For some freakish reason, people who @@ -194,15 +204,22 @@ class MiniTest::Spec < MiniTest::Unit::TestCase @specs ||= 0 @specs += 1 - name = "test_%04d_%s" % [ @specs, desc.gsub(/\W+/, '_').downcase ] + name = "test_%04d_%s" % [ @specs, desc.gsub(NAME_RE, '_').downcase ] define_method name, &block self.children.each do |mod| mod.send :undef_method, name if mod.public_method_defined? name end + + name end + ## + # Essentially, define an accessor for +name+ with +block+. + # + # Why use let instead of def? I honestly don't know. + def self.let name, &block define_method name do @_memoized ||= {} @@ -210,6 +227,10 @@ class MiniTest::Spec < MiniTest::Unit::TestCase end end + ## + # Another lazy man's accessor generator. Made even more lazy by + # setting the name for you to +subject+. + def self.subject &block let :subject, &block end @@ -232,6 +253,14 @@ class MiniTest::Spec < MiniTest::Unit::TestCase end # :stopdoc: + def after_setup + run_setup_hooks + end + + def before_teardown + run_teardown_hooks + end + class << self attr_reader :desc alias :specify :it @@ -240,6 +269,9 @@ class MiniTest::Spec < MiniTest::Unit::TestCase # :startdoc: end +## +# It's where you hide your "assertions". + module MiniTest::Expectations ## # See MiniTest::Assertions#assert_empty. @@ -248,7 +280,7 @@ module MiniTest::Expectations # # :method: must_be_empty - infect_an_assertion :assert_empty, :must_be_empty + infect_an_assertion :assert_empty, :must_be_empty, :unary ## # See MiniTest::Assertions#assert_equal @@ -322,7 +354,7 @@ module MiniTest::Expectations # # :method: must_be_nil - infect_an_assertion :assert_nil, :must_be_nil + infect_an_assertion :assert_nil, :must_be_nil, :unary ## # See MiniTest::Assertions#assert_operator @@ -408,7 +440,7 @@ module MiniTest::Expectations # # :method: wont_be_empty - infect_an_assertion :refute_empty, :wont_be_empty + infect_an_assertion :refute_empty, :wont_be_empty, :unary ## # See MiniTest::Assertions#refute_equal @@ -483,7 +515,7 @@ module MiniTest::Expectations # # :method: wont_be_nil - infect_an_assertion :refute_nil, :wont_be_nil + infect_an_assertion :refute_nil, :wont_be_nil, :unary ## # See MiniTest::Assertions#refute_operator @@ -517,6 +549,6 @@ module MiniTest::Expectations infect_an_assertion :refute_same, :wont_be_same_as end -class Object +class Object # :nodoc: include MiniTest::Expectations end diff --git a/lib/minitest/unit.rb b/lib/minitest/unit.rb index 2c767b68fa..0a0e10816e 100644 --- a/lib/minitest/unit.rb +++ b/lib/minitest/unit.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 ###################################################################### # This file is imported from the minitest project. # DO NOT make modifications in this repo. They _will_ be reverted! @@ -61,8 +62,13 @@ module MiniTest # printed if the assertion fails. module Assertions + UNDEFINED = Object.new # :nodoc: - WINDOZE = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ + def UNDEFINED.inspect # :nodoc: + "UNDEFINED" # again with the rdoc bugs... :( + end + + WINDOZE = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ # :nodoc: ## # Returns the diff command to use in #diff. Tries to intelligently @@ -187,6 +193,7 @@ module MiniTest # Fails unless the block returns a true value. def assert_block msg = nil + warn "NOTE: MiniTest::Unit::TestCase#assert_block is deprecated, use assert. It will be removed on or after 2012-06-01." msg = message(msg) { "Expected block to return true value" } assert yield, msg end @@ -225,7 +232,7 @@ module MiniTest def assert_in_delta exp, act, delta = 0.001, msg = nil n = (exp - act).abs - msg = message(msg) { "Expected #{exp} - #{act} (#{n}) to be < #{delta}" } + msg = message(msg) { "Expected |#{exp} - #{act}| (#{n}) to be < #{delta}"} assert delta >= n, msg end @@ -234,7 +241,7 @@ module MiniTest # error less than +epsilon+. def assert_in_epsilon a, b, epsilon = 0.001, msg = nil - assert_in_delta a, b, [a, b].min * epsilon, msg + assert_in_delta a, b, [a.abs, b.abs].min * epsilon, msg end ## @@ -270,13 +277,13 @@ module MiniTest end ## - # Fails unless +exp+ is <tt>=~</tt> +act+. + # Fails unless +matcher+ <tt>=~</tt> +obj+. - def assert_match exp, act, msg = nil - msg = message(msg) { "Expected #{mu_pp(exp)} to match #{mu_pp(act)}" } - assert_respond_to act, :"=~" - exp = Regexp.new Regexp.escape exp if String === exp and String === act - assert exp =~ act, msg + def assert_match matcher, obj, msg = nil + msg = message(msg) { "Expected #{mu_pp matcher} to match #{mu_pp obj}" } + assert_respond_to matcher, :"=~" + matcher = Regexp.new Regexp.escape matcher if String === matcher + assert matcher =~ obj, msg end ## @@ -287,9 +294,6 @@ module MiniTest assert obj.nil?, msg end - UNDEFINED = Object.new - def UNDEFINED.inspect; "UNDEFINED"; end - ## # For testing with binary operators. # @@ -313,8 +317,8 @@ module MiniTest yield end - x = assert_equal stdout, out, "In stdout" if stdout y = assert_equal stderr, err, "In stderr" if stderr + x = assert_equal stdout, out, "In stdout" if stdout (!stdout || x) && (!stderr || y) end @@ -334,10 +338,11 @@ module MiniTest end ## - # Fails unless the block raises one of +exp+ + # Fails unless the block raises one of +exp+. Returns the + # exception matched so you can check the message, attributes, etc. def assert_raises *exp - msg = "#{exp.pop}\n" if String === exp.last + msg = "#{exp.pop}.\n" if String === exp.last should_raise = false begin @@ -355,7 +360,7 @@ module MiniTest details = "#{msg}#{mu_pp(exp)} exception expected, not" assert(exp.any? { |ex| ex.instance_of?(Module) ? e.kind_of?(ex) : ex == e.class - }, proc{exception_details(e, details)}) + }, exception_details(e, details)) return e end @@ -523,14 +528,14 @@ module MiniTest end ## - # For comparing Floats. Fails if +exp+ is within +delta+ of +act+ + # For comparing Floats. Fails if +exp+ is within +delta+ of +act+. # # refute_in_delta Math::PI, (22.0 / 7.0) def refute_in_delta exp, act, delta = 0.001, msg = nil n = (exp - act).abs msg = message(msg) { - "Expected #{exp} - #{act} (#{n}) to not be < #{delta}" + "Expected |#{exp} - #{act}| (#{n}) to not be < #{delta}" } refute delta > n, msg end @@ -544,7 +549,7 @@ module MiniTest end ## - # Fails if +collection+ includes +obj+ + # Fails if +collection+ includes +obj+. def refute_includes collection, obj, msg = nil msg = message(msg) { @@ -555,7 +560,7 @@ module MiniTest end ## - # Fails if +obj+ is an instance of +cls+ + # Fails if +obj+ is an instance of +cls+. def refute_instance_of cls, obj, msg = nil msg = message(msg) { @@ -565,7 +570,7 @@ module MiniTest end ## - # Fails if +obj+ is a kind of +cls+ + # Fails if +obj+ is a kind of +cls+. def refute_kind_of cls, obj, msg = nil # TODO: merge with instance_of msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" } @@ -573,13 +578,13 @@ module MiniTest end ## - # Fails if +exp+ <tt>=~</tt> +act+ + # Fails if +matcher+ <tt>=~</tt> +obj+. - def refute_match exp, act, msg = nil - msg = message(msg) { "Expected #{mu_pp(exp)} to not match #{mu_pp(act)}" } - assert_respond_to act, :"=~" - exp = (/#{Regexp.escape exp}/) if String === exp and String === act - refute exp =~ act, msg + def refute_match matcher, obj, msg = nil + msg = message(msg) {"Expected #{mu_pp matcher} to not match #{mu_pp obj}"} + assert_respond_to matcher, :"=~" + matcher = Regexp.new Regexp.escape matcher if String === matcher + refute matcher =~ obj, msg end ## @@ -646,8 +651,8 @@ module MiniTest end end - class Unit - VERSION = "2.8.1" # :nodoc: + class Unit # :nodoc: + VERSION = "2.12.1" # :nodoc: attr_accessor :report, :failures, :errors, :skips # :nodoc: attr_accessor :test_count, :assertion_count # :nodoc: @@ -655,6 +660,10 @@ module MiniTest attr_accessor :help # :nodoc: attr_accessor :verbose # :nodoc: attr_writer :options # :nodoc: + attr_accessor :last_error # :nodoc: + + ## + # Lazy accessor for options. def options @options ||= {} @@ -662,6 +671,7 @@ module MiniTest @@installed_at_exit ||= false @@out = $stdout + @@after_tests = [] ## # A simple hook allowing you to run a block of code after the @@ -669,8 +679,8 @@ module MiniTest # # MiniTest::Unit.after_tests { p $debugging_info } - def self.after_tests - at_exit { at_exit { yield } } + def self.after_tests &block + @@after_tests << block end ## @@ -686,7 +696,10 @@ module MiniTest # to run (at_exit stacks). exit_code = nil - at_exit { exit false if exit_code && exit_code != 0 } + at_exit { + @@after_tests.reverse_each(&:call) + exit false if exit_code && exit_code != 0 + } exit_code = MiniTest::Unit.new.run ARGV } unless @@installed_at_exit @@ -744,6 +757,9 @@ module MiniTest grep(/^run_/).map { |s| s.to_s }).uniq end + ## + # Return the IO for output. + def output self.class.output end @@ -756,6 +772,9 @@ module MiniTest output.print(*a) end + ## + # Runner for a given +type+ (eg, test vs bench). + def _run_anything type suites = TestCase.send "#{type}_suites" return if suites.empty? @@ -793,10 +812,16 @@ module MiniTest status end + ## + # Runs all the +suites+ for a given +type+. + def _run_suites suites, type suites.map { |suite| _run_suite suite, type } end + ## + # Run a single +suite+ for a given +type+. + def _run_suite suite, type header = "#{type}_suite_header" puts send(header, suite) if respond_to? header @@ -811,9 +836,12 @@ module MiniTest print "#{suite}##{method} = " if @verbose @start_time = Time.now + self.last_error = nil result = inst.run self time = Time.now - @start_time + record suite, method, inst._assertions, time, last_error + print "%.2f s = " % time if @verbose print result puts if @verbose @@ -824,6 +852,21 @@ module MiniTest return assertions.size, assertions.inject(0) { |sum, n| sum + n } end + ## + # Record the result of a single run. Makes it very easy to gather + # information. Eg: + # + # class StatisticsRecorder < MiniTest::Unit + # def record suite, method, assertions, time, error + # # ... record the results somewhere ... + # end + # end + # + # MiniTest::Unit.runner = StatisticsRecorder.new + + def record suite, method, assertions, time, error + end + def location e # :nodoc: last_before_assertion = "" e.backtrace.reverse_each do |s| @@ -838,6 +881,7 @@ module MiniTest # exception +e+ def puke klass, meth, e + self.last_error = e e = case e when MiniTest::Skip then @skips += 1 @@ -859,9 +903,10 @@ module MiniTest @report = [] @errors = @failures = @skips = 0 @verbose = false + self.last_error = nil end - def process_args args = [] + def process_args args = [] # :nodoc: options = {} orig_args = args.dup @@ -882,7 +927,7 @@ module MiniTest options[:verbose] = true end - opts.on '-n', '--name PATTERN', "Filter test names on pattern." do |a| + opts.on '-n', '--name PATTERN', "Filter test names on pattern (e.g. /foo/)" do |a| options[:filter] = a end @@ -945,12 +990,61 @@ module MiniTest end ## + # Provides a simple set of guards that you can use in your tests + # to skip execution if it is not applicable. These methods are + # mixed into TestCase as both instance and class methods so you + # can use them inside or outside of the test methods. + # + # def test_something_for_mri + # skip "bug 1234" if jruby? + # # ... + # end + # + # if windows? then + # # ... lots of test methods ... + # end + + module Guard + + ## + # Is this running on jruby? + + def jruby? platform = RUBY_PLATFORM + "java" == platform + end + + ## + # Is this running on mri? + + def mri? platform = RUBY_DESCRIPTION + /^ruby/ =~ platform + end + + ## + # Is this running on rubinius? + + def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE + "rbx" == platform + end + + ## + # Is this running on windows? + + def windows? platform = RUBY_PLATFORM + /mswin|mingw/ =~ platform + end + end + + ## # Subclass TestCase to create your own tests. Typically you'll want a # TestCase subclass per implementation class. # # See MiniTest::Assertions class TestCase + include Guard + extend Guard + attr_reader :__name__ # :nodoc: PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, @@ -963,16 +1057,21 @@ module MiniTest def run runner trap "INFO" do + runner.report.each_with_index do |msg, i| + warn "\n%3d) %s" % [i + 1, msg] + end + warn '' time = runner.start_time ? Time.now - runner.start_time : 0 - warn "%s#%s %.2fs" % [self.class, self.__name__, time] + warn "Current Test: %s#%s %.2fs" % [self.class, self.__name__, time] runner.status $stderr end if SUPPORTS_INFO_SIGNAL result = "" begin @passed = nil + self.before_setup self.setup - self.run_setup_hooks + self.after_setup self.run_test self.__name__ result = "." unless io? @passed = true @@ -982,13 +1081,14 @@ module MiniTest @passed = false result = runner.puke self.class, self.__name__, e ensure - begin - self.run_teardown_hooks - self.teardown - rescue *PASSTHROUGH_EXCEPTIONS - raise - rescue Exception => e - result = runner.puke self.class, self.__name__, e + %w{ before_teardown teardown after_teardown }.each do |hook| + begin + self.send hook + rescue *PASSTHROUGH_EXCEPTIONS + raise + rescue Exception => e + result = runner.puke self.class, self.__name__, e + end end trap 'INFO', 'DEFAULT' if SUPPORTS_INFO_SIGNAL end @@ -1008,11 +1108,17 @@ module MiniTest @@current end + ## + # Return the output IO object + def io @__io__ = true MiniTest::Unit.output end + ## + # Have we hooked up the IO yet? + def io? @__io__ end @@ -1030,6 +1136,7 @@ module MiniTest def self.i_suck_and_my_tests_are_order_dependent! class << self + undef_method :test_order if method_defined? :test_order define_method :test_order do :alpha end end end @@ -1075,10 +1182,32 @@ module MiniTest def setup; end ## + # Runs before every test after setup. Use this to refactor test + # initialization. + + def after_setup; end + + ## + # Runs before every setup. Use this to refactor test initialization. + + def before_setup; end + + ## # Runs after every test. Use this to refactor test cleanup. def teardown; end + ## + # Runs after every test before teardown. Use this to refactor test + # initialization. + + def before_teardown; end + + ## + # Runs after every teardown. Use this to refactor test cleanup. + + def after_teardown; end + def self.reset_setup_teardown_hooks # :nodoc: @setup_hooks = [] @teardown_hooks = [] @@ -1189,6 +1318,8 @@ module MiniTest end # class Unit end # module MiniTest +Minitest = MiniTest # because ugh... I typo this all the time + if $DEBUG then module Test # :nodoc: module Unit # :nodoc: |