ruby-changes:25910
From: ryan <ko1@a...>
Date: Thu, 29 Nov 2012 12:23:32 +0900 (JST)
Subject: [ruby-changes:25910] ryan:r37967 (trunk): Imported minitest 4.3.2 (r8026)
ryan 2012-11-29 12:23:11 +0900 (Thu, 29 Nov 2012) New Revision: 37967 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=37967 Log: Imported minitest 4.3.2 (r8026) Added files: trunk/lib/minitest/hell.rb trunk/lib/minitest/parallel_each.rb Modified files: trunk/ChangeLog trunk/lib/minitest/README.txt trunk/lib/minitest/mock.rb trunk/lib/minitest/pride.rb trunk/lib/minitest/spec.rb trunk/lib/minitest/unit.rb trunk/test/minitest/metametameta.rb trunk/test/minitest/test_minitest_benchmark.rb trunk/test/minitest/test_minitest_mock.rb trunk/test/minitest/test_minitest_spec.rb trunk/test/minitest/test_minitest_unit.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 37966) +++ ChangeLog (revision 37967) @@ -1,3 +1,8 @@ +Thu Nov 29 12:13:54 2012 Ryan Davis <ryand-ruby@z...> + + * lib/minitest/*: Imported minitest 4.3.2 (r8026) + * test/minitest/*: ditto + Thu Nov 29 11:06:06 2012 KOSAKI Motohiro <kosaki.motohiro@g...> * thread.c (thread_start_func_2): remove unused code. When Index: lib/minitest/unit.rb =================================================================== --- lib/minitest/unit.rb (revision 37966) +++ lib/minitest/unit.rb (revision 37967) @@ -7,6 +7,8 @@ require 'optparse' require 'rbconfig' +require 'thread' # required for 1.8 +require 'minitest/parallel_each' ## # Minimal (mostly drop-in) replacement for test-unit. @@ -37,24 +39,36 @@ class Skip < Assertion; end - def self.filter_backtrace bt # :nodoc: - return ["No backtrace"] unless bt + class << self + attr_accessor :backtrace_filter + end - new_bt = [] + class BacktraceFilter # :nodoc: + def filter bt + return ["No backtrace"] unless bt - unless $DEBUG then - bt.each do |line| - break if line =~ /lib\/minitest/ - new_bt << line + new_bt = [] + + unless $DEBUG then + bt.each do |line| + break if line =~ /lib\/minitest/ + new_bt << line + end + + new_bt = bt.reject { |line| line =~ /lib\/minitest/ } if new_bt.empty? + new_bt = bt.dup if new_bt.empty? + else + new_bt = bt.dup end - new_bt = bt.reject { |line| line =~ /lib\/minitest/ } if new_bt.empty? - new_bt = bt.dup if new_bt.empty? - else - new_bt = bt.dup + new_bt end + end - new_bt + self.backtrace_filter = BacktraceFilter.new + + def self.filter_backtrace bt # :nodoc: + backtrace_filter.filter bt end ## @@ -68,14 +82,12 @@ "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 # figure out what diff to use. def self.diff - @diff = if WINDOZE + @diff = if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ then "diff.exe -u" else if system("gdiff", __FILE__, __FILE__) @@ -136,10 +148,11 @@ if result.empty? then klass = exp.class result = [ - "No visible difference.", - "You should look at your implementation of #{klass}#==.", - expect - ].join "\n" + "No visible difference in the #{klass}#inspect output.\n", + "You should look at the implementation of #== on ", + "#{klass} or its members.\n", + expect, + ].join end end end @@ -314,6 +327,8 @@ # "" if you require it to be silent. Pass in a regexp if you want # to pattern match. # + # NOTE: this uses #capture_io, not #capture_subprocess_io. + # # See also: #assert_silent def assert_output stdout = nil, stderr = nil @@ -351,30 +366,30 @@ def assert_raises *exp msg = "#{exp.pop}.\n" if String === exp.last - should_raise = false begin yield - should_raise = true rescue MiniTest::Skip => e - details = "#{msg}#{mu_pp(exp)} exception expected, not" - - if exp.include? MiniTest::Skip then - return e - else - raise e - end + return e if exp.include? MiniTest::Skip + raise e rescue Exception => e - details = "#{msg}#{mu_pp(exp)} exception expected, not" - assert(exp.any? { |ex| - ex.instance_of?(Module) ? e.kind_of?(ex) : ex == e.class - }, exception_details(e, details)) + expected = exp.any? { |ex| + if ex.instance_of? Module then + e.kind_of? ex + else + e.instance_of? ex + end + } + assert expected, proc { + exception_details(e, "#{msg}#{mu_pp(exp)} exception expected, not") + } + return e end exp = exp.first if exp.size == 1 - flunk "#{msg}#{mu_pp(exp)} expected but nothing was raised." if - should_raise + + flunk "#{msg}#{mu_pp(exp)} expected but nothing was raised." end ## @@ -431,6 +446,8 @@ catch(sym) do begin yield + rescue ThreadError => e # wtf?!? 1.8 + threads == suck + default += ", not \:#{e.message[/uncaught throw \`(\w+?)\'/, 1]}" rescue ArgumentError => e # 1.9 exception default += ", not #{e.message.split(/ /).last}" rescue NameError => e # 1.8 exception @@ -446,27 +463,79 @@ # Captures $stdout and $stderr into strings: # # out, err = capture_io do + # puts "Some info" # warn "You did a bad thing" # end # + # assert_match %r%info%, out # assert_match %r%bad%, err + # + # NOTE: For efficiency, this method uses StringIO and does not + # capture IO for subprocesses. Use #capture_subprocess_io for + # that. def capture_io require 'stringio' - orig_stdout, orig_stderr = $stdout, $stderr captured_stdout, captured_stderr = StringIO.new, StringIO.new - $stdout, $stderr = captured_stdout, captured_stderr - yield + synchronize do + orig_stdout, orig_stderr = $stdout, $stderr + $stdout, $stderr = captured_stdout, captured_stderr + begin + yield + ensure + $stdout = orig_stdout + $stderr = orig_stderr + end + end + return captured_stdout.string, captured_stderr.string - ensure - $stdout = orig_stdout - $stderr = orig_stderr end ## + # Captures $stdout and $stderr into strings, using Tempfile to + # ensure that subprocess IO is captured as well. + # + # out, err = capture_subprocess_io do + # system "echo Some info" + # system "echo You did a bad thing 1>&2" + # end + # + # assert_match %r%info%, out + # assert_match %r%bad%, err + # + # NOTE: This method is approximately 10x slower than #capture_io so + # only use it when you need to test the output of a subprocess. + + def capture_subprocess_io + require 'tempfile' + + captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err") + + synchronize do + orig_stdout, orig_stderr = $stdout.dup, $stderr.dup + $stdout.reopen captured_stdout + $stderr.reopen captured_stderr + + begin + yield + + $stdout.rewind + $stderr.rewind + + [captured_stdout.read, captured_stderr.read] + ensure + captured_stdout.unlink + captured_stderr.unlink + $stdout.reopen orig_stdout + $stderr.reopen orig_stderr + end + end + end + + ## # Returns details for exception +e+ def exception_details e, msg @@ -656,10 +725,19 @@ msg ||= "Skipped, no message given" raise MiniTest::Skip, msg, bt end + + ## + # Takes a block and wraps it with the runner's shared mutex. + + def synchronize + Minitest::Unit.runner.synchronize do + yield + end + end end class Unit # :nodoc: - VERSION = "3.4.0" # :nodoc: + VERSION = "4.3.2" # :nodoc: attr_accessor :report, :failures, :errors, :skips # :nodoc: attr_accessor :test_count, :assertion_count # :nodoc: @@ -667,7 +745,6 @@ attr_accessor :help # :nodoc: attr_accessor :verbose # :nodoc: attr_writer :options # :nodoc: - attr_accessor :last_error # :nodoc: ## # Lazy accessor for options. @@ -695,7 +772,8 @@ def self.autorun at_exit { - next if $! # don't run if there was an exception + # don't run if there was a non-exit exception + next if $! and not $!.kind_of? SystemExit # the order here is important. The at_exit handler must be # installed before anyone else gets a chance to install their @@ -810,10 +888,15 @@ end ## - # Runs all the +suites+ for a given +type+. + # Runs all the +suites+ for a given +type+. Runs suites declaring + # a test_order of +:parallel+ in parallel, and everything else + # serial. def _run_suites suites, type - suites.map { |suite| _run_suite suite, type } + parallel, serial = suites.partition { |s| s.test_order == :parallel } + + ParallelEach.new(parallel).map { |suite| _run_suite suite, type } + + serial.map { |suite| _run_suite suite, type } end ## @@ -832,14 +915,10 @@ print "#{suite}##{method} = " if @verbose - @start_time = Time.now - self.last_error = nil + start_time = Time.now if @verbose result = inst.run self - time = Time.now - @start_time - record suite, method, inst._assertions, time, last_error - - print "%.2f s = " % time if @verbose + print "%.2f s = " % (Time.now - start_time) if @verbose print result puts if @verbose @@ -878,7 +957,6 @@ # exception +e+ def puke klass, meth, e - self.last_error = e e = case e when MiniTest::Skip then @skips += 1 @@ -900,9 +978,13 @@ @report = [] @errors = @failures = @skips = 0 @verbose = false - self.last_error = nil + @mutex = Mutex.new end + def synchronize # :nodoc: + @mutex.synchronize { yield } + end + def process_args args = [] # :nodoc: options = {} orig_args = args.dup @@ -1103,10 +1185,33 @@ module Deprecated # :nodoc: - ## - # This entire module is deprecated and slated for removal on 2013-01-01. + ## + # This entire module is deprecated and slated for removal on 2013-01-01. module Hooks + def run_setup_hooks # :nodoc: + _run_hooks self.class.setup_hooks + end + + def _run_hooks hooks # :nodoc: + hooks.each do |hook| + if hook.respond_to?(:arity) && hook.arity == 1 + hook.call(self) + else + hook.call + end + end + end + + def run_teardown_hooks # :nodoc: + _run_hooks self.class.teardown_hooks.reverse + end + end + + ## + # This entire module is deprecated and slated for removal on 2013-01-01. + + module HooksCM ## # Adds a block of code that will be executed before every # TestCase is run. @@ -1114,13 +1219,13 @@ # NOTE: This method is deprecated, use before/after_setup. It # will be removed on 2013-01-01. - def self.add_setup_hook arg=nil, &block + def add_setup_hook arg=nil, &block warn "NOTE: MiniTest::Unit::TestCase.add_setup_hook is deprecated, use before/after_setup via a module (and call super!). It will be removed on 2013-01-01. Called from #{caller.first}" hook = arg || block @setup_hooks << hook end - def self.setup_hooks # :nodoc: + def setup_hooks # :nodoc: if superclass.respond_to? :setup_hooks then superclass.setup_hooks else @@ -1128,20 +1233,6 @@ end + @setup_hooks end - def run_setup_hooks # :nodoc: - _run_hooks self.class.setup_hooks - end - - def _run_hooks hooks # :nodoc: - hooks.each do |hook| - if hook.respond_to?(:arity) && hook.arity == 1 - hook.call(self) - else - hook.call - end - end - end - ## # Adds a block of code that will be executed after every # TestCase is run. @@ -1149,23 +1240,19 @@ # NOTE: This method is deprecated, use before/after_teardown. It # will be removed on 2013-01-01. - def self.add_teardown_hook arg=nil, &block + def add_teardown_hook arg=nil, &block warn "NOTE: MiniTest::Unit::TestCase#add_teardown_hook is deprecated, use before/after_teardown. It will be removed on 2013-01-01. Called from #{caller.first}" hook = arg || block @teardown_hooks << hook end - def self.teardown_hooks # :nodoc: + def teardown_hooks # :nodoc: if superclass.respond_to? :teardown_hooks then superclass.teardown_hooks else [] end + @teardown_hooks end - - def run_teardown_hooks # :nodoc: - _run_hooks self.class.teardown_hooks.reverse - end end end @@ -1178,6 +1265,7 @@ class TestCase include LifecycleHooks include Deprecated::Hooks + extend Deprecated::HooksCM # UGH... I can't wait 'til 2013! include Guard extend Guard @@ -1202,6 +1290,8 @@ runner.status $stderr end if SUPPORTS_INFO_SIGNAL + start_time = Time.now + result = "" begin @passed = nil @@ -1210,11 +1300,15 @@ self.after_setup self.run_test self.__name__ result = "." unless io? + time = Time.now - start_time + runner.record self.class, self.__name__, self._assertions, time, nil @passed = true rescue *PASSTHROUGH_EXCEPTIONS raise rescue Exception => e @passed = false + time = Time.now - start_time + runner.record self.class, self.__name__, self._assertions, time, e result = runner.puke self.class, self.__name__, e ensure %w{ before_teardown teardown after_teardown }.each do |hook| @@ -1278,6 +1372,32 @@ end end + ## + # Make diffs for this TestCase use #pretty_inspect so that diff + # in assert_equal can be more details. NOTE: this is much slower + # than the regular inspect but much more usable for complex + # objects. + + def self.make_my_diffs_pretty! + require 'pp' + + define_method :mu_pp do |o| + o.pretty_inspect + end + end + + ## + # Call this at the top of your tests when you want to run your + # tests in parallel. In doing so, you're admitting that you rule + # and your tests are awesome. + + def self.parallelize_me! + class << self + undef_method :test_order if method_defined? :test_order + define_method :test_order do :parallel end + end + end + def self.inherited klass # :nodoc: @@test_suites[klass] = true klass.reset_setup_teardown_hooks @@ -1296,6 +1416,9 @@ methods = public_instance_methods(true).grep(/^test/).map { |m| m.to_s } case self.test_order + when :parallel + max = methods.size + ParallelEach.new methods.sort.sort_by { rand max } when :random then max = methods.size methods.sort.sort_by { rand max } Index: lib/minitest/pride.rb =================================================================== --- lib/minitest/pride.rb (revision 37966) +++ lib/minitest/pride.rb (revision 37967) @@ -47,7 +47,7 @@ def puts(*o) # :nodoc: o.map! { |s| - s.sub(/Finished tests/) { + s.to_s.sub(/Finished tests/) { @index = 0 'Fabulous tests'.split(//).map { |c| pride(c) Index: lib/minitest/hell.rb =================================================================== --- lib/minitest/hell.rb (revision 0) +++ lib/minitest/hell.rb (revision 37967) @@ -0,0 +1,16 @@ +# 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 Minitest::Unit::TestCase + class << self + alias :old_test_order :test_order + + def test_order # :nodoc: + :parallel + end + end +end Index: lib/minitest/README.txt =================================================================== --- lib/minitest/README.txt (revision 37966) +++ lib/minitest/README.txt (revision 37967) @@ -49,6 +49,17 @@ -- Piotr Szotkowski +Comparing to rspec: + + rspec is a testing DSL. minitest is ruby. + + -- Adam Hawkins, "Bow Before MiniTest" + +minitest doesn't reinvent anything that ruby already provides, like: +classes, modules, inheritance, methods. This means you only have to +learn ruby to use minitest and all of your regular OO practices like +extract-method refactorings still apply. + == FEATURES/PROBLEMS: * minitest/autorun - the easy and explicit way to run all your tests. @@ -93,6 +104,10 @@ def test_that_it_will_not_blend refute_match /^no/i, @meme.will_it_blend? end + + def test_that_will_be_skipped + skip "test this later" + end end === Specs @@ -260,44 +275,75 @@ == 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 mini (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/