[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]