From f8e5c7c79e720d3b0af3cb96f27d421f08eb7744 Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 2 May 2013 04:48:43 +0000 Subject: Imported minitest 4.7.4 (r8483) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40553 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 + lib/minitest/README.txt | 155 ++++++++---- lib/minitest/benchmark.rb | 43 ++++ lib/minitest/hell.rb | 8 +- lib/minitest/mock.rb | 6 +- lib/minitest/parallel_each.rb | 46 +++- lib/minitest/spec.rb | 275 +++++++++++---------- lib/minitest/unit.rb | 249 ++++++++----------- test/minitest/test_minitest_benchmark.rb | 16 ++ test/minitest/test_minitest_mock.rb | 43 +++- test/minitest/test_minitest_spec.rb | 129 +++++++--- test/minitest/test_minitest_unit.rb | 398 ++++++++++++++++++++++--------- 12 files changed, 886 insertions(+), 487 deletions(-) diff --git a/ChangeLog b/ChangeLog index 83fb137c98..9ada4d4b03 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Thu May 2 13:42:42 2013 Ryan Davis + + * lib/minitest/*: Imported minitest 4.7.4 (r8483) + * test/minitest/*: ditto + Thu May 2 11:32:22 2013 NAKAMURA Usaku * win32/win32.c (poll_child_status): [experimental] set the cause of diff --git a/lib/minitest/README.txt b/lib/minitest/README.txt index 6430c1b442..368cc3aa4e 100644 --- a/lib/minitest/README.txt +++ b/lib/minitest/README.txt @@ -104,7 +104,7 @@ Given that you'd like to test the following class: 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 @@ -221,6 +221,14 @@ Output is tab-delimited to make it easy to paste into a spreadsheet. end end +A note on stubbing: In order to stub a method, the method must +actually exist prior to stubbing. Use a singleton method to create a +new non-existing method: + + def obj_under_test.fake_method + ... + end + === Customizable Test Runner Types: MiniTest::Unit.runner=(runner) provides an easy way of creating custom @@ -273,54 +281,113 @@ fixture loading: MiniTest::Unit.runner = MiniTestWithTransactions::Unit.new +== FAQ + +=== How to test SimpleDelegates? + +The following implementation and test: + + class Worker < SimpleDelegator + def work + end + end + + describe Worker do + before do + @worker = Worker.new(Object.new) + end + + it "must respond to work" do + @worker.must_respond_to :work + end + end + +outputs a failure: + + 1) Failure: + Worker#test_0001_must respond to work [bug11.rb:16]: + Expected # (Object) to respond to #work. + +Worker is a SimpleDelegate which in 1.9+ is a subclass of BasicObject. +Expectations are put on Object (one level down) so the Worker +(SimpleDelegate) hits `method_missing` and delegates down to the +`Object.new` instance. That object doesn't respond to work so the test +fails. + +You can bypass `SimpleDelegate#method_missing` by extending the worker +with `MiniTest::Expectations`. You can either do that in your setup at +the instance level, like: + + before do + @worker = Worker.new(Object.new) + @worker.extend MiniTest::Expectations + end + +or you can extend the Worker class (within the test file!), like: + + class Worker + include ::MiniTest::Expectations + end + == 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-rails :: MiniTest integration for Rails 3.x -minitest-rails-capybara :: Capybara integration for MiniTest::Rails -minitest-reporters :: Create customizable MiniTest output formats -minitest-rg :: redgreen minitest -minitest-shouldify :: Adding all manner of shoulds to MiniTest (bad idea) -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. -pry-rescue :: A pry plugin w/ minitest support. See pry-rescue/minitest.rb. +capybara_minitest_spec :: Bridge between Capybara RSpec matchers and MiniTest::Spec expectations (e.g. page.must_have_content('Title')). +minispec-metadata :: Metadata for describe/it blocks + (e.g. `it 'requires JS driver', js: true do`) +minitest-ansi :: Colorize minitest output with ANSI colors. +minitest-around :: Around block for minitest. An alternative to setup/teardown dance. +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-english :: Semantically symmetric aliases for assertions and expectations. +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-great_expectations :: Generally useful additions to minitest's assertions and expectations +minitest-growl :: Test notifier for minitest via growl. +minitest-implicit-subject :: Implicit declaration of the test subject. +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-nc :: Test notifier for minitest via Mountain Lion's Notification Center +minitest-predicates :: Adds support for .predicate? methods +minitest-rails :: MiniTest integration for Rails 3.x +minitest-rails-capybara :: Capybara integration for MiniTest::Rails +minitest-reporters :: Create customizable MiniTest output formats +minitest-should_syntax :: RSpec-style +x.should == y+ assertions for MiniTest +minitest-shouldify :: Adding all manner of shoulds to MiniTest (bad idea) +minitest-spec-context :: Provides rspec-ish context method to MiniTest::Spec +minitest-spec-magic :: Minitest::Spec extensions for Rails and beyond +minitest-spec-rails :: Drop in MiniTest::Spec superclass for ActiveSupport::TestCase. +minitest-stub-const :: Stub constants for the duration of a block +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. +pry-rescue :: A pry plugin w/ minitest support. See pry-rescue/minitest.rb. == Unknown Extensions: Authors... Please send me a pull request with a description of your minitest extension. * assay-minitest -* capybara_minitest_spec * detroit-minitest * em-minitest-spec * flexmock-minitest @@ -328,16 +395,12 @@ Authors... Please send me a pull request with a description of your minitest ext * guard-minitest-decisiv * minitest-activemodel * minitest-ar-assertions -* minitest-around * minitest-capybara-unit * minitest-colorer * minitest-deluxe * minitest-extra-assertions -* minitest-nc * minitest-rails-shoulda * minitest-spec -* minitest-spec-context -* minitest-spec-rails * minitest-spec-should * minitest-sugar * minitest_should @@ -358,7 +421,7 @@ the gem, but you'll need to activate the gem explicitly to use it: require 'rubygems' gem 'minitest' # ensures you're using the gem, and not the built in MT require 'minitest/autorun' - + # ... usual testing stuffs ... DO NOTE: There is a serious problem with the way that ruby 1.9/2.0 diff --git a/lib/minitest/benchmark.rb b/lib/minitest/benchmark.rb index 02121db340..e233282b0a 100644 --- a/lib/minitest/benchmark.rb +++ b/lib/minitest/benchmark.rb @@ -161,6 +161,26 @@ class MiniTest::Unit # :nodoc: assert_performance validation_for_fit(:exponential, threshold), &work end + ## + # Runs the given +work+ and asserts that the times gathered fit to + # match a logarithmic curve within a given error +threshold+. + # + # Fit is calculated by #fit_logarithmic. + # + # Ranges are specified by ::bench_range. + # + # Eg: + # + # def bench_algorithm + # assert_performance_logarithmic 0.9999 do |n| + # @obj.algorithm(n) + # end + # end + + def assert_performance_logarithmic threshold = 0.99, &work + assert_performance validation_for_fit(:logarithmic, threshold), &work + end + ## # Runs the given +work+ and asserts that the times gathered fit to # match a straight line within a given error +threshold+. @@ -236,6 +256,29 @@ class MiniTest::Unit # :nodoc: return Math.exp(a), b, fit_error(xys) { |x| Math.exp(a + b * x) } end + ## + # To fit a functional form: y = a + b*ln(x). + # + # Takes x and y values and returns [a, b, r^2]. + # + # See: http://mathworld.wolfram.com/LeastSquaresFittingLogarithmic.html + + def fit_logarithmic xs, ys + n = xs.size + xys = xs.zip(ys) + slnx2 = sigma(xys) { |x,y| Math.log(x) ** 2 } + slnx = sigma(xys) { |x,y| Math.log(x) } + sylnx = sigma(xys) { |x,y| y * Math.log(x) } + sy = sigma(xys) { |x,y| y } + + c = n * slnx2 - slnx ** 2 + b = ( n * sylnx - sy * slnx ) / c + a = (sy - b * slnx) / n + + return a, b, fit_error(xys) { |x| a + b * Math.log(x) } + end + + ## # Fits the functional form: a + bx. # diff --git a/lib/minitest/hell.rb b/lib/minitest/hell.rb index 0e4101f3f8..827bf0e320 100644 --- a/lib/minitest/hell.rb +++ b/lib/minitest/hell.rb @@ -5,12 +5,16 @@ # File a patch instead and assign it to Ryan Davis. ###################################################################### -class Minitest::Unit::TestCase # :nodoc: +require "minitest/parallel_each" + +# :stopdoc: +class Minitest::Unit::TestCase class << self alias :old_test_order :test_order - def test_order # :nodoc: + def test_order :parallel end end end +# :startdoc: diff --git a/lib/minitest/mock.rb b/lib/minitest/mock.rb index c636b9e901..a5b0f602f5 100644 --- a/lib/minitest/mock.rb +++ b/lib/minitest/mock.rb @@ -5,8 +5,7 @@ # File a patch instead and assign it to Ryan Davis. ###################################################################### -class MockExpectationError < StandardError # :nodoc: -end # omg... worst bug ever. rdoc doesn't allow 1-liners +class MockExpectationError < StandardError; end # :nodoc: ## # A simple and clean mock object framework. @@ -159,7 +158,8 @@ class Object # :nodoc: # Add a temporary stubbed method replacing +name+ for the duration # of the +block+. If +val_or_callable+ responds to #call, then it # returns the result of calling it, otherwise returns the value - # as-is. Cleans up the stub at the end of the +block+. + # as-is. Cleans up the stub at the end of the +block+. The method + # +name+ must exist before stubbing. # # def test_stale_eh # obj_under_test = Something.new diff --git a/lib/minitest/parallel_each.rb b/lib/minitest/parallel_each.rb index d501aa34ef..e1020b35a0 100644 --- a/lib/minitest/parallel_each.rb +++ b/lib/minitest/parallel_each.rb @@ -5,12 +5,24 @@ # File a patch instead and assign it to Ryan Davis. ###################################################################### +## +# Provides a parallel #each that lets you enumerate using N threads. +# Use environment variable N to customize. Defaults to 2. Enumerable, +# so all the goodies come along (tho not all are wrapped yet to +# return another ParallelEach instance). + class ParallelEach require 'thread' include Enumerable + ## + # How many Threads to use for this parallel #each. + N = (ENV['N'] || 2).to_i + ## + # Create a new ParallelEach instance over +list+. + def initialize list @queue = Queue.new # *sigh*... the Queue api sucks sooo much... @@ -18,10 +30,20 @@ class ParallelEach N.times { @queue << nil } end - def grep pattern + def grep pattern # :nodoc: self.class.new super end + def select(&block) # :nodoc: + self.class.new super + end + + alias find_all select # :nodoc: + + ## + # Starts N threads that yield each element to your block. Joins the + # threads at the end. + def each threads = N.times.map { Thread.new do @@ -33,4 +55,26 @@ class ParallelEach } threads.map(&:join) end + + def count + [@queue.size - N, 0].max + end + + alias_method :size, :count +end + +class MiniTest::Unit + alias _old_run_suites _run_suites + + ## + # 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 + 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 end diff --git a/lib/minitest/spec.rb b/lib/minitest/spec.rb index 7588982038..c8584f6e4a 100644 --- a/lib/minitest/spec.rb +++ b/lib/minitest/spec.rb @@ -66,7 +66,7 @@ module Kernel # :nodoc: def describe desc, additional_desc = nil, &block # :doc: stack = MiniTest::Spec.describe_stack name = [stack.last, desc, additional_desc].compact.join("::") - sclas = stack.last || if Class === self && self < MiniTest::Spec then + sclas = stack.last || if Class === self && is_a?(MiniTest::Spec::DSL) then self else MiniTest::Spec.spec_type desc @@ -88,173 +88,184 @@ end # For a list of expectations, see MiniTest::Expectations. class MiniTest::Spec < MiniTest::Unit::TestCase - ## - # Contains pairs of matchers and Spec classes to be used to - # calculate the superclass of a top-level describe. This allows for - # automatically customizable spec types. - # - # See: register_spec_type and spec_type - - TYPES = [[//, MiniTest::Spec]] - - ## - # Register a new type of spec that matches the spec's description. - # This method can take either a Regexp and a spec class or a spec - # class and a block that takes the description and returns true if - # it matches. - # - # Eg: - # - # register_spec_type(/Controller$/, MiniTest::Spec::Rails) - # - # or: - # - # register_spec_type(MiniTest::Spec::RailsModel) do |desc| - # desc.superclass == ActiveRecord::Base - # end - - def self.register_spec_type(*args, &block) - if block then - matcher, klass = block, args.first - else - matcher, klass = *args - end - TYPES.unshift [matcher, klass] - end ## - # Figure out the spec class to use based on a spec's description. Eg: - # - # spec_type("BlahController") # => MiniTest::Spec::Rails - - def self.spec_type desc - TYPES.find { |matcher, klass| - if matcher.respond_to? :call then - matcher.call desc + # Oh look! A MiniTest::Spec::DSL module! Eat your heart out DHH. + + module DSL + ## + # Contains pairs of matchers and Spec classes to be used to + # calculate the superclass of a top-level describe. This allows for + # automatically customizable spec types. + # + # See: register_spec_type and spec_type + + TYPES = [[//, MiniTest::Spec]] + + ## + # Register a new type of spec that matches the spec's description. + # This method can take either a Regexp and a spec class or a spec + # class and a block that takes the description and returns true if + # it matches. + # + # Eg: + # + # register_spec_type(/Controller$/, MiniTest::Spec::Rails) + # + # or: + # + # register_spec_type(MiniTest::Spec::RailsModel) do |desc| + # desc.superclass == ActiveRecord::Base + # end + + def register_spec_type(*args, &block) + if block then + matcher, klass = block, args.first else - matcher === desc.to_s + matcher, klass = *args end - }.last - end - - @@describe_stack = [] - def self.describe_stack # :nodoc: - @@describe_stack - end + TYPES.unshift [matcher, klass] + end - ## - # Returns the children of this spec. + ## + # Figure out the spec class to use based on a spec's description. Eg: + # + # spec_type("BlahController") # => MiniTest::Spec::Rails - def self.children - @children ||= [] - end + def spec_type desc + TYPES.find { |matcher, klass| + if matcher.respond_to? :call then + matcher.call desc + else + matcher === desc.to_s + end + }.last + end - def self.nuke_test_methods! # :nodoc: - self.public_instance_methods.grep(/^test_/).each do |name| - self.send :undef_method, name + @@describe_stack = [] + def describe_stack # :nodoc: + @@describe_stack end - end - ## - # Define a 'before' action. Inherits the way normal methods should. - # - # NOTE: +type+ is ignored and is only there to make porting easier. - # - # Equivalent to MiniTest::Unit::TestCase#setup. + ## + # Returns the children of this spec. - def self.before type = nil, &block - define_method :setup do - super() - self.instance_eval(&block) + def children + @children ||= [] end - end - ## - # Define an 'after' action. Inherits the way normal methods should. - # - # NOTE: +type+ is ignored and is only there to make porting easier. - # - # Equivalent to MiniTest::Unit::TestCase#teardown. + def nuke_test_methods! # :nodoc: + self.public_instance_methods.grep(/^test_/).each do |name| + self.send :undef_method, name + end + end - def self.after type = nil, &block - define_method :teardown do - self.instance_eval(&block) - super() + ## + # Define a 'before' action. Inherits the way normal methods should. + # + # NOTE: +type+ is ignored and is only there to make porting easier. + # + # Equivalent to MiniTest::Unit::TestCase#setup. + + def before type = nil, &block + define_method :setup do + super() + self.instance_eval(&block) + end end - end - ## - # Define an expectation with name +desc+. Name gets morphed to a - # proper test method name. For some freakish reason, people who - # write specs don't like class inheritence, so this goes way out of - # its way to make sure that expectations aren't inherited. - # - # This is also aliased to #specify and doesn't require a +desc+ arg. - # - # Hint: If you _do_ want inheritence, use minitest/unit. You can mix - # and match between assertions and expectations as much as you want. + ## + # Define an 'after' action. Inherits the way normal methods should. + # + # NOTE: +type+ is ignored and is only there to make porting easier. + # + # Equivalent to MiniTest::Unit::TestCase#teardown. + + def after type = nil, &block + define_method :teardown do + self.instance_eval(&block) + super() + end + end + + ## + # Define an expectation with name +desc+. Name gets morphed to a + # proper test method name. For some freakish reason, people who + # write specs don't like class inheritance, so this goes way out of + # its way to make sure that expectations aren't inherited. + # + # This is also aliased to #specify and doesn't require a +desc+ arg. + # + # Hint: If you _do_ want inheritence, use minitest/unit. You can mix + # and match between assertions and expectations as much as you want. + + def it desc = "anonymous", &block + block ||= proc { skip "(no tests defined)" } - def self.it desc = "anonymous", &block - block ||= proc { skip "(no tests defined)" } + @specs ||= 0 + @specs += 1 - @specs ||= 0 - @specs += 1 + name = "test_%04d_%s" % [ @specs, desc ] - name = "test_%04d_%s" % [ @specs, desc ] + define_method name, &block - define_method name, &block + self.children.each do |mod| + mod.send :undef_method, name if mod.public_method_defined? name + end - self.children.each do |mod| - mod.send :undef_method, name if mod.public_method_defined? name + name end - name - end + ## + # Essentially, define an accessor for +name+ with +block+. + # + # Why use let instead of def? I honestly don't know. - ## - # Essentially, define an accessor for +name+ with +block+. - # - # Why use let instead of def? I honestly don't know. + def let name, &block + define_method name do + @_memoized ||= {} + @_memoized.fetch(name) { |k| @_memoized[k] = instance_eval(&block) } + end + end - def self.let name, &block - define_method name do - @_memoized ||= {} - @_memoized.fetch(name) { |k| @_memoized[k] = instance_eval(&block) } + ## + # Another lazy man's accessor generator. Made even more lazy by + # setting the name for you to +subject+. + + def subject &block + let :subject, &block end - end - ## - # Another lazy man's accessor generator. Made even more lazy by - # setting the name for you to +subject+. + def create name, desc # :nodoc: + cls = Class.new(self) do + @name = name + @desc = desc - def self.subject &block - let :subject, &block - end + nuke_test_methods! + end - def self.create name, desc # :nodoc: - cls = Class.new(self) do - @name = name - @desc = desc + children << cls - nuke_test_methods! + cls end - children << cls - - cls - end + def name # :nodoc: + defined?(@name) ? @name : super + end - def self.to_s # :nodoc: - defined?(@name) ? @name : super - end + def to_s # :nodoc: + name # Can't alias due to 1.8.7, not sure why + end - # :stopdoc: - class << self + # :stopdoc: attr_reader :desc alias :specify :it - alias :name :to_s + # :startdoc: end - # :startdoc: + + extend DSL + + TYPES = DSL::TYPES # :nodoc: end ## diff --git a/lib/minitest/unit.rb b/lib/minitest/unit.rb index a221dda4b4..a29c8ec93b 100644 --- a/lib/minitest/unit.rb +++ b/lib/minitest/unit.rb @@ -5,10 +5,8 @@ # File a patch instead and assign it to Ryan Davis. ###################################################################### -require 'optparse' -require 'rbconfig' -require 'thread' # required for 1.8 -require 'minitest/parallel_each' +require "optparse" +require "rbconfig" ## # Minimal (mostly drop-in) replacement for test-unit. @@ -40,6 +38,9 @@ module MiniTest class Skip < Assertion; end class << self + ## + # Filter object for backtraces. + attr_accessor :backtrace_filter end @@ -87,16 +88,17 @@ module MiniTest # figure out what diff to use. def self.diff - @diff = if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ then + @diff = if (RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ && + system("diff.exe", __FILE__, __FILE__)) then "diff.exe -u" + elsif Minitest::Unit::Guard.maglev? then # HACK + "diff -u" + elsif system("gdiff", __FILE__, __FILE__) + "gdiff -u" # solaris and kin suck + elsif system("diff", __FILE__, __FILE__) + "diff -u" else - if system("gdiff", __FILE__, __FILE__) - "gdiff -u" # solaris and kin suck - elsif system("diff", __FILE__, __FILE__) - "diff -u" - else - nil - end + nil end unless defined? @diff @diff @@ -177,8 +179,8 @@ module MiniTest # newlines and makes hex-values generic (like object_ids). This # uses mu_pp to do the first pass and then cleans it up. - def mu_pp_for_diff obj # TODO: possibly rename - mu_pp(obj).gsub(/\\n/, "\n").gsub(/0x[a-f0-9]+/m, '0xXXXXXX') + def mu_pp_for_diff obj + mu_pp(obj).gsub(/\\n/, "\n").gsub(/:0x[a-fA-F0-9]{4,}/m, ':0xXXXXXX') end def _assertions= n # :nodoc: @@ -202,18 +204,6 @@ module MiniTest true end - ## - # Fails unless the block returns a true value. - # - # NOTE: This method is deprecated, use assert. It will be removed - # on 2013-01-01." - - def assert_block msg = nil - warn "NOTE: MiniTest::Unit::TestCase#assert_block is deprecated, use assert. It will be removed on 2013-01-01. Called from #{caller.first}" - msg = message(msg) { "Expected block to return true value" } - assert yield, msg - end - ## # Fails unless +obj+ is empty. @@ -237,7 +227,7 @@ module MiniTest def assert_equal exp, act, msg = nil msg = message(msg, "") { diff exp, act } - assert(exp == act, msg) + assert exp == act, msg end ## @@ -248,7 +238,9 @@ 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 @@ -562,6 +554,7 @@ module MiniTest def message msg = nil, ending = ".", &default proc { + msg = msg.call.chomp(".") if Proc === msg custom_message = "#{msg}.\n" unless msg.nil? or msg.to_s.empty? "#{custom_message}#{default.call}#{ending}" } @@ -611,9 +604,9 @@ module MiniTest 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 + refute delta >= n, msg end ## @@ -723,9 +716,17 @@ module MiniTest def skip msg = nil, bt = caller msg ||= "Skipped, no message given" + @skip = true raise MiniTest::Skip, msg, bt end + ## + # Was this testcase skipped? Meant for #teardown. + + def skipped? + defined?(@skip) and @skip + end + ## # Takes a block and wraps it with the runner's shared mutex. @@ -737,15 +738,27 @@ module MiniTest end class Unit # :nodoc: - VERSION = "4.3.2" # :nodoc: + VERSION = "4.7.4" # :nodoc: attr_accessor :report, :failures, :errors, :skips # :nodoc: - attr_accessor :test_count, :assertion_count # :nodoc: + attr_accessor :assertion_count # :nodoc: + attr_writer :test_count # :nodoc: attr_accessor :start_time # :nodoc: attr_accessor :help # :nodoc: attr_accessor :verbose # :nodoc: attr_writer :options # :nodoc: + ## + # :attr: + # + # if true, installs an "INFO" signal handler (only available to BSD and + # OS X users) which prints diagnostic information about the test run. + # + # This is auto-detected by default but may be overridden by custom + # runners. + + attr_accessor :info_signal + ## # Lazy accessor for options. @@ -847,6 +860,10 @@ module MiniTest output.print(*a) end + def test_count # :nodoc: + @test_count ||= 0 + end + ## # Runner for a given +type+ (eg, test vs bench). @@ -888,15 +905,13 @@ module MiniTest end ## - # Runs all the +suites+ for a given +type+. Runs suites declaring - # a test_order of +:parallel+ in parallel, and everything else - # serial. + # Runs all the +suites+ for a given +type+. + # + # NOTE: this method is redefined in parallel_each.rb, which is + # loaded if a test-suite calls parallelize_me!. def _run_suites suites, 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 } + suites.map { |suite| _run_suite suite, type } end ## @@ -909,7 +924,13 @@ module MiniTest filter = options[:filter] || '/./' filter = Regexp.new $1 if filter =~ /\/(.*)\// - assertions = suite.send("#{type}_methods").grep(filter).map { |method| + all_test_methods = suite.send "#{type}_methods" + + filtered_test_methods = all_test_methods.find_all { |m| + filter === m || filter === "#{suite}##{m}" + } + + assertions = filtered_test_methods.map { |method| inst = suite.new method inst._assertions = 0 @@ -929,7 +950,7 @@ module MiniTest end ## - # Record the result of a single run. Makes it very easy to gather + # Record the result of a single test. Makes it very easy to gather # information. Eg: # # class StatisticsRecorder < MiniTest::Unit @@ -939,6 +960,11 @@ module MiniTest # end # # MiniTest::Unit.runner = StatisticsRecorder.new + # + # NOTE: record might be sent more than once per test. It will be + # sent once with the results from the test itself. If there is a + # failure or error in teardown, it will be sent again with the + # error or failure. def record suite, method, assertions, time, error end @@ -961,14 +987,14 @@ module MiniTest when MiniTest::Skip then @skips += 1 return "S" unless @verbose - "Skipped:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n" + "Skipped:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n" when MiniTest::Assertion then @failures += 1 - "Failure:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n" + "Failure:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n" else @errors += 1 bt = MiniTest::filter_backtrace(e.backtrace).join "\n " - "Error:\n#{meth}(#{klass}):\n#{e.class}: #{e.message}\n #{bt}\n" + "Error:\n#{klass}##{meth}:\n#{e.class}: #{e.message}\n #{bt}\n" end @report << e e[0, 1] @@ -978,11 +1004,16 @@ module MiniTest @report = [] @errors = @failures = @skips = 0 @verbose = false - @mutex = Mutex.new + @mutex = defined?(Mutex) ? Mutex.new : nil + @info_signal = Signal.list['INFO'] end def synchronize # :nodoc: - @mutex.synchronize { yield } + if @mutex then + @mutex.synchronize { yield } + else + yield + end end def process_args args = [] # :nodoc: @@ -1039,7 +1070,8 @@ module MiniTest # Top level driver, controls all output and filtering. def _run args = [] - self.options = process_args args + args = process_args args # ARGH!! blame test/unit process_args + self.options.merge! args puts "Run options: #{help}" @@ -1048,7 +1080,7 @@ module MiniTest break unless report.empty? end - return failures + errors if @test_count > 0 # or return nil... + return failures + errors if self.test_count > 0 # or return nil... rescue Interrupt abort 'Interrupted' end @@ -1095,6 +1127,15 @@ module MiniTest ## # Is this running on mri? + def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE + "maglev" == platform + end + + module_function :maglev? + + ## + # Is this running on mri? + def mri? platform = RUBY_DESCRIPTION /^ruby/ =~ platform end @@ -1183,79 +1224,6 @@ module MiniTest def after_teardown; end end - module Deprecated # :nodoc: - - ## - # 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. - # - # NOTE: This method is deprecated, use before/after_setup. It - # will be removed on 2013-01-01. - - 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 setup_hooks # :nodoc: - if superclass.respond_to? :setup_hooks then - superclass.setup_hooks - else - [] - end + @setup_hooks - end - - ## - # Adds a block of code that will be executed after every - # TestCase is run. - # - # NOTE: This method is deprecated, use before/after_teardown. It - # will be removed on 2013-01-01. - - 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 teardown_hooks # :nodoc: - if superclass.respond_to? :teardown_hooks then - superclass.teardown_hooks - else - [] - end + @teardown_hooks - end - end - end - ## # Subclass TestCase to create your own tests. Typically you'll want a # TestCase subclass per implementation class. @@ -1264,8 +1232,6 @@ module MiniTest class TestCase include LifecycleHooks - include Deprecated::Hooks - extend Deprecated::HooksCM # UGH... I can't wait 'til 2013! include Guard extend Guard @@ -1274,8 +1240,6 @@ module MiniTest PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, Interrupt, SystemExit] # :nodoc: - SUPPORTS_INFO_SIGNAL = Signal.list['INFO'] # :nodoc: - ## # Runs the tests reporting the status to +runner+ @@ -1288,7 +1252,7 @@ module MiniTest time = runner.start_time ? Time.now - runner.start_time : 0 warn "Current Test: %s#%s %.2fs" % [self.class, self.__name__, time] runner.status $stderr - end if SUPPORTS_INFO_SIGNAL + end if runner.info_signal start_time = Time.now @@ -1306,7 +1270,7 @@ module MiniTest rescue *PASSTHROUGH_EXCEPTIONS raise rescue Exception => e - @passed = false + @passed = Skip === e time = Time.now - start_time runner.record self.class, self.__name__, self._assertions, time, e result = runner.puke self.class, self.__name__, e @@ -1318,10 +1282,11 @@ module MiniTest raise rescue Exception => e @passed = false + runner.record self.class, self.__name__, self._assertions, time, e result = runner.puke self.class, self.__name__, e end end - trap 'INFO', 'DEFAULT' if SUPPORTS_INFO_SIGNAL + trap 'INFO', 'DEFAULT' if runner.info_signal end result end @@ -1332,11 +1297,11 @@ module MiniTest @__name__ = name @__io__ = nil @passed = nil - @@current = self + @@current = self # FIX: make thread local end def self.current # :nodoc: - @@current + @@current # FIX: make thread local end ## @@ -1392,6 +1357,8 @@ module MiniTest # and your tests are awesome. def self.parallelize_me! + require "minitest/parallel_each" + class << self undef_method :test_order if method_defined? :test_order define_method :test_order do :parallel end @@ -1400,7 +1367,6 @@ module MiniTest def self.inherited klass # :nodoc: @@test_suites[klass] = true - klass.reset_setup_teardown_hooks super end @@ -1448,30 +1414,9 @@ module MiniTest def teardown; end - def self.reset_setup_teardown_hooks # :nodoc: - # also deprecated... believe it. - @setup_hooks = [] - @teardown_hooks = [] - end - - reset_setup_teardown_hooks - include MiniTest::Assertions end # class TestCase end # class Unit end # module MiniTest Minitest = MiniTest # :nodoc: because ugh... I typo this all the time - -if $DEBUG then - module Test # :nodoc: - module Unit # :nodoc: - class TestCase # :nodoc: - def self.inherited x # :nodoc: - # this helps me ferret out porting issues - raise "Using minitest and test/unit in the same process: #{x}" - end - end - end - end -end diff --git a/test/minitest/test_minitest_benchmark.rb b/test/minitest/test_minitest_benchmark.rb index 708589b3fa..8f0aab4904 100644 --- a/test/minitest/test_minitest_benchmark.rb +++ b/test/minitest/test_minitest_benchmark.rb @@ -51,6 +51,22 @@ class TestMiniTestBenchmark < MiniTest::Unit::TestCase assert_fit :exponential, x, y, 0.95, 13.81148, -0.1820 end + def test_fit_logarithmic_clean + x = [1.0, 2.0, 3.0, 4.0, 5.0] + y = x.map { |n| 1.1 + 2.1 * Math.log(n) } + + assert_fit :logarithmic, x, y, 1.0, 1.1, 2.1 + end + + def test_fit_logarithmic_noisy + x = [1.0, 2.0, 3.0, 4.0, 5.0] + # Generated with + # y = x.map { |n| jitter = 0.999 + 0.002 * rand; (Math.log(n) ) * jitter } + y = [0.0, 0.6935, 1.0995, 1.3873, 1.6097] + + assert_fit :logarithmic, x, y, 0.95, 0, 1 + end + def test_fit_constant_clean x = (1..5).to_a y = [5.0, 5.0, 5.0, 5.0, 5.0] diff --git a/test/minitest/test_minitest_mock.rb b/test/minitest/test_minitest_mock.rb index 918ef4c012..7fabb79292 100644 --- a/test/minitest/test_minitest_mock.rb +++ b/test/minitest/test_minitest_mock.rb @@ -5,10 +5,7 @@ # File a patch instead and assign it to Ryan Davis. ###################################################################### -require 'minitest/mock' -require 'minitest/unit' - -MiniTest::Unit.autorun +require 'minitest/autorun' class TestMiniTestMock < MiniTest::Unit::TestCase parallelize_me! if ENV["PARALLEL"] @@ -74,6 +71,8 @@ class TestMiniTestMock < MiniTest::Unit::TestCase end def test_mock_args_does_not_raise + skip "non-opaque use of ==" if maglev? + arg = MiniTest::Mock.new mock = MiniTest::Mock.new mock.expect(:foo, nil, [arg]) @@ -276,7 +275,7 @@ class TestMiniTestMock < MiniTest::Unit::TestCase end end -require_relative "metametameta" +require "minitest/metametameta" class TestMiniTestStub < MiniTest::Unit::TestCase parallelize_me! if ENV["PARALLEL"] @@ -308,6 +307,40 @@ class TestMiniTestStub < MiniTest::Unit::TestCase end end + def test_stub_private_module_method + @assertion_count += 1 + + t0 = Time.now + + self.stub :sleep, nil do + @tc.assert_nil sleep(10) + end + + @tc.assert_operator Time.now - t0, :<=, 1 + end + + def test_stub_private_module_method_indirect + @assertion_count += 1 + + slow_clapper = Class.new do + def slow_clap + sleep 3 + :clap + end + end.new + + slow_clapper.stub :sleep, nil do |fast_clapper| + @tc.assert_equal :clap, fast_clapper.slow_clap # either form works + @tc.assert_equal :clap, slow_clapper.slow_clap # yay closures + end + end + + def test_stub_public_module_method + Math.stub(:log10, 42.0) do + @tc.assert_in_delta 42.0, Math.log10(1000) + end + end + def test_stub_value assert_stub 42 end diff --git a/test/minitest/test_minitest_spec.rb b/test/minitest/test_minitest_spec.rb index 85cb95f42b..96589ede0b 100644 --- a/test/minitest/test_minitest_spec.rb +++ b/test/minitest/test_minitest_spec.rb @@ -6,16 +6,20 @@ ###################################################################### # encoding: utf-8 -require 'minitest/autorun' -require 'stringio' +require "minitest/autorun" +require "stringio" class MiniSpecA < MiniTest::Spec; end -class MiniSpecB < MiniTest::Spec; end +class MiniSpecB < MiniTest::Unit::TestCase; extend MiniTest::Spec::DSL; end +class MiniSpecC < MiniSpecB; end +class NamedExampleA < MiniSpecA; end +class NamedExampleB < MiniSpecB; end +class NamedExampleC < MiniSpecC; end class ExampleA; end class ExampleB < ExampleA; end describe MiniTest::Spec do - # do not parallelize this suite... it just can't handle it. + # do not parallelize this suite... it just can"t handle it. def assert_triggered expected = "blah", klass = MiniTest::Assertion @assertion_count += 2 @@ -25,7 +29,7 @@ describe MiniTest::Spec do end msg = e.message.sub(/(---Backtrace---).*/m, '\1') - msg.gsub!(/\(oid=[-0-9]+\)/, '(oid=N)') + msg.gsub!(/\(oid=[-0-9]+\)/, "(oid=N)") assert_equal expected, msg end @@ -35,7 +39,7 @@ describe MiniTest::Spec do end after do - self._assertions.must_equal @assertion_count + self._assertions.must_equal @assertion_count if passed? and not skipped? end it "needs to be able to catch a MiniTest::Assertion exception" do @@ -84,10 +88,10 @@ describe MiniTest::Spec do it "needs to catch an unexpected exception" do @assertion_count -= 2 # no positive - msg = <<-EOM.gsub(/^ {6}/, '').chomp + msg = <<-EOM.gsub(/^ {6}/, "").chomp [RuntimeError] exception expected, not Class: - Message: <\"MiniTest::Assertion\"> + Message: <"MiniTest::Assertion"> ---Backtrace--- EOM @@ -140,7 +144,7 @@ describe MiniTest::Spec do bad = %w[not raise throw send output be_silent] - expected_wonts = expected_musts.map { |m| m.sub(/^must/, 'wont') } + expected_wonts = expected_musts.map { |m| m.sub(/^must/, "wont") } expected_wonts.reject! { |m| m =~ /wont_#{Regexp.union(*bad)}/ } musts.must_equal expected_musts @@ -162,7 +166,7 @@ describe MiniTest::Spec do it "needs to verify binary messages" do 42.wont_be(:<, 24).must_equal false - assert_triggered 'Expected 24 to not be < 42.' do + assert_triggered "Expected 24 to not be < 42." do 24.wont_be :<, 42 end @@ -202,15 +206,16 @@ describe MiniTest::Spec do 24.wont_be_close_to(42).must_equal false - assert_triggered 'Expected |42 - 42.0| (0.0) to not be < 0.001.' do + assert_triggered "Expected |42 - 42.0| (0.0) to not be <= 0.001." do (6 * 7.0).wont_be_close_to 42 end - assert_triggered 'Expected |42 - 42.0| (0.0) to not be < 1.0e-05.' do + x = maglev? ? "1.0000000000000001e-05" : "1.0e-05" + assert_triggered "Expected |42 - 42.0| (0.0) to not be <= #{x}." do (6 * 7.0).wont_be_close_to 42, 0.00001 end - assert_triggered "msg.\nExpected |42 - 42.0| (0.0) to not be < 1.0e-05." do + assert_triggered "msg.\nExpected |42 - 42.0| (0.0) to not be <= #{x}." do (6 * 7.0).wont_be_close_to 42, 0.00001, "msg" end end @@ -220,15 +225,17 @@ describe MiniTest::Spec do 24.wont_be_within_epsilon(42).must_equal false - assert_triggered 'Expected |42 - 42.0| (0.0) to not be < 0.042.' do + x = maglev? ? "0.042000000000000003" : "0.042" + assert_triggered "Expected |42 - 42.0| (0.0) to not be <= #{x}." do (6 * 7.0).wont_be_within_epsilon 42 end - assert_triggered 'Expected |42 - 42.0| (0.0) to not be < 0.00042.' do + x = maglev? ? "0.00042000000000000002" : "0.00042" + assert_triggered "Expected |42 - 42.0| (0.0) to not be <= #{x}." do (6 * 7.0).wont_be_within_epsilon 42, 0.00001 end - assert_triggered "msg.\nExpected |42 - 42.0| (0.0) to not be < 0.00042." do + assert_triggered "msg.\nExpected |42 - 42.0| (0.0) to not be <= #{x}." do (6 * 7.0).wont_be_within_epsilon 42, 0.00001, "msg" end end @@ -238,15 +245,16 @@ describe MiniTest::Spec do (6.0 * 7).must_be_close_to(42.0).must_equal true - assert_triggered 'Expected |0.0 - 0.01| (0.01) to be < 0.001.' do + assert_triggered "Expected |0.0 - 0.01| (0.01) to be <= 0.001." do (1.0 / 100).must_be_close_to 0.0 end - assert_triggered 'Expected |0.0 - 0.001| (0.001) to be < 1.0e-06.' do + x = maglev? ? "9.9999999999999995e-07" : "1.0e-06" + assert_triggered "Expected |0.0 - 0.001| (0.001) to be <= #{x}." do (1.0 / 1000).must_be_close_to 0.0, 0.000001 end - assert_triggered "msg.\nExpected |0.0 - 0.001| (0.001) to be < 1.0e-06." do + assert_triggered "msg.\nExpected |0.0 - 0.001| (0.001) to be <= #{x}." do (1.0 / 1000).must_be_close_to 0.0, 0.000001, "msg" end end @@ -256,15 +264,15 @@ describe MiniTest::Spec do (6.0 * 7).must_be_within_epsilon(42.0).must_equal true - assert_triggered 'Expected |0.0 - 0.01| (0.01) to be < 0.0.' do + assert_triggered "Expected |0.0 - 0.01| (0.01) to be <= 0.0." do (1.0 / 100).must_be_within_epsilon 0.0 end - assert_triggered 'Expected |0.0 - 0.001| (0.001) to be < 0.0.' do + assert_triggered "Expected |0.0 - 0.001| (0.001) to be <= 0.0." do (1.0 / 1000).must_be_within_epsilon 0.0, 0.000001 end - assert_triggered "msg.\nExpected |0.0 - 0.001| (0.001) to be < 0.0." do + assert_triggered "msg.\nExpected |0.0 - 0.001| (0.001) to be <= 0.0." do (1.0 / 1000).must_be_within_epsilon 0.0, 0.000001, "msg" end end @@ -296,7 +304,7 @@ describe MiniTest::Spec do it "needs to verify instances of a class" do 42.wont_be_instance_of(String).must_equal false - assert_triggered 'Expected 42 to not be an instance of Fixnum.' do + assert_triggered "Expected 42 to not be an instance of Fixnum." do 42.wont_be_instance_of Fixnum end @@ -308,7 +316,7 @@ describe MiniTest::Spec do it "needs to verify kinds of a class" do 42.wont_be_kind_of(String).must_equal false - assert_triggered 'Expected 42 to not be a kind of Integer.' do + assert_triggered "Expected 42 to not be a kind of Integer." do 42.wont_be_kind_of Integer end @@ -361,7 +369,7 @@ describe MiniTest::Spec do it "needs to verify non-emptyness" do @assertion_count += 3 # empty is 2 assertions - ['some item'].wont_be_empty.must_equal false + ["some item"].wont_be_empty.must_equal false assert_triggered "Expected [] to not be empty." do [].wont_be_empty @@ -399,7 +407,7 @@ describe MiniTest::Spec do it "needs to verify objects not responding to a message" do "".wont_respond_to(:woot!).must_equal false - assert_triggered 'Expected "" to not respond to to_s.' do + assert_triggered "Expected \"\" to not respond to to_s." do "".wont_respond_to :to_s end @@ -479,7 +487,7 @@ describe MiniTest::Spec do end it "needs to verify using any (negative) predicate" do - @assertion_count -= 1 # doesn't take a message + @assertion_count -= 1 # doesn"t take a message "blah".wont_be(:empty?).must_equal false @@ -653,6 +661,26 @@ class TestMeta < MiniTest::Unit::TestCase MiniTest::Spec::TYPES.replace original_types end + def test_name + spec_a = describe ExampleA do; end + spec_b = describe ExampleB, :random_method do; end + + assert_equal "ExampleA", spec_a.name + assert_equal "ExampleB::random_method", spec_b.name + end + + def test_name2 + assert_equal "NamedExampleA", NamedExampleA.name + assert_equal "NamedExampleB", NamedExampleB.name + assert_equal "NamedExampleC", NamedExampleC.name + + spec_a = describe ExampleA do; end + spec_b = describe ExampleB, :random_method do; end + + assert_equal "ExampleA", spec_a.name + assert_equal "ExampleB::random_method", spec_b.name + end + def test_structure x, y, z, * = util_structure @@ -700,7 +728,7 @@ class TestMeta < MiniTest::Unit::TestCase z = describe "second thingy" do end end - test_methods = ['test_0001_top level it', 'test_0002_не латинские буквы-и-спецсимволы&いった α, β, γ, δ, ε hello!!! world'].sort + test_methods = ["test_0001_top level it", "test_0002_не латинские буквы-и-спецсимволы&いった α, β, γ, δ, ε hello!!! world"].sort assert_equal test_methods, [x1, x2] assert_equal test_methods, @@ -736,3 +764,48 @@ class TestMeta < MiniTest::Unit::TestCase end end end + +require "minitest/metametameta" + +class TestSpecInTestCase < MetaMetaMetaTestCase + def setup + super + + @tc = MiniTest::Unit::TestCase.new "fake tc" + @assertion_count = 1 + end + + def util_assert_triggered expected, klass = MiniTest::Assertion # REFACTOR + e = assert_raises klass do + yield + end + + msg = e.message.sub(/(---Backtrace---).*/m, "\1") + msg.gsub!(/\(oid=[-0-9]+\)/, "(oid=N)") + + assert_equal expected, msg + end + + def teardown # REFACTOR + assert_equal(@assertion_count, @tc._assertions, + "expected #{@assertion_count} assertions to be fired during the test, not #{@tc._assertions}") if @tc.passed? + end + + def test_expectation + @assertion_count = 2 + + @tc.assert_equal true, 1.must_equal(1) + end + + def test_expectation_triggered + util_assert_triggered "Expected: 2\n Actual: 1" do + 1.must_equal 2 + end + end + + def test_expectation_with_a_message + util_assert_triggered "Expected: 2\n Actual: 1" do + 1.must_equal 2, "" + end + end +end diff --git a/test/minitest/test_minitest_unit.rb b/test/minitest/test_minitest_unit.rb index 65b912e986..199fa0347f 100644 --- a/test/minitest/test_minitest_unit.rb +++ b/test/minitest/test_minitest_unit.rb @@ -6,7 +6,7 @@ ###################################################################### require 'pathname' -require_relative 'metametameta' +require 'minitest/metametameta' module MyModule; end class AnError < StandardError; include MyModule; end @@ -24,30 +24,13 @@ class TestMiniTestUnit < MetaMetaMetaTestCase "#{MINITEST_BASE_DIR}/test.rb:139:in `run'", "#{MINITEST_BASE_DIR}/test.rb:106:in `run'"] - def test_wtf - $hook_value = nil - - capture_io do # don't care about deprecation - MiniTest::Unit::TestCase.add_setup_hook do - $hook_value = 42 - end - end - - run_setup_hooks - - assert_equal 42, $hook_value - assert_equal [Proc], MiniTest::Unit::TestCase.setup_hooks.map(&:class) - MiniTest::Unit::TestCase.reset_setup_teardown_hooks - assert_equal [], MiniTest::Unit::TestCase.setup_hooks.map(&:class) - end - def test_class_puke_with_assertion_failed exception = MiniTest::Assertion.new "Oh no!" exception.set_backtrace ["unhappy"] assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception) assert_equal 1, @tu.failures assert_match(/^Failure.*Oh no!/m, @tu.report.first) - assert_match("method_name(SomeClass) [unhappy]", @tu.report.first) + assert_match("SomeClass#method_name [unhappy]", @tu.report.first) end def test_class_puke_with_assertion_failed_and_long_backtrace @@ -67,7 +50,7 @@ class TestMiniTestUnit < MetaMetaMetaTestCase assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception) assert_equal 1, @tu.failures assert_match(/^Failure.*Oh no!/m, @tu.report.first) - assert_match("test_method_name(TestSomeClass) [#{ex_location}]", @tu.report.first) + assert_match("TestSomeClass#test_method_name [#{ex_location}]", @tu.report.first) end def test_class_puke_with_assertion_failed_and_user_defined_assertions @@ -90,7 +73,7 @@ class TestMiniTestUnit < MetaMetaMetaTestCase assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception) assert_equal 1, @tu.failures assert_match(/^Failure.*Oh no!/m, @tu.report.first) - assert_match("test_method_name(TestSomeClass) [#{ex_location}]", @tu.report.first) + assert_match("TestSomeClass#test_method_name [#{ex_location}]", @tu.report.first) end def test_class_puke_with_failure_and_flunk_in_backtrace @@ -123,7 +106,7 @@ class TestMiniTestUnit < MetaMetaMetaTestCase assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception) assert_equal 1, @tu.failures assert_match(/^Failure.*Oh no!/m, @tu.report.first) - assert_match("test_method_name(TestSomeClass) [#{ex_location}]", @tu.report.first) + assert_match("TestSomeClass#test_method_name [#{ex_location}]", @tu.report.first) end def test_class_puke_with_non_failure_exception @@ -179,42 +162,22 @@ class TestMiniTestUnit < MetaMetaMetaTestCase assert_instance_of MiniTest::Unit, MiniTest::Unit.runner end - def with_overridden_include - Class.class_eval do - def inherited_with_hacks klass - throw :inherited_hook - end - - alias inherited_without_hacks inherited - alias inherited inherited_with_hacks - alias IGNORE_ME! inherited # 1.8 bug. god I love venture bros - end - - yield - ensure - Class.class_eval do - alias inherited inherited_without_hacks - undef_method :inherited_with_hacks - undef_method :inherited_without_hacks + def test_passed_eh_teardown_good + test_class = Class.new MiniTest::Unit::TestCase do + def teardown; assert true; end + def test_omg; assert true; end end - refute_respond_to Class, :inherited_with_hacks - refute_respond_to Class, :inherited_without_hacks - end - - def test_inherited_hook_plays_nice_with_others - with_overridden_include do - assert_throws :inherited_hook do - Class.new MiniTest::Unit::TestCase - end - end + test = test_class.new :test_omg + test.run @tu + assert test.passed? end - def test_passed_eh_teardown_good + def test_passed_eh_teardown_skipped test_class = Class.new MiniTest::Unit::TestCase do def teardown; assert true; end - def test_omg; assert true; end + def test_omg; skip "bork"; end end test = test_class.new :test_omg @@ -242,6 +205,40 @@ class TestMiniTestUnit < MetaMetaMetaTestCase end end +class TestMiniTestUnitInherited < MetaMetaMetaTestCase + def with_overridden_include + Class.class_eval do + def inherited_with_hacks klass + throw :inherited_hook + end + + alias inherited_without_hacks inherited + alias inherited inherited_with_hacks + alias IGNORE_ME! inherited # 1.8 bug. god I love venture bros + end + + yield + ensure + Class.class_eval do + alias inherited inherited_without_hacks + + undef_method :inherited_with_hacks + undef_method :inherited_without_hacks + end + + refute_respond_to Class, :inherited_with_hacks + refute_respond_to Class, :inherited_without_hacks + end + + def test_inherited_hook_plays_nice_with_others + with_overridden_include do + assert_throws :inherited_hook do + Class.new MiniTest::Unit::TestCase + end + end + end +end + class TestMiniTestRunner < MetaMetaMetaTestCase # do not parallelize this suite... it just can't handle it. @@ -297,9 +294,9 @@ class TestMiniTestRunner < MetaMetaMetaTestCase Finished tests in 0.00 1) Error: - test_error(#): + ##test_error: RuntimeError: unhandled exception - FILE:LINE:in `test_error' + FILE:LINE:in \`test_error\' 2 tests, 1 assertions, 0 failures, 1 errors, 0 skips EOM @@ -324,9 +321,9 @@ class TestMiniTestRunner < MetaMetaMetaTestCase Finished tests in 0.00 1) Error: - test_something(#): + ##test_something: RuntimeError: unhandled exception - FILE:LINE:in `teardown' + FILE:LINE:in \`teardown\' 1 tests, 1 assertions, 0 failures, 1 errors, 0 skips EOM @@ -351,7 +348,7 @@ class TestMiniTestRunner < MetaMetaMetaTestCase Finished tests in 0.00 1) Failure: - test_failure(#) [FILE:LINE]: + ##test_failure [FILE:LINE]: Failed assertion, no message given. 2 tests, 2 assertions, 1 failures, 0 errors, 0 skips @@ -382,6 +379,65 @@ class TestMiniTestRunner < MetaMetaMetaTestCase assert_report expected, %w[--name /some|thing/ --seed 42] end + def assert_filtering name, expected, a = false + args = %W[--name #{name} --seed 42] + + alpha = Class.new MiniTest::Unit::TestCase do + define_method :test_something do + assert a + end + end + Object.const_set(:Alpha, alpha) + + beta = Class.new MiniTest::Unit::TestCase do + define_method :test_something do + assert true + end + end + Object.const_set(:Beta, beta) + + assert_report expected, args + ensure + Object.send :remove_const, :Alpha + Object.send :remove_const, :Beta + end + + def test_run_filtered_including_suite_name + expected = clean <<-EOM + . + + Finished tests in 0.00 + + 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips + EOM + + assert_filtering "/Beta#test_something/", expected + end + + def test_run_filtered_including_suite_name_string + expected = clean <<-EOM + . + + Finished tests in 0.00 + + 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips + EOM + + assert_filtering "Beta#test_something", expected + end + + def test_run_filtered_string_method_only + expected = clean <<-EOM + .. + + Finished tests in 0.00 + + 2 tests, 2 assertions, 0 failures, 0 errors, 0 skips + EOM + + assert_filtering "test_something", expected, :pass + end + def test_run_passing Class.new MiniTest::Unit::TestCase do def test_something @@ -441,7 +497,7 @@ class TestMiniTestRunner < MetaMetaMetaTestCase Finished tests in 0.00 1) Skipped: - test_skip(#) [FILE:LINE]: + ##test_skip [FILE:LINE]: not yet 2 tests, 1 assertions, 0 failures, 0 errors, 1 skips @@ -508,7 +564,13 @@ class TestMiniTestRunner < MetaMetaMetaTestCase end end + def test_parallel_each_size + assert_equal 0, ParallelEach.new([]).size + end + def test_run_parallel + skip "I don't have ParallelEach debugged yet" if maglev? + test_count = 2 test_latch = Latch.new test_count main_latch = Latch.new @@ -637,12 +699,12 @@ class TestMiniTestUnitOrder < MetaMetaMetaTestCase def test_setup_and_teardown_survive_inheritance call_order = [] - parent = Class.new MiniTest::Spec do - before do + parent = Class.new MiniTest::Unit::TestCase do + define_method :setup do call_order << :setup_method end - after do + define_method :teardown do call_order << :teardown_method end @@ -665,7 +727,9 @@ class TestMiniTestUnitOrder < MetaMetaMetaTestCase end class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase - parallelize_me! if ENV["PARALLEL"] + # do not call parallelize_me! - teardown accesses @tc._assertions + # which is not threadsafe. Nearly every method in here is an + # assertion test so it isn't worth splitting it out further. RUBY18 = ! defined? Encoding @@ -681,7 +745,7 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase def teardown assert_equal(@assertion_count, @tc._assertions, - "expected #{@assertion_count} assertions to be fired during the test, not #{@tc._assertions}") if @tc._assertions + "expected #{@assertion_count} assertions to be fired during the test, not #{@tc._assertions}") if @tc.passed? end def non_verbose @@ -711,30 +775,6 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase end end - def test_assert_block - exp = ["NOTE: MiniTest::Unit::TestCase#assert_block is deprecated,", - "use assert. It will be removed on 2013-01-01."].join " " - - out, err = capture_io do - @tc.assert_block do - true - end - end - - assert_equal "", out - assert_match exp, err - end - - def test_assert_block_triggered - assert_output do - util_assert_triggered "blah.\nExpected block to return true value." do - @tc.assert_block "blah" do - false - end - end - end - end - def test_assert_empty @assertion_count = 2 @@ -778,6 +818,8 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase end def test_assert_equal_different_diff_deactivated + skip "https://github.com/MagLev/maglev/issues/209" if maglev? + without_diff do util_assert_triggered util_msg("haha" * 10, "blah" * 10) do o1 = "haha" * 10 @@ -890,8 +932,17 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase @tc.assert_in_delta 0.0, 1.0 / 1000, 0.1 end + def test_delta_consistency + @tc.assert_in_delta 0, 1, 1 + + util_assert_triggered "Expected |0 - 1| (1) to not be <= 1." do + @tc.refute_in_delta 0, 1, 1 + end + end + def test_assert_in_delta_triggered - util_assert_triggered 'Expected |0.0 - 0.001| (0.001) to be < 1.0e-06.' do + x = maglev? ? "9.999999xxxe-07" : "1.0e-06" + util_assert_triggered "Expected |0.0 - 0.001| (0.001) to be <= #{x}." do @tc.assert_in_delta 0.0, 1.0 / 1000, 0.000001 end end @@ -913,15 +964,25 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase @tc.assert_in_epsilon(-10000, -9991) end + def test_epsilon_consistency + @tc.assert_in_epsilon 1.0, 1.001 + + msg = "Expected |1.0 - 1.001| (0.000999xxx) to not be <= 0.001." + util_assert_triggered msg do + @tc.refute_in_epsilon 1.0, 1.001 + end + end + def test_assert_in_epsilon_triggered - util_assert_triggered 'Expected |10000 - 9990| (10) to be < 9.99.' do + util_assert_triggered 'Expected |10000 - 9990| (10) to be <= 9.99.' do @tc.assert_in_epsilon 10000, 9990 end end def test_assert_in_epsilon_triggered_negative_case - x = RUBY18 ? "0.1" : "0.10000000000000009" - util_assert_triggered "Expected |-1.1 - -1| (#{x}) to be < 0.1." do + x = (RUBY18 and not maglev?) ? "0.1" : "0.100000xxx" + y = maglev? ? "0.100000xxx" : "0.1" + util_assert_triggered "Expected |-1.1 - -1| (#{x}) to be <= #{y}." do @tc.assert_in_epsilon(-1.1, -1, 0.1) end end @@ -1149,7 +1210,7 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase Class: Message: <\"icky\"> ---Backtrace--- - FILE:LINE:in `test_assert_raises_triggered_different' + FILE:LINE:in \`test_assert_raises_triggered_different\' --------------- EOM @@ -1172,7 +1233,7 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase Class: Message: <\"icky\"> ---Backtrace--- - FILE:LINE:in `test_assert_raises_triggered_different_msg' + FILE:LINE:in \`test_assert_raises_triggered_different_msg\' --------------- EOM @@ -1218,7 +1279,7 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase Class: Message: <\"AnError\"> ---Backtrace--- - FILE:LINE:in `test_assert_raises_triggered_subclass' + FILE:LINE:in \`test_assert_raises_triggered_subclass\' --------------- EOM @@ -1326,7 +1387,7 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase non_verbose do out, err = capture_io do puts 'hi' - warn 'bye!' + $stderr.puts 'bye!' end assert_equal "hi\n", out @@ -1357,7 +1418,7 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase # These don't have corresponding refutes _on purpose_. They're # useless and will never be added, so don't bother. - ignores = %w[assert_block assert_output assert_raises assert_send + ignores = %w[assert_output assert_raises assert_send assert_silent assert_throws] # These are test/unit methods. I'm not actually sure why they're still here @@ -1372,24 +1433,6 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase assert_empty asserts.map { |n| n.sub(/^assert/, 'refute') } - refutes end - def test_expectation - @assertion_count = 2 - - @tc.assert_equal true, 1.must_equal(1) - end - - def test_expectation_triggered - util_assert_triggered "Expected: 2\n Actual: 1" do - 1.must_equal 2 - end - end - - def test_expectation_with_a_message - util_assert_triggered "Expected: 2\n Actual: 1" do - 1.must_equal 2, '' - end - end - def test_flunk util_assert_triggered 'Epic Fail!' do @tc.flunk @@ -1409,6 +1452,36 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase assert_equal "blah2.", @tc.message("") { "blah2" }.call assert_equal "blah1.\nblah2.", @tc.message(:blah1) { "blah2" }.call assert_equal "blah1.\nblah2.", @tc.message("blah1") { "blah2" }.call + + message = proc { "blah1" } + assert_equal "blah1.\nblah2.", @tc.message(message) { "blah2" }.call + + message = @tc.message { "blah1" } + assert_equal "blah1.\nblah2.", @tc.message(message) { "blah2" }.call + end + + def test_message_message + util_assert_triggered "whoops.\nExpected: 1\n Actual: 2" do + @tc.assert_equal 1, 2, message { "whoops" } + end + end + + def test_message_lambda + util_assert_triggered "whoops.\nExpected: 1\n Actual: 2" do + @tc.assert_equal 1, 2, lambda { "whoops" } + end + end + + def test_message_deferred + @assertion_count, var = 0, nil + + msg = message { var = "blah" } + + assert_nil var + + msg.call + + assert_equal "blah", var end def test_pass @@ -1455,18 +1528,19 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase end def test_refute_in_delta_triggered - util_assert_triggered 'Expected |0.0 - 0.001| (0.001) to not be < 0.1.' do + x = maglev? ? "0.100000xxx" : "0.1" + util_assert_triggered "Expected |0.0 - 0.001| (0.001) to not be <= #{x}." do @tc.refute_in_delta 0.0, 1.0 / 1000, 0.1 end end def test_refute_in_epsilon - @tc.refute_in_epsilon 10000, 9990 + @tc.refute_in_epsilon 10000, 9990-1 end def test_refute_in_epsilon_triggered - util_assert_triggered 'Expected |10000 - 9991| (9) to not be < 10.0.' do - @tc.refute_in_epsilon 10000, 9991 + util_assert_triggered 'Expected |10000 - 9990| (10) to not be <= 10.0.' do + @tc.refute_in_epsilon 10000, 9990 fail end end @@ -1613,7 +1687,12 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase end srand 42 - expected = %w(test_test2 test_test1 test_test3) + expected = case + when maglev? then + %w(test_test2 test_test3 test_test1) + else + %w(test_test2 test_test1 test_test3) + end assert_equal expected, sample_test_case.test_methods end @@ -1660,6 +1739,7 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase msg = e.message.sub(/(---Backtrace---).*/m, '\1') msg.gsub!(/\(oid=[-0-9]+\)/, '(oid=N)') + msg.gsub!(/(\d\.\d{6})\d+/, '\1xxx') # normalize: ruby version, impl, platform assert_equal expected, msg end @@ -1703,3 +1783,85 @@ class TestMiniTestGuard < MiniTest::Unit::TestCase assert self.windows? "mswin" end end + +class TestMiniTestUnitRecording < MetaMetaMetaTestCase + # do not parallelize this suite... it just can't handle it. + + def assert_run_record(*expected, &block) + def @tu.record suite, method, assertions, time, error + recording[method] << error + end + + def @tu.recording + @recording ||= Hash.new { |h,k| h[k] = [] } + end + + MiniTest::Unit.runner = @tu + + Class.new MiniTest::Unit::TestCase, &block + + with_output do + @tu.run + end + + recorded = @tu.recording.fetch("test_method").map(&:class) + + assert_equal expected, recorded + end + + def test_record_passing + assert_run_record NilClass do + def test_method + assert true + end + end + end + + def test_record_failing + assert_run_record MiniTest::Assertion do + def test_method + assert false + end + end + end + + def test_record_error + assert_run_record RuntimeError do + def test_method + raise "unhandled exception" + end + end + end + + def test_record_error_teardown + assert_run_record NilClass, RuntimeError do + def test_method + assert true + end + + def teardown + raise "unhandled exception" + end + end + end + + def test_record_error_in_test_and_teardown + assert_run_record AnError, RuntimeError do + def test_method + raise AnError + end + + def teardown + raise "unhandled exception" + end + end + end + + def test_record_skip + assert_run_record MiniTest::Skip do + def test_method + skip "not yet" + end + end + end +end -- cgit v1.2.3