[DRE-commits] [SCM] ruby-minitest.git branch, upstream, updated. upstream/2.1.0-1-g30524d4
Lucas Nussbaum
lucas at lucas-nussbaum.net
Sun Oct 9 11:29:36 UTC 2011
The following commit has been merged in the upstream branch:
commit 30524d450f4759bd0680ef4e78c34648e4ae431f
Author: Lucas Nussbaum <lucas at lucas-nussbaum.net>
Date: Sun Oct 9 12:42:20 2011 +0200
Imported Upstream version 2.6.1
diff --git a/History.txt b/History.txt
index 3a72582..b1ba8ec 100644
--- a/History.txt
+++ b/History.txt
@@ -1,3 +1,102 @@
+=== 2.6.1 / 2011-09-27
+
+* 2 bug fixes:
+
+ * Alias Spec.name from Spec.to_s so it works when @name is nil (nathany)
+ * Fixed assert and refute_operator where second object has a bad == method.
+
+=== 2.6.0 / 2011-09-13
+
+* 2 minor enhancements:
+
+ * Added specify alias for it and made desc optional.
+ * Spec#must_be and #wont_be can be used with predicates (metaskills)
+
+* 1 bug fix:
+
+ * Fixed Mock.respond_to?(var) to work with strings. (holli)
+
+=== 2.5.1 / 2011-08-27
+
+* 2 minor enhancements:
+
+ * Added gem activation for minitest in minitest/autoload to help out 1.9 users
+ * Extended Spec.register_spec_type to allow for procs instead of just regexps.
+
+=== 2.5.0 / 2011-08-18
+
+* 4 minor enhancements:
+
+ * Added 2 more arguments against rspec: let & subject in 9 loc! (emmanuel/luis)
+ * Added TestCase.i_suck_and_my_tests_are_order_dependent!
+ * Extended describe to take an optional method name (2 line change!). (emmanuel)
+ * Refactored and extended minitest/pride to do full 256 color support. (lolcat)
+
+* 1 bug fix:
+
+ * Doc fixes. (chastell)
+
+=== 2.4.0 / 2011-08-09
+
+* 4 minor enhancements:
+
+ * Added simple examples for all expectations.
+ * Improved Mock error output when args mismatch.
+ * Moved all expectations from Object to MiniTest::Expectations.
+ * infect_with_assertions has been removed due to excessive clever
+
+* 4 bug fixes:
+
+ * Fix Assertions#mu_pp to deal with immutable encoded strings. (ferrous26)
+ * Fix minitest/pride for MacRuby (ferrous26)
+ * Made error output less fancy so it is more readable
+ * Mock shouldn't undef === and inspect. (dgraham)
+
+=== 2.3.1 / 2011-06-22
+
+* 1 bug fix:
+
+ * Fixed minitest hoe plugin to be a spermy dep and not depend on itself.
+
+=== 2.3.0 / 2011-06-15
+
+* 5 minor enhancements:
+
+ * Add setup and teardown hooks to MiniTest::TestCase. (phiggins)
+ * Added nicer error messages for MiniTest::Mock. (phiggins)
+ * Allow for less specific expected arguments in Mock. (bhenderson/phiggins)
+ * Made MiniTest::Mock a blank slate. (phiggins)
+ * Refactored minitest/spec to use the hooks instead of define_inheritable_method. (phiggins)
+
+* 2 bug fixes:
+
+ * Fixed TestCase's inherited hook. (dchelimsky/phiggins/jamis, the 'good' neighbor)
+ * MiniTest::Assertions#refute_empty should use mu_pp in the default message. (whatthejeff)
+
+=== 2.2.2 / 2011-06-01
+
+* 2 bug fixes:
+
+ * Got rid of the trailing period in message for assert_equal. (tenderlove)
+ * Windows needs more flushing. (Akio Tajima)
+
+=== 2.2.1 / 2011-05-31
+
+* 1 bug fix:
+
+ * My _ONE_ non-rubygems-using minitest user goes to Seattle.rb!
+
+=== 2.2.0 / 2011-05-29
+
+* 6 minor enhancements:
+
+ * assert_equal (and must_equal) now tries to diff output where it makes sense.
+ * Added Assertions#diff(exp, act) to be used by assert_equal.
+ * Added Assertions#mu_pp_for_diff
+ * Added Assertions.diff and diff=
+ * Moved minitest hoe-plugin from hoe-seattlerb. (erikh)
+ * Skipped tests only output details in verbose mode. (tenderlove+zenspider=xoxo)
+
=== 2.1.0 / 2011-04-11
* 5 minor enhancements:
diff --git a/Manifest.txt b/Manifest.txt
index 018b001..4fe8612 100644
--- a/Manifest.txt
+++ b/Manifest.txt
@@ -4,6 +4,7 @@ Manifest.txt
README.txt
Rakefile
design_rationale.rb
+lib/hoe/minitest.rb
lib/minitest/autorun.rb
lib/minitest/benchmark.rb
lib/minitest/mock.rb
diff --git a/README.txt b/README.txt
index 7b1e6e6..74a319e 100644
--- a/README.txt
+++ b/README.txt
@@ -1,12 +1,24 @@
-= minitest/*
+= minitest/{unit,spec,mock,benchmark}
-* http://rubyforge.org/projects/bfts
+home :: https://github.com/seattlerb/minitest
+rdoc :: http://docs.seattlerb.org/minitest
== DESCRIPTION:
minitest provides a complete suite of testing facilities supporting
TDD, BDD, mocking, and benchmarking.
+ "I had a class with Jim Weirich on testing last week and we were
+ allowed to choose our testing frameworks. Kirk Haines and I were
+ paired up and we cracked open the code for a few test
+ frameworks...
+
+ I MUST say that mintiest is *very* readable / understandable
+ compared to the 'other two' options we looked at. Nicely done and
+ thank you for helping us keep our mental sanity."
+
+ -- Wayne E. Seguin
+
minitest/unit is a small and incredibly fast unit testing framework.
It provides a rich set of assertions to make your tests clean and
readable.
@@ -24,13 +36,18 @@ minitest/mock by Steven Baker, is a beautifully tiny mock object
framework.
minitest/pride shows pride in testing and adds coloring to your test
-output.
+output. I guess it is an example of how to write IO pipes too. :P
minitest/unit is meant to have a clean implementation for language
implementors that need a minimal set of methods to bootstrap a working
test suite. For example, there is no magic involved for test-case
discovery.
+ "Again, I can’t praise enough the idea of a testing/specing
+ framework that I can actually read in full in one sitting!"
+
+ -- Piotr Szotkowski
+
== FEATURES/PROBLEMS:
* minitest/autorun - the easy and explicit way to run all your tests.
@@ -247,7 +264,7 @@ the gem, but you'll need to activate the gem explicitly to use it:
(The MIT License)
-Copyright (c) Ryan Davis, Seattle.rb
+Copyright (c) Ryan Davis, seattle.rb
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/Rakefile b/Rakefile
index 56f7598..25d9b90 100644
--- a/Rakefile
+++ b/Rakefile
@@ -18,6 +18,57 @@ def loc dir
system "find #{dir} -name \\*.rb | xargs wc -l | tail -1"
end
+desc "Find missing expectations"
+task :specs do
+ $:.unshift "lib"
+ require "minitest/unit"
+ require "minitest/spec"
+
+ pos_prefix, neg_prefix = "must", "wont"
+ skip_re = /^(must|wont)$|wont_(throw)|must_(block|not?_|nothing|raise$)/x
+ dont_flip_re = /(must|wont)_(include|respond_to)/
+
+ map = {
+ /(must_throw)s/ => '\1',
+ /(?!not)_same/ => '_be_same_as',
+ /_in_/ => '_be_within_',
+ /_operator/ => '_be',
+ /_includes/ => '_include',
+ /(must|wont)_(.*_of|nil|silent|empty)/ => '\1_be_\2',
+ /must_raises/ => 'must_raise',
+ }
+
+ expectations = MiniTest::Expectations.public_instance_methods.map(&:to_s)
+ assertions = MiniTest::Assertions.public_instance_methods.map(&:to_s)
+
+ assertions.sort.each do |assertion|
+ expectation = case assertion
+ when /^assert/ then
+ assertion.sub(/^assert/, pos_prefix.to_s)
+ when /^refute/ then
+ assertion.sub(/^refute/, neg_prefix.to_s)
+ end
+
+ next unless expectation
+ next if expectation =~ skip_re
+
+ regexp, replacement = map.find { |re, _| expectation =~ re }
+ expectation.sub! regexp, replacement if replacement
+
+ next if expectations.include? expectation
+
+ args = [assertion, expectation].map(&:to_sym).map(&:inspect)
+ args << :reverse if expectation =~ dont_flip_re
+
+ puts
+ puts "##"
+ puts "# :method: #{expectation}"
+ puts "# See MiniTest::Assertions##{assertion}"
+ puts
+ puts "infect_an_assertion #{args.join ", "}"
+ end
+end
+
desc "stupid line count"
task :dickwag do
puts
diff --git a/data.tar.gz.sig b/data.tar.gz.sig
index eb3b1c2..b7560ef 100644
Binary files a/data.tar.gz.sig and b/data.tar.gz.sig differ
diff --git a/lib/hoe/minitest.rb b/lib/hoe/minitest.rb
new file mode 100644
index 0000000..d67a3b8
--- /dev/null
+++ b/lib/hoe/minitest.rb
@@ -0,0 +1,16 @@
+module Hoe::Minitest
+ def initialize_minitest
+ require 'minitest/unit'
+ version = MiniTest::Unit::VERSION.split(/\./).first(2).join(".")
+
+ dependency 'minitest', "~> #{version}", :development unless
+ self.name == "minitest"
+ end
+
+ def define_minitest_tasks
+ self.testlib = :minitest
+
+ # make sure we use the gemmed minitest on 1.9
+ self.test_prelude = 'gem "minitest"'
+ end
+end
diff --git a/lib/minitest/autorun.rb b/lib/minitest/autorun.rb
index 3cf64fc..15bbe43 100644
--- a/lib/minitest/autorun.rb
+++ b/lib/minitest/autorun.rb
@@ -1,3 +1,10 @@
+begin
+ require 'rubygems'
+ gem 'minitest'
+rescue Gem::LoadError
+ # do nothing
+end
+
require 'minitest/unit'
require 'minitest/spec'
require 'minitest/mock'
diff --git a/lib/minitest/mock.rb b/lib/minitest/mock.rb
index 00bee3b..acb978e 100644
--- a/lib/minitest/mock.rb
+++ b/lib/minitest/mock.rb
@@ -9,20 +9,39 @@ module MiniTest
# All mock objects are an instance of Mock
class Mock
+ alias :__respond_to? :respond_to?
+
+ skip_methods = %w(object_id respond_to_missing? inspect === to_s)
+
+ instance_methods.each do |m|
+ undef_method m unless skip_methods.include?(m.to_s) || m =~ /^__/
+ end
+
def initialize # :nodoc:
@expected_calls = {}
@actual_calls = Hash.new {|h,k| h[k] = [] }
end
##
- # Expect that method +name+ is called, optionally with +args+, and
- # returns +retval+.
+ # Expect that method +name+ is called, optionally with +args+, and returns
+ # +retval+.
#
# @mock.expect(:meaning_of_life, 42)
# @mock.meaning_of_life # => 42
#
# @mock.expect(:do_something_with, true, [some_obj, true])
# @mock.do_something_with(some_obj, true) # => true
+ #
+ # +args+ is compared to the expected args using case equality (ie, the
+ # '===' operator), allowing for less specific expectations.
+ #
+ # @mock.expect(:uses_any_string, true, [String])
+ # @mock.uses_any_string("foo") # => true
+ # @mock.verify # => true
+ #
+ # @mock.expect(:uses_one_string, true, ["foo"]
+ # @mock.uses_one_string("bar") # => true
+ # @mock.verify # => raises MockExpectationError
def expect(name, retval, args=[])
@expected_calls[name] = { :retval => retval, :args => args }
@@ -37,25 +56,45 @@ module MiniTest
def verify
@expected_calls.each_key do |name|
expected = @expected_calls[name]
- msg = "expected #{name}, #{expected.inspect}"
- raise MockExpectationError, msg unless
+ msg1 = "expected #{name}, #{expected.inspect}"
+ msg2 = "#{msg1}, got #{@actual_calls[name].inspect}"
+
+ raise MockExpectationError, msg2 if
+ @actual_calls.has_key? name and
+ not @actual_calls[name].include?(expected)
+
+ raise MockExpectationError, msg1 unless
@actual_calls.has_key? name and @actual_calls[name].include?(expected)
end
true
end
def method_missing(sym, *args) # :nodoc:
- raise NoMethodError unless @expected_calls.has_key?(sym)
- raise ArgumentError unless @expected_calls[sym][:args].size == args.size
- retval = @expected_calls[sym][:retval]
- @actual_calls[sym] << { :retval => retval, :args => args }
+ expected = @expected_calls[sym]
+
+ unless expected then
+ raise NoMethodError, "unmocked method %p, expected one of %p" %
+ [sym, @expected_calls.keys.sort_by(&:to_s)]
+ end
+
+ expected_args, retval = expected[:args], expected[:retval]
+
+ unless expected_args.size == args.size
+ raise ArgumentError, "mocked method %p expects %d arguments, got %d" %
+ [sym, expected[:args].size, args.size]
+ end
+
+ @actual_calls[sym] << {
+ :retval => retval,
+ :args => expected_args.zip(args).map { |mod, a| mod if mod === a }
+ }
+
retval
end
- alias :original_respond_to? :respond_to?
def respond_to?(sym) # :nodoc:
- return true if @expected_calls.has_key?(sym)
- return original_respond_to?(sym)
+ return true if @expected_calls.has_key?(sym.to_sym)
+ return __respond_to?(sym)
end
end
end
diff --git a/lib/minitest/pride.rb b/lib/minitest/pride.rb
index ebf6e30..3d9e458 100644
--- a/lib/minitest/pride.rb
+++ b/lib/minitest/pride.rb
@@ -4,32 +4,90 @@ require "minitest/unit"
# Show your testing pride!
class PrideIO
- attr_reader :io
+ ESC = "\e["
+ NND = "#{ESC}0m"
- # stolen from /System/Library/Perl/5.10.0/Term/ANSIColor.pm
- COLORS = (31..36).to_a
- CHARS = ["*"]
+ attr_reader :io
def initialize io
@io = io
- @colors = COLORS.cycle
- @chars = CHARS.cycle
+ # stolen from /System/Library/Perl/5.10.0/Term/ANSIColor.pm
+ # also reference http://en.wikipedia.org/wiki/ANSI_escape_code
+ @colors ||= (31..36).to_a
+ @size = @colors.size
+ @index = 0
+ # io.sync = true
end
def print o
case o
when "." then
- io.print "\e[#{@colors.next}m#{@chars.next}\e[0m"
+ io.print pride o
when "E", "F" then
- io.print "\e[41m\e[37m#{o}\e[0m"
+ io.print "#{ESC}41m#{ESC}37m#{o}#{NND}"
else
io.print o
end
end
+ def puts(*o)
+ o.map! { |s|
+ s.sub(/Finished tests/) {
+ @index = 0
+ 'Fabulous tests'.split(//).map { |c|
+ pride(c)
+ }.join
+ }
+ }
+
+ super
+ end
+
+ def pride string
+ string = "*" if string == "."
+ c = @colors[@index % @size]
+ @index += 1
+ "#{ESC}#{c}m#{string}#{NND}"
+ end
+
def method_missing msg, *args
io.send(msg, *args)
end
end
-MiniTest::Unit.output = PrideIO.new(MiniTest::Unit.output)
+class PrideLOL < PrideIO # inspired by lolcat, but massively cleaned up
+ PI_3 = Math::PI / 3
+
+ def initialize io
+ # walk red, green, and blue around a circle separated by equal thirds.
+ #
+ # To visualize, type this into wolfram-alpha:
+ #
+ # plot (3*sin(x)+3), (3*sin(x+2*pi/3)+3), (3*sin(x+4*pi/3)+3)
+
+ # 6 has wide pretty gradients. 3 == lolcat, about half the width
+ @colors = (0...(6 * 7)).map { |n|
+ n *= 1.0 / 6
+ r = (3 * Math.sin(n ) + 3).to_i
+ g = (3 * Math.sin(n + 2 * PI_3) + 3).to_i
+ b = (3 * Math.sin(n + 4 * PI_3) + 3).to_i
+
+ # Then we take rgb and encode them in a single number using base 6.
+ # For some mysterious reason, we add 16... to clear the bottom 4 bits?
+ # Yes... they're ugly.
+
+ 36 * r + 6 * g + b + 16
+ }
+
+ super
+ end
+
+ def pride string
+ c = @colors[@index % @size]
+ @index += 1
+ "#{ESC}38;5;#{c}m#{string}#{NND}"
+ end
+end
+
+klass = ENV['TERM'] =~ /^xterm(-256color)?$/ ? PrideLOL : PrideIO
+MiniTest::Unit.output = klass.new(MiniTest::Unit.output)
diff --git a/lib/minitest/spec.rb b/lib/minitest/spec.rb
index 29b4ba8..fd24d5e 100644
--- a/lib/minitest/spec.rb
+++ b/lib/minitest/spec.rb
@@ -2,7 +2,7 @@
require 'minitest/unit'
-class Module
+class Module # :nodoc:
def infect_an_assertion meth, new_name, dont_flip = false # :nodoc:
# warn "%-22p -> %p %p" % [meth, new_name, dont_flip]
self.class_eval <<-EOM
@@ -17,39 +17,18 @@ class Module
end
##
- # Create your own expectations from MiniTest::Assertions using a
- # flexible set of rules. If you don't like must/wont, then this
- # method is your friend. For an example of its usage see the bottom
- # of minitest/spec.rb.
+ # infect_with_assertions has been removed due to excessive clever.
+ # Use infect_an_assertion directly instead.
def infect_with_assertions(pos_prefix, neg_prefix,
skip_re,
dont_flip_re = /\c0/,
map = {})
- MiniTest::Assertions.public_instance_methods(false).sort.each do |meth|
- meth = meth.to_s
-
- new_name = case meth
- when /^assert/ then
- meth.sub(/^assert/, pos_prefix.to_s)
- when /^refute/ then
- meth.sub(/^refute/, neg_prefix.to_s)
- end
- next unless new_name
- next if new_name =~ skip_re
-
- regexp, replacement = map.find { |re, _| new_name =~ re }
- new_name.sub! regexp, replacement if replacement
-
- puts "\n##\n# :method: #{new_name}\n# See MiniTest::Assertions##{meth}" if
- $0 == __FILE__
-
- infect_an_assertion meth, new_name, new_name =~ dont_flip_re
- end
+ abort "infect_with_assertions is dead. Use infect_an_assertion directly"
end
end
-module Kernel
+module Kernel # :nodoc:
##
# Describe a series of expectations for a given target +desc+.
#
@@ -74,25 +53,16 @@ module Kernel
# end
# end
- def describe desc, &block # :doc:
+ def describe desc, additional_desc = nil, &block # :doc:
stack = MiniTest::Spec.describe_stack
- name = [stack.last, desc].compact.join("::")
+ name = [stack.last, desc, additional_desc].compact.join("::")
sclas = stack.last || if Class === self && self < MiniTest::Spec then
self
else
MiniTest::Spec.spec_type desc
end
- cls = Class.new sclas
-
- sclas.children << cls unless cls == MiniTest::Spec
- # :stopdoc:
- # omg this sucks
- (class << cls; self; end).send(:define_method, :to_s) { name }
- (class << cls; self; end).send(:define_method, :desc) { desc }
- # :startdoc:
-
- cls.nuke_test_methods!
+ cls = sclas.create name, desc
stack.push cls
cls.class_eval(&block)
@@ -105,7 +75,7 @@ end
##
# MiniTest::Spec -- The faster, better, less-magical spec framework!
#
-# For a list of expectations, see Object.
+# For a list of expectations, see MiniTest::Expectations.
class MiniTest::Spec < MiniTest::Unit::TestCase
##
@@ -118,11 +88,27 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
TYPES = [[//, MiniTest::Spec]]
##
- # Register a new type of spec that matches the spec's description. Eg:
+ # 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_plugin(/Controller$/, MiniTest::Spec::Rails)
+ # 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 matcher, klass
+ 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
@@ -132,8 +118,13 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
# spec_type("BlahController") # => MiniTest::Spec::Rails
def self.spec_type desc
- desc = desc.to_s
- TYPES.find { |re, klass| re === desc }.last
+ TYPES.find { |matcher, klass|
+ if matcher.respond_to? :call then
+ matcher.call desc
+ else
+ matcher === desc.to_s
+ end
+ }.last
end
@@describe_stack = []
@@ -145,6 +136,9 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
@@current_spec
end
+ ##
+ # Returns the children of this spec.
+
def self.children
@children ||= []
end
@@ -161,25 +155,6 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
end
##
- # Spec users want setup/teardown to be inherited and NOTHING ELSE.
- # It is almost like method reuse is lost on them.
-
- def self.define_inheritable_method name, &block # :nodoc:
- # regular super() warns
- super_method = self.superclass.instance_method name
-
- teardown = name.to_s == "teardown"
- super_before = super_method && ! teardown
- super_after = super_method && teardown
-
- define_method name do
- super_method.bind(self).call if super_before
- instance_eval(&block)
- super_method.bind(self).call if super_after
- end
- end
-
- ##
# Define a 'before' action. Inherits the way normal methods should.
#
# NOTE: +type+ is ignored and is only there to make porting easier.
@@ -188,7 +163,8 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
def self.before type = :each, &block
raise "unsupported before type: #{type}" unless type == :each
- define_inheritable_method :setup, &block
+
+ add_setup_hook {|tc| tc.instance_eval(&block) }
end
##
@@ -200,7 +176,8 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
def self.after type = :each, &block
raise "unsupported after type: #{type}" unless type == :each
- define_inheritable_method :teardown, &block
+
+ add_teardown_hook {|tc| tc.instance_eval(&block) }
end
##
@@ -209,10 +186,12 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
# 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.
- def self.it desc, &block
+ def self.it desc = "anonymous", &block
block ||= proc { skip "(no tests defined)" }
@specs ||= 0
@@ -226,154 +205,321 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
mod.send :undef_method, name if mod.public_method_defined? name
end
end
-end
-Object.infect_with_assertions(:must, :wont,
- /^(must|wont)$|wont_(throw)|
- must_(block|not?_|nothing|raise$)/x,
- /(must|wont)_(include|respond_to)/,
- /(must_throw)s/ => '\1',
- /(?!not)_same/ => '_be_same_as',
- /_in_/ => '_be_within_',
- /_operator/ => '_be',
- /_includes/ => '_include',
- /(must|wont)_(.*_of|nil|silent|empty)/ => '\1_be_\2',
- /must_raises/ => 'must_raise')
+ def self.let name, &block
+ define_method name do
+ @_memoized ||= {}
+ @_memoized.fetch(name) { |k| @_memoized[k] = instance_eval(&block) }
+ end
+ end
-class Object
- alias :must_be_close_to :must_be_within_delta
- alias :wont_be_close_to :wont_be_within_delta
+ def self.subject &block
+ let :subject, &block
+ end
- if $0 == __FILE__ then
- { "must" => "assert", "wont" => "refute" }.each do |a, b|
- puts "\n"
- puts "##"
- puts "# :method: #{a}_be_close_to"
- puts "# See MiniTest::Assertions##{b}_in_delta"
+ def self.create name, desc # :nodoc:
+ cls = Class.new(self) do
+ @name = name
+ @desc = desc
+
+ nuke_test_methods!
end
+
+ children << cls
+
+ cls
end
- ##
- # :method: must_be
- # See MiniTest::Assertions#assert_operator
+ def self.to_s # :nodoc:
+ defined?(@name) ? @name : super
+ end
- ##
- # :method: must_be_close_to
- # See MiniTest::Assertions#assert_in_delta
+ # :stopdoc:
+ class << self
+ attr_reader :desc
+ alias :specify :it
+ alias :name :to_s
+ end
+ # :startdoc:
+end
+module MiniTest::Expectations
##
+ # See MiniTest::Assertions#assert_empty.
+ #
+ # collection.must_be_empty
+ #
# :method: must_be_empty
- # See MiniTest::Assertions#assert_empty
- ##
- # :method: must_be_instance_of
- # See MiniTest::Assertions#assert_instance_of
+ infect_an_assertion :assert_empty, :must_be_empty
##
- # :method: must_be_kind_of
- # See MiniTest::Assertions#assert_kind_of
+ # See MiniTest::Assertions#assert_equal
+ #
+ # a.must_equal b
+ #
+ # :method: must_equal
+
+ infect_an_assertion :assert_equal, :must_equal
##
- # :method: must_be_nil
- # See MiniTest::Assertions#assert_nil
+ # See MiniTest::Assertions#assert_in_delta
+ #
+ # n.must_be_close_to m [, delta]
+ #
+ # :method: must_be_within_delta
+
+ infect_an_assertion :assert_in_delta, :must_be_close_to
+
+ alias :must_be_within_delta :must_be_close_to
##
- # :method: must_be_same_as
- # See MiniTest::Assertions#assert_same
+ # See MiniTest::Assertions#assert_in_epsilon
+ #
+ # n.must_be_within_epsilon m [, epsilon]
+ #
+ # :method: must_be_within_epsilon
+
+ infect_an_assertion :assert_in_epsilon, :must_be_within_epsilon
##
- # :method: must_be_silent
- # See MiniTest::Assertions#assert_silent
+ # See MiniTest::Assertions#assert_includes
+ #
+ # collection.must_include obj
+ #
+ # :method: must_include
+
+ infect_an_assertion :assert_includes, :must_include, :reverse
##
- # :method: must_be_within_delta
- # See MiniTest::Assertions#assert_in_delta
+ # See MiniTest::Assertions#assert_instance_of
+ #
+ # obj.must_be_instance_of klass
+ #
+ # :method: must_be_instance_of
+
+ infect_an_assertion :assert_instance_of, :must_be_instance_of
##
- # :method: must_be_within_epsilon
- # See MiniTest::Assertions#assert_in_epsilon
+ # See MiniTest::Assertions#assert_kind_of
+ #
+ # obj.must_be_kind_of mod
+ #
+ # :method: must_be_kind_of
+
+ infect_an_assertion :assert_kind_of, :must_be_kind_of
##
- # :method: must_equal
- # See MiniTest::Assertions#assert_equal
+ # See MiniTest::Assertions#assert_match
+ #
+ # a.must_match b
+ #
+ # :method: must_match
+
+ infect_an_assertion :assert_match, :must_match
##
- # :method: must_include
- # See MiniTest::Assertions#assert_includes
+ # See MiniTest::Assertions#assert_nil
+ #
+ # obj.must_be_nil
+ #
+ # :method: must_be_nil
+
+ infect_an_assertion :assert_nil, :must_be_nil
##
- # :method: must_match
- # See MiniTest::Assertions#assert_match
+ # See MiniTest::Assertions#assert_operator
+ #
+ # n.must_be :<=, 42
+ #
+ # This can also do predicates:
+ #
+ # str.must_be :empty?
+ #
+ # :method: must_be
+
+ infect_an_assertion :assert_operator, :must_be, :reverse
##
- # :method: must_output
# See MiniTest::Assertions#assert_output
+ #
+ # proc { ... }.must_output out_or_nil [, err]
+ #
+ # :method: must_output
+
+ infect_an_assertion :assert_output, :must_output
##
- # :method: must_raise
# See MiniTest::Assertions#assert_raises
+ #
+ # proc { ... }.must_raise exception
+ #
+ # :method: must_raise
+
+ infect_an_assertion :assert_raises, :must_raise
##
- # :method: must_respond_to
# See MiniTest::Assertions#assert_respond_to
+ #
+ # obj.must_respond_to msg
+ #
+ # :method: must_respond_to
+
+ infect_an_assertion :assert_respond_to, :must_respond_to, :reverse
##
- # :method: must_send
- # See MiniTest::Assertions#assert_send
+ # See MiniTest::Assertions#assert_same
+ #
+ # a.must_be_same_as b
+ #
+ # :method: must_be_same_as
+
+ infect_an_assertion :assert_same, :must_be_same_as
##
- # :method: must_throw
- # See MiniTest::Assertions#assert_throws
+ # See MiniTest::Assertions#assert_send
+ # TODO: remove me
+ #
+ # a.must_send
+ #
+ # :method: must_send
+
+ infect_an_assertion :assert_send, :must_send
##
- # :method: wont_be
- # See MiniTest::Assertions#refute_operator
+ # See MiniTest::Assertions#assert_silent
+ #
+ # proc { ... }.must_be_silent
+ #
+ # :method: must_be_silent
+
+ infect_an_assertion :assert_silent, :must_be_silent
##
- # :method: wont_be_close_to
- # See MiniTest::Assertions#refute_in_delta
+ # See MiniTest::Assertions#assert_throws
+ #
+ # proc { ... }.must_throw sym
+ #
+ # :method: must_throw
+
+ infect_an_assertion :assert_throws, :must_throw
##
- # :method: wont_be_empty
# See MiniTest::Assertions#refute_empty
+ #
+ # collection.wont_be_empty
+ #
+ # :method: wont_be_empty
+
+ infect_an_assertion :refute_empty, :wont_be_empty
##
- # :method: wont_be_instance_of
- # See MiniTest::Assertions#refute_instance_of
+ # See MiniTest::Assertions#refute_equal
+ #
+ # a.wont_equal b
+ #
+ # :method: wont_equal
+
+ infect_an_assertion :refute_equal, :wont_equal
##
- # :method: wont_be_kind_of
- # See MiniTest::Assertions#refute_kind_of
+ # See MiniTest::Assertions#refute_in_delta
+ #
+ # n.wont_be_close_to m [, delta]
+ #
+ # :method: wont_be_within_delta
+
+ infect_an_assertion :refute_in_delta, :wont_be_within_delta
+
+ alias :wont_be_close_to :wont_be_within_delta
+ # FIX: reverse aliases
##
- # :method: wont_be_nil
- # See MiniTest::Assertions#refute_nil
+ # See MiniTest::Assertions#refute_in_epsilon
+ #
+ # n.wont_be_within_epsilon m [, epsilon]
+ #
+ # :method: wont_be_within_epsilon
+
+ infect_an_assertion :refute_in_epsilon, :wont_be_within_epsilon
##
- # :method: wont_be_same_as
- # See MiniTest::Assertions#refute_same
+ # See MiniTest::Assertions#refute_includes
+ #
+ # collection.wont_include obj
+ #
+ # :method: wont_include
+
+ infect_an_assertion :refute_includes, :wont_include, :reverse
##
- # :method: wont_be_within_delta
- # See MiniTest::Assertions#refute_in_delta
+ # See MiniTest::Assertions#refute_instance_of
+ #
+ # obj.wont_be_instance_of klass
+ #
+ # :method: wont_be_instance_of
+
+ infect_an_assertion :refute_instance_of, :wont_be_instance_of
##
- # :method: wont_be_within_epsilon
- # See MiniTest::Assertions#refute_in_epsilon
+ # See MiniTest::Assertions#refute_kind_of
+ #
+ # obj.wont_be_kind_of mod
+ #
+ # :method: wont_be_kind_of
+
+ infect_an_assertion :refute_kind_of, :wont_be_kind_of
##
- # :method: wont_equal
- # See MiniTest::Assertions#refute_equal
+ # See MiniTest::Assertions#refute_match
+ #
+ # a.wont_match b
+ #
+ # :method: wont_match
+
+ infect_an_assertion :refute_match, :wont_match
##
- # :method: wont_include
- # See MiniTest::Assertions#refute_includes
+ # See MiniTest::Assertions#refute_nil
+ #
+ # obj.wont_be_nil
+ #
+ # :method: wont_be_nil
+
+ infect_an_assertion :refute_nil, :wont_be_nil
##
- # :method: wont_match
- # See MiniTest::Assertions#refute_match
+ # See MiniTest::Assertions#refute_operator
+ #
+ # n.wont_be :<=, 42
+ #
+ # This can also do predicates:
+ #
+ # str.wont_be :empty?
+ #
+ # :method: wont_be
+
+ infect_an_assertion :refute_operator, :wont_be, :reverse
##
- # :method: wont_respond_to
# See MiniTest::Assertions#refute_respond_to
+ #
+ # obj.wont_respond_to msg
+ #
+ # :method: wont_respond_to
+
+ infect_an_assertion :refute_respond_to, :wont_respond_to, :reverse
+
+ ##
+ # See MiniTest::Assertions#refute_same
+ #
+ # a.wont_be_same_as b
+ #
+ # :method: wont_be_same_as
+
+ infect_an_assertion :refute_same, :wont_be_same_as
+end
+
+class Object
+ include MiniTest::Expectations
end
diff --git a/lib/minitest/unit.rb b/lib/minitest/unit.rb
index f1f0b3e..b9871ec 100644
--- a/lib/minitest/unit.rb
+++ b/lib/minitest/unit.rb
@@ -1,4 +1,5 @@
require 'optparse'
+require 'rbconfig'
##
# Minimal (mostly drop-in) replacement for test-unit.
@@ -59,16 +60,106 @@ module MiniTest
module Assertions
+ WINDOZE = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
+
+ ##
+ # Returns the diff command to use in #diff. Tries to intelligently
+ # figure out what diff to use.
+
+ def self.diff
+ @diff = if WINDOZE
+ "diff.exe -u"
+ else
+ if system("gdiff", __FILE__, __FILE__)
+ "gdiff -u" # solaris and kin suck
+ elsif system("diff", __FILE__, __FILE__)
+ "diff -u"
+ else
+ nil
+ end
+ end unless defined? @diff
+
+ @diff
+ end
+
+ ##
+ # Set the diff command to use in #diff.
+
+ def self.diff= o
+ @diff = o
+ end
+
##
- # mu_pp gives a human-readable version of +obj+. By default #inspect is
- # called. You can override this to use #pretty_print if you want.
+ # Returns a diff between +exp+ and +act+. If there is no known
+ # diff command or if it doesn't make sense to diff the output
+ # (single line, short output), then it simply returns a basic
+ # comparison between the two.
+
+ def diff exp, act
+ require "tempfile"
+
+ expect = mu_pp_for_diff exp
+ butwas = mu_pp_for_diff act
+ result = nil
+
+ need_to_diff =
+ MiniTest::Assertions.diff &&
+ (expect.include?("\n") ||
+ butwas.include?("\n") ||
+ expect.size > 30 ||
+ butwas.size > 30 ||
+ expect == butwas)
+
+ return "Expected: #{mu_pp exp}\n Actual: #{mu_pp act}" unless
+ need_to_diff
+
+ Tempfile.open("expect") do |a|
+ a.puts expect
+ a.flush
+
+ Tempfile.open("butwas") do |b|
+ b.puts butwas
+ b.flush
+
+ result = `#{MiniTest::Assertions.diff} #{a.path} #{b.path}`
+ result.sub!(/^\-\-\- .+/, "--- expected")
+ result.sub!(/^\+\+\+ .+/, "+++ actual")
+
+ if result.empty? then
+ klass = exp.class
+ result = [
+ "No visible difference.",
+ "You should look at your implementation of #{klass}#==.",
+ expect
+ ].join "\n"
+ end
+ end
+ end
+
+ result
+ end
+
+ ##
+ # This returns a human-readable version of +obj+. By default
+ # #inspect is called. You can override this to use #pretty_print
+ # if you want.
def mu_pp obj
s = obj.inspect
- s = s.force_encoding Encoding.default_external if defined? Encoding
+ s = s.encode Encoding.default_external if defined? Encoding
s
end
+ ##
+ # This returns a diff-able human-readable version of +obj+. This
+ # differs from the regular mu_pp because it expands escaped
+ # 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')
+ end
+
def _assertions= n # :nodoc:
@_assertions = n
end
@@ -108,12 +199,19 @@ module MiniTest
end
##
- # Fails unless <tt>exp == act</tt>.
+ # Fails unless <tt>exp == act</tt> printing the difference between
+ # the two, if possible.
+ #
+ # If there is no visible difference but the assertion fails, you
+ # should suspect that your #== is buggy, or your inspect output is
+ # missing crucial details.
+ #
+ # For floats use assert_in_delta.
#
- # For floats use assert_in_delta
+ # See also: MiniTest::Assertions.diff
def assert_equal exp, act, msg = nil
- msg = message(msg) { "Expected #{mu_pp(exp)}, not #{mu_pp(act)}" }
+ msg = message(msg, "") { diff exp, act }
assert(exp == act, msg)
end
@@ -187,12 +285,16 @@ module MiniTest
assert obj.nil?, msg
end
+ UNDEFINED = Object.new
+ def UNDEFINED.inspect; "UNDEFINED"; end
+
##
- # For testing equality operators and so-forth.
+ # For testing with binary operators.
#
# assert_operator 5, :<=, 4
- def assert_operator o1, op, o2, msg = nil
+ def assert_operator o1, op, o2 = UNDEFINED, msg = nil
+ return assert_predicate o1, op, msg if UNDEFINED == o2
msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" }
assert o1.__send__(op, o2), msg
end
@@ -216,6 +318,20 @@ module MiniTest
end
##
+ # For testing with predicates.
+ #
+ # assert_predicate str, :empty?
+ #
+ # This is really meant for specs and is front-ended by assert_operator:
+ #
+ # str.must_be :empty?
+
+ def assert_predicate o1, op, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op}" }
+ assert o1.__send__(op), msg
+ end
+
+ ##
# Fails unless the block raises one of +exp+
def assert_raises *exp
@@ -361,10 +477,10 @@ module MiniTest
##
# Returns a proc that will output +msg+ along with the default message.
- def message msg = nil, &default
+ def message msg = nil, ending = ".", &default
proc {
custom_message = "#{msg}.\n" unless msg.nil? or msg.to_s.empty?
- "#{custom_message}#{default.call}."
+ "#{custom_message}#{default.call}#{ending}"
}
end
@@ -387,7 +503,7 @@ module MiniTest
# Fails if +obj+ is empty.
def refute_empty obj, msg = nil
- msg = message(msg) { "Expected #{obj.inspect} to not be empty" }
+ msg = message(msg) { "Expected #{mu_pp(obj)} to not be empty" }
assert_respond_to obj, :empty?
refute obj.empty?, msg
end
@@ -473,19 +589,32 @@ module MiniTest
end
##
- # Fails if +o1+ is not +op+ +o2+ nil. eg:
+ # Fails if +o1+ is not +op+ +o2+. Eg:
#
# refute_operator 1, :>, 2 #=> pass
# refute_operator 1, :<, 2 #=> fail
- def refute_operator o1, op, o2, msg = nil
- msg = message(msg) {
- "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}"
- }
+ def refute_operator o1, op, o2 = UNDEFINED, msg = nil
+ return refute_predicate o1, op, msg if UNDEFINED == o2
+ msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}"}
refute o1.__send__(op, o2), msg
end
##
+ # For testing with predicates.
+ #
+ # refute_predicate str, :empty?
+ #
+ # This is really meant for specs and is front-ended by refute_operator:
+ #
+ # str.wont_be :empty?
+
+ def refute_predicate o1, op, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op}" }
+ refute o1.__send__(op), msg
+ end
+
+ ##
# Fails if +obj+ responds to the message +meth+.
def refute_respond_to obj, meth, msg = nil
@@ -516,7 +645,7 @@ module MiniTest
end
class Unit
- VERSION = "2.1.0" # :nodoc:
+ VERSION = "2.6.1" # :nodoc:
attr_accessor :report, :failures, :errors, :skips # :nodoc:
attr_accessor :test_count, :assertion_count # :nodoc:
@@ -710,6 +839,7 @@ module MiniTest
e = case e
when MiniTest::Skip then
@skips += 1
+ return "S" unless @verbose
"Skipped:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
when MiniTest::Assertion then
@failures += 1
@@ -840,6 +970,7 @@ module MiniTest
begin
@passed = nil
self.setup
+ self.run_setup_hooks
self.__send__ self.__name__
result = "." unless io?
@passed = true
@@ -850,6 +981,7 @@ module MiniTest
result = runner.puke self.class, self.__name__, e
ensure
begin
+ self.run_teardown_hooks
self.teardown
rescue *PASSTHROUGH_EXCEPTIONS
raise
@@ -882,16 +1014,24 @@ module MiniTest
reset
+ ##
+ # Call this at the top of your tests when you absolutely
+ # positively need to have ordered tests. In doing so, you're
+ # admitting that you suck and your tests are weak.
+
+ def self.i_suck_and_my_tests_are_order_dependent!
+ class << self
+ define_method :test_order do :alpha end
+ end
+ end
+
def self.inherited klass # :nodoc:
@@test_suites[klass] = true
+ klass.reset_setup_teardown_hooks
+ super
end
- ##
- # Defines test order and is subclassable. Defaults to :random
- # but can be overridden to return :alpha if your tests are order
- # dependent (read: weak).
-
- def self.test_order
+ def self.test_order # :nodoc:
:random
end
@@ -930,6 +1070,111 @@ module MiniTest
def teardown; end
+ def self.reset_setup_teardown_hooks # :nodoc:
+ @setup_hooks = []
+ @teardown_hooks = []
+ end
+
+ reset_setup_teardown_hooks
+
+ ##
+ # Adds a block of code that will be executed before every TestCase is
+ # run. Equivalent to +setup+, but usable multiple times and without
+ # re-opening any classes.
+ #
+ # All of the setup hooks will run in order after the +setup+ method, if
+ # one is defined.
+ #
+ # The argument can be any object that responds to #call or a block.
+ # That means that this call,
+ #
+ # MiniTest::TestCase.add_setup_hook { puts "foo" }
+ #
+ # ... is equivalent to:
+ #
+ # module MyTestSetup
+ # def call
+ # puts "foo"
+ # end
+ # end
+ #
+ # MiniTest::TestCase.add_setup_hook MyTestSetup
+ #
+ # The blocks passed to +add_setup_hook+ take an optional parameter that
+ # will be the TestCase instance that is executing the block.
+
+ def self.add_setup_hook arg=nil, &block
+ hook = arg || block
+ @setup_hooks << hook
+ end
+
+ def self.setup_hooks # :nodoc:
+ if superclass.respond_to? :setup_hooks then
+ superclass.setup_hooks
+ else
+ []
+ end + @setup_hooks
+ end
+
+ def run_setup_hooks # :nodoc:
+ self.class.setup_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. Equivalent to +teardown+, but usable multiple times and without
+ # re-opening any classes.
+ #
+ # All of the teardown hooks will run in reverse order after the
+ # +teardown+ method, if one is defined.
+ #
+ # The argument can be any object that responds to #call or a block.
+ # That means that this call,
+ #
+ # MiniTest::TestCase.add_teardown_hook { puts "foo" }
+ #
+ # ... is equivalent to:
+ #
+ # module MyTestTeardown
+ # def call
+ # puts "foo"
+ # end
+ # end
+ #
+ # MiniTest::TestCase.add_teardown_hook MyTestTeardown
+ #
+ # The blocks passed to +add_teardown_hook+ take an optional parameter
+ # that will be the TestCase instance that is executing the block.
+
+ def self.add_teardown_hook arg=nil, &block
+ hook = arg || block
+ @teardown_hooks << hook
+ end
+
+ def self.teardown_hooks # :nodoc:
+ if superclass.respond_to? :teardown_hooks then
+ superclass.teardown_hooks
+ else
+ []
+ end + @teardown_hooks
+ end
+
+ def run_teardown_hooks # :nodoc:
+ self.class.teardown_hooks.reverse.each do |hook|
+ if hook.respond_to?(:arity) && hook.arity == 1
+ hook.call(self)
+ else
+ hook.call
+ end
+ end
+ end
+
include MiniTest::Assertions
end # class TestCase
end # class Unit
diff --git a/metadata.gz.sig b/metadata.gz.sig
index c11f08c..5a14e1f 100644
Binary files a/metadata.gz.sig and b/metadata.gz.sig differ
diff --git a/metadata.yml b/metadata.yml
index 88a5a85..9c12ff0 100644
--- a/metadata.yml
+++ b/metadata.yml
@@ -1,13 +1,13 @@
--- !ruby/object:Gem::Specification
name: minitest
version: !ruby/object:Gem::Version
- hash: 11
+ hash: 21
prerelease:
segments:
- 2
+ - 6
- 1
- - 0
- version: 2.1.0
+ version: 2.6.1
platform: ruby
authors:
- Ryan Davis
@@ -36,68 +36,43 @@ cert_chain:
FBHgymkyj/AOSqKRIpXPhjC6
-----END CERTIFICATE-----
-date: 2011-04-11 00:00:00 -07:00
-default_executable:
+date: 2011-09-28 00:00:00 Z
dependencies:
- !ruby/object:Gem::Dependency
- name: minitest
+ name: hoe
prerelease: false
requirement: &id001 !ruby/object:Gem::Requirement
none: false
requirements:
- - - ">="
+ - - ~>
- !ruby/object:Gem::Version
- hash: 11
+ hash: 27
segments:
- 2
- - 0
- - 2
- version: 2.0.2
+ - 12
+ version: "2.12"
type: :development
version_requirements: *id001
-- !ruby/object:Gem::Dependency
- name: hoe
- prerelease: false
- requirement: &id002 !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ">="
- - !ruby/object:Gem::Version
- hash: 41
- segments:
- - 2
- - 9
- - 1
- version: 2.9.1
- type: :development
- version_requirements: *id002
-description: |-
- minitest provides a complete suite of testing facilities supporting
- TDD, BDD, mocking, and benchmarking.
-
- minitest/unit is a small and incredibly fast unit testing framework.
- It provides a rich set of assertions to make your tests clean and
- readable.
-
- minitest/spec is a functionally complete spec engine. It hooks onto
- minitest/unit and seamlessly bridges test assertions over to spec
- expectations.
-
- minitest/benchmark is an awesome way to assert the performance of your
- algorithms in a repeatable manner. Now you can assert that your newb
- co-worker doesn't replace your linear algorithm with an exponential
- one!
-
- minitest/mock by Steven Baker, is a beautifully tiny mock object
- framework.
-
- minitest/pride shows pride in testing and adds coloring to your test
- output.
-
- minitest/unit is meant to have a clean implementation for language
- implementors that need a minimal set of methods to bootstrap a working
- test suite. For example, there is no magic involved for test-case
- discovery.
+description: "minitest provides a complete suite of testing facilities supporting\n\
+ TDD, BDD, mocking, and benchmarking.\n\n \"I had a class with Jim Weirich on testing last week and we were\n allowed to choose our testing frameworks. Kirk Haines and I were\n paired up and we cracked open the code for a few test\n frameworks...\n\n I MUST say that mintiest is *very* readable / understandable\n compared to the 'other two' options we looked at. Nicely done and\n thank you for helping us keep our mental sanity.\"\n\n -- Wayne E. Seguin\n\n\
+ minitest/unit is a small and incredibly fast unit testing framework.\n\
+ It provides a rich set of assertions to make your tests clean and\n\
+ readable.\n\n\
+ minitest/spec is a functionally complete spec engine. It hooks onto\n\
+ minitest/unit and seamlessly bridges test assertions over to spec\n\
+ expectations.\n\n\
+ minitest/benchmark is an awesome way to assert the performance of your\n\
+ algorithms in a repeatable manner. Now you can assert that your newb\n\
+ co-worker doesn't replace your linear algorithm with an exponential\n\
+ one!\n\n\
+ minitest/mock by Steven Baker, is a beautifully tiny mock object\n\
+ framework.\n\n\
+ minitest/pride shows pride in testing and adds coloring to your test\n\
+ output. I guess it is an example of how to write IO pipes too. :P\n\n\
+ minitest/unit is meant to have a clean implementation for language\n\
+ implementors that need a minimal set of methods to bootstrap a working\n\
+ test suite. For example, there is no magic involved for test-case\n\
+ discovery.\n\n \"Again, I can\xE2\x80\x99t praise enough the idea of a testing/specing\n framework that I can actually read in full in one sitting!\"\n\n -- Piotr Szotkowski"
email:
- ryand-ruby at zenspider.com
executables: []
@@ -115,6 +90,7 @@ files:
- README.txt
- Rakefile
- design_rationale.rb
+- lib/hoe/minitest.rb
- lib/minitest/autorun.rb
- lib/minitest/benchmark.rb
- lib/minitest/mock.rb
@@ -126,8 +102,7 @@ files:
- test/test_minitest_spec.rb
- test/test_minitest_unit.rb
- .gemtest
-has_rdoc: true
-homepage: http://rubyforge.org/projects/bfts
+homepage: https://github.com/seattlerb/minitest
licenses: []
post_install_message:
@@ -157,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
requirements: []
rubyforge_project: bfts
-rubygems_version: 1.6.2
+rubygems_version: 1.8.10
signing_key:
specification_version: 3
summary: minitest provides a complete suite of testing facilities supporting TDD, BDD, mocking, and benchmarking
diff --git a/test/test_minitest_mock.rb b/test/test_minitest_mock.rb
index ddf44e6..b33057f 100644
--- a/test/test_minitest_mock.rb
+++ b/test/test_minitest_mock.rb
@@ -43,20 +43,34 @@ class TestMiniTestMock < MiniTest::Unit::TestCase
util_verify_bad
end
- def test_not_verify_if_unexpected_method_is_called
- assert_raises NoMethodError do
- @mock.unexpected
- end
- end
-
def test_blow_up_on_wrong_number_of_arguments
@mock.foo
@mock.meaning_of_life
@mock.expect(:sum, 3, [1, 2])
- assert_raises ArgumentError do
+ e = assert_raises ArgumentError do
@mock.sum
end
+
+ assert_equal "mocked method :sum expects 2 arguments, got 0", e.message
+ end
+
+ def test_return_mock_does_not_raise
+ retval = MiniTest::Mock.new
+ mock = MiniTest::Mock.new
+ mock.expect(:foo, retval)
+ mock.foo
+
+ assert mock.verify
+ end
+
+ def test_mock_args_does_not_raise
+ arg = MiniTest::Mock.new
+ mock = MiniTest::Mock.new
+ mock.expect(:foo, nil, [arg])
+ mock.foo(arg)
+
+ assert mock.verify
end
def test_blow_up_on_wrong_arguments
@@ -71,22 +85,27 @@ class TestMiniTestMock < MiniTest::Unit::TestCase
def test_respond_appropriately
assert @mock.respond_to?(:foo)
+ assert @mock.respond_to?('foo')
assert !@mock.respond_to?(:bar)
end
def test_no_method_error_on_unexpected_methods
- assert_raises NoMethodError do
+ e = assert_raises NoMethodError do
@mock.bar
end
+
+ expected = "unmocked method :bar, expected one of [:foo, :meaning_of_life]"
+
+ assert_equal expected, e.message
end
def test_assign_per_mock_return_values
a = MiniTest::Mock.new
b = MiniTest::Mock.new
-
+
a.expect(:foo, :a)
b.expect(:foo, :b)
-
+
assert_equal :a, a.foo
assert_equal :b, b.foo
end
@@ -98,6 +117,30 @@ class TestMiniTestMock < MiniTest::Unit::TestCase
assert !MiniTest::Mock.new.respond_to?(:foo)
end
+ def test_mock_is_a_blank_slate
+ @mock.expect :kind_of?, true, [Fixnum]
+ @mock.expect :==, true, [1]
+
+ assert @mock.kind_of?(Fixnum), "didn't mock :kind_of\?"
+ assert @mock == 1, "didn't mock :=="
+ end
+
+ def test_verify_allows_called_args_to_be_loosely_specified
+ mock = MiniTest::Mock.new
+ mock.expect :loose_expectation, true, [Integer]
+ mock.loose_expectation 1
+
+ assert mock.verify
+ end
+
+ def test_verify_raises_with_strict_args
+ mock = MiniTest::Mock.new
+ mock.expect :strict_expectation, true, [2]
+ mock.strict_expectation 1
+
+ util_verify_bad
+ end
+
def util_verify_bad
assert_raises MockExpectationError do
@mock.verify
diff --git a/test/test_minitest_spec.rb b/test/test_minitest_spec.rb
index 892e7b6..b9379d0 100755
--- a/test/test_minitest_spec.rb
+++ b/test/test_minitest_spec.rb
@@ -1,7 +1,10 @@
-require 'minitest/spec'
+require 'minitest/autorun'
require 'stringio'
-MiniTest::Unit.autorun
+class MiniSpecA < MiniTest::Spec; end
+class MiniSpecB < MiniTest::Spec; end
+class ExampleA; end
+class ExampleB < ExampleA; end
describe MiniTest::Spec do
before do
@@ -86,11 +89,16 @@ describe MiniTest::Spec do
proc { 42.must_be_nil }.must_raise MiniTest::Assertion
end
- it "needs to verify using any operator" do
+ it "needs to verify using any binary operator" do
41.must_be(:<, 42).must_equal true
proc { 42.must_be(:<, 41) }.must_raise MiniTest::Assertion
end
+ it "needs to verify using any predicate" do
+ "".must_be(:empty?).must_equal true
+ proc { "blah".must_be(:empty?) }.must_raise MiniTest::Assertion
+ end
+
it "needs to catch an expected exception" do
@assertion_count = 2
@@ -147,6 +155,11 @@ describe MiniTest::Spec do
proc { "blah".wont_match(/\w+/) }.must_raise MiniTest::Assertion
end
+ it "needs to verify using any (negative) predicate" do
+ "blah".wont_be(:empty?).must_equal false
+ proc { "".wont_be(:empty?) }.must_raise MiniTest::Assertion
+ end
+
it "needs to verify non-nil" do
42.wont_be_nil.must_equal false
proc { nil.wont_be_nil }.must_raise MiniTest::Assertion
@@ -196,6 +209,53 @@ describe MiniTest::Spec do
end
end
+describe MiniTest::Spec, :let do
+ i_suck_and_my_tests_are_order_dependent!
+
+ def _count
+ $let_count ||= 0
+ end
+
+ let :count do
+ $let_count += 1
+ $let_count
+ end
+
+ it "is evaluated once per example" do
+ _count.must_equal 0
+
+ count.must_equal 1
+ count.must_equal 1
+
+ _count.must_equal 1
+ end
+
+ it "is REALLY evaluated once per example" do
+ _count.must_equal 1
+
+ count.must_equal 2
+ count.must_equal 2
+
+ _count.must_equal 2
+ end
+end
+
+describe MiniTest::Spec, :subject do
+ attr_reader :subject_evaluation_count
+
+ subject do
+ @subject_evaluation_count ||= 0
+ @subject_evaluation_count += 1
+ @subject_evaluation_count
+ end
+
+ it "is evaluated once per example" do
+ subject.must_equal 1
+ subject.must_equal 1
+ subject_evaluation_count.must_equal 1
+ end
+end
+
class TestMeta < MiniTest::Unit::TestCase
def test_setup
srand 42
@@ -221,6 +281,9 @@ class TestMeta < MiniTest::Unit::TestCase
before { before_list << 3 }
after { after_list << 3 }
it "inner-it" do end
+
+ it {} # ignore me
+ specify {} # anonymous it
end
end
end
@@ -228,6 +291,38 @@ class TestMeta < MiniTest::Unit::TestCase
return x, y, z, before_list, after_list
end
+ def test_register_spec_type
+ original_types = MiniTest::Spec::TYPES.dup
+
+ assert_equal [[//, MiniTest::Spec]], MiniTest::Spec::TYPES
+
+ MiniTest::Spec.register_spec_type(/woot/, TestMeta)
+
+ p = lambda do |x| true end
+ MiniTest::Spec.register_spec_type TestMeta, &p
+
+ keys = MiniTest::Spec::TYPES.map(&:first)
+
+ assert_includes keys, /woot/
+ assert_includes keys, p
+ ensure
+ MiniTest::Spec::TYPES.replace original_types
+ end
+
+ def test_spec_type
+ original_types = MiniTest::Spec::TYPES.dup
+
+ MiniTest::Spec.register_spec_type(/A$/, MiniSpecA)
+ MiniTest::Spec.register_spec_type MiniSpecB do |desc|
+ desc.superclass == ExampleA
+ end
+
+ assert_equal MiniSpecA, MiniTest::Spec.spec_type(ExampleA)
+ assert_equal MiniSpecB, MiniTest::Spec.spec_type(ExampleB)
+ ensure
+ MiniTest::Spec::TYPES.replace original_types
+ end
+
def test_structure
x, y, z, * = util_structure
@@ -239,20 +334,23 @@ class TestMeta < MiniTest::Unit::TestCase
assert_equal "inner thingy", y.desc
assert_equal "very inner thingy", z.desc
- top_methods = %w(setup teardown test_0001_top_level_it)
- inner_methods = %w(setup teardown test_0001_inner_it)
+ top_methods = %w(test_0001_top_level_it)
+ inner_methods1 = %w(test_0001_inner_it)
+ inner_methods2 = inner_methods1 +
+ %w(test_0002_anonymous test_0003_anonymous)
- assert_equal top_methods, x.instance_methods(false).sort.map {|o| o.to_s }
- assert_equal inner_methods, y.instance_methods(false).sort.map {|o| o.to_s }
- assert_equal inner_methods, z.instance_methods(false).sort.map {|o| o.to_s }
+ assert_equal top_methods, x.instance_methods(false).sort.map(&:to_s)
+ assert_equal inner_methods1, y.instance_methods(false).sort.map(&:to_s)
+ assert_equal inner_methods2, z.instance_methods(false).sort.map(&:to_s)
end
def test_setup_teardown_behavior
_, _, z, before_list, after_list = util_structure
tc = z.new(nil)
- tc.setup
- tc.teardown
+
+ tc.run_setup_hooks
+ tc.run_teardown_hooks
assert_equal [1, 2, 3], before_list
assert_equal [3, 2, 1], after_list
diff --git a/test/test_minitest_unit.rb b/test/test_minitest_unit.rb
index ccab757..32a9767 100755
--- a/test/test_minitest_unit.rb
+++ b/test/test_minitest_unit.rb
@@ -6,6 +6,7 @@ MiniTest::Unit.autorun
module MyModule; end
class AnError < StandardError; include MyModule; end
+class ImmutableString < String; def inspect; super.freeze; end; end
class TestMiniTestUnit < MiniTest::Unit::TestCase
pwd = Pathname.new(File.expand_path(Dir.pwd))
@@ -40,12 +41,12 @@ Finished tests in 0.00
MiniTest::Unit::TestCase.reset
@tu = MiniTest::Unit.new
@output = StringIO.new("")
+ MiniTest::Unit.runner = nil # protect the outer runner from the inner tests
MiniTest::Unit.output = @output
end
def teardown
MiniTest::Unit.output = $stdout
- MiniTest::Unit.runner = nil
Object.send :remove_const, :ATestCase if defined? ATestCase
end
@@ -346,6 +347,36 @@ S.
Finished tests in 0.00
+2 tests, 1 assertions, 0 failures, 0 errors, 1 skips
+"
+ assert_report expected
+ end
+
+ def test_run_skip_verbose
+ tc = Class.new(MiniTest::Unit::TestCase) do
+ def test_something
+ assert true
+ end
+
+ def test_skip
+ skip "not yet"
+ end
+ end
+
+ Object.const_set(:ATestCase, tc)
+
+ @tu.run %w[--seed 42 --verbose]
+
+ expected = "Run options: --seed 42 --verbose
+
+# Running tests:
+
+ATestCase#test_skip = 0.00 s = S
+ATestCase#test_something = 0.00 s = .
+
+
+Finished tests in 0.00
+
1) Skipped:
test_skip(ATestCase) [FILE:LINE]:
not yet
@@ -406,6 +437,149 @@ Finished tests in 0.00
assert_report expected
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
+ 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
+
+ def test_setup_hooks
+ call_order = []
+
+ tc = Class.new(MiniTest::Unit::TestCase) do
+ define_method :setup do
+ super()
+ call_order << :method
+ end
+
+ define_method :test2 do
+ call_order << :test2
+ end
+
+ define_method :test1 do
+ call_order << :test1
+ end
+ end
+
+ tc.add_setup_hook lambda { call_order << :proc }
+
+ argument = nil
+
+ tc.add_setup_hook do |arg|
+ argument = arg
+ call_order << :block
+ end
+
+ @tu.run %w[--seed 42]
+
+ assert_kind_of tc, argument
+
+ expected = [:method, :proc, :block, :test1,
+ :method, :proc, :block, :test2]
+
+ assert_equal expected, call_order
+ end
+
+ def test_teardown_hooks
+ call_order = []
+
+ tc = Class.new(MiniTest::Unit::TestCase) do
+ define_method :teardown do
+ super()
+ call_order << :method
+ end
+
+ define_method :test2 do
+ call_order << :test2
+ end
+
+ define_method :test1 do
+ call_order << :test1
+ end
+ end
+
+ tc.add_teardown_hook lambda { call_order << :proc }
+
+ argument = nil
+
+ tc.add_teardown_hook do |arg|
+ argument = arg
+ call_order << :block
+ end
+
+ @tu.run %w[--seed 42]
+
+ assert_kind_of tc, argument
+
+ expected = [:test1, :block, :proc, :method,
+ :test2, :block, :proc, :method]
+
+ assert_equal expected, call_order
+ end
+
+ def test_setup_and_teardown_hooks_survive_inheritance
+ call_order = []
+
+ parent = Class.new(MiniTest::Unit::TestCase) do
+ define_method :setup do
+ super()
+ call_order << :setup_method
+ end
+
+ define_method :teardown do
+ super()
+ call_order << :teardown_method
+ end
+
+ define_method :test_something do
+ call_order << :test
+ end
+ end
+
+ parent.add_setup_hook { call_order << :setup_hook }
+ parent.add_teardown_hook { call_order << :teardown_hook }
+
+ _ = Class.new parent
+
+ parent.add_setup_hook { call_order << :setup_after }
+ parent.add_teardown_hook { call_order << :teardown_after }
+
+ @tu.run %w[--seed 42]
+
+ # Once for the parent class, once for the child
+ expected = [:setup_method, :setup_hook, :setup_after, :test,
+ :teardown_after, :teardown_hook, :teardown_method] * 2
+
+ assert_equal expected, call_order
+ end
+
def util_expand_bt bt
if RUBY_VERSION =~ /^1\.9/ then
bt.map { |f| (f =~ /^\./) ? File.expand_path(f) : f }
@@ -480,12 +654,115 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase
@tc.assert_equal 1, 1
end
- def test_assert_equal_different
- util_assert_triggered "Expected 1, not 2." do
+ def test_assert_equal_different_diff_deactivated
+ without_diff do
+ util_assert_triggered util_msg("haha" * 10, "blah" * 10) do
+ o1 = "haha" * 10
+ o2 = "blah" * 10
+
+ @tc.assert_equal o1, o2
+ end
+ end
+ end
+
+ def test_assert_equal_different_hex
+ c = Class.new do
+ def initialize s; @name = s; end
+ end
+
+ o1 = c.new "a"
+ o2 = c.new "b"
+ msg = "--- expected
+ +++ actual
+ @@ -1 +1 @@
+ -#<#<Class:0xXXXXXX>:0xXXXXXX @name=\"a\">
+ +#<#<Class:0xXXXXXX>:0xXXXXXX @name=\"b\">
+ ".gsub(/^ +/, "")
+
+ util_assert_triggered msg do
+ @tc.assert_equal o1, o2
+ end
+ end
+
+ def test_assert_equal_different_hex_invisible
+ o1 = Object.new
+ o2 = Object.new
+
+ msg = "No visible difference.
+ You should look at your implementation of Object#==.
+ #<Object:0xXXXXXX>".gsub(/^ +/, "")
+
+ util_assert_triggered msg do
+ @tc.assert_equal o1, o2
+ end
+ end
+
+ def test_assert_equal_different_long
+ msg = "--- expected
+ +++ actual
+ @@ -1 +1 @@
+ -\"hahahahahahahahahahahahahahahahahahahaha\"
+ +\"blahblahblahblahblahblahblahblahblahblah\"
+ ".gsub(/^ +/, "")
+
+ util_assert_triggered msg do
+ o1 = "haha" * 10
+ o2 = "blah" * 10
+
+ @tc.assert_equal o1, o2
+ end
+ end
+
+ def test_assert_equal_different_long_invisible
+ msg = "No visible difference.
+ You should look at your implementation of String#==.
+ \"blahblahblahblahblahblahblahblahblahblah\"".gsub(/^ +/, "")
+
+ util_assert_triggered msg do
+ o1 = "blah" * 10
+ o2 = "blah" * 10
+ def o1.== o
+ false
+ end
+ @tc.assert_equal o1, o2
+ end
+ end
+
+ def test_assert_equal_different_long_msg
+ msg = "message.
+ --- expected
+ +++ actual
+ @@ -1 +1 @@
+ -\"hahahahahahahahahahahahahahahahahahahaha\"
+ +\"blahblahblahblahblahblahblahblahblahblah\"
+ ".gsub(/^ +/, "")
+
+ util_assert_triggered msg do
+ o1 = "haha" * 10
+ o2 = "blah" * 10
+ @tc.assert_equal o1, o2, "message"
+ end
+ end
+
+ def test_assert_equal_different_short
+ util_assert_triggered util_msg(1, 2) do
@tc.assert_equal 1, 2
end
end
+ def test_assert_equal_different_short_msg
+ util_assert_triggered util_msg(1, 2, "message") do
+ @tc.assert_equal 1, 2, "message"
+ end
+ end
+
+ def test_assert_equal_different_short_multiline
+ msg = "--- expected\n+++ actual\n@@ -1,2 +1,2 @@\n \"a\n-b\"\n+c\"\n"
+ util_assert_triggered msg do
+ @tc.assert_equal "a\nb", "a\nc"
+ end
+ end
+
def test_assert_in_delta
@tc.assert_in_delta 0.0, 1.0 / 1000, 0.1
end
@@ -600,6 +877,13 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase
@tc.assert_operator 2, :>, 1
end
+ def test_assert_operator_bad_object
+ bad = Object.new
+ def bad.==(other) true end
+
+ @tc.assert_operator bad, :equal?, bad
+ end
+
def test_assert_operator_triggered
util_assert_triggered "Expected 2 to be < 1." do
@tc.assert_operator 2, :<, 1
@@ -636,7 +920,7 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase
end
def test_assert_output_triggered_both
- util_assert_triggered "In stdout.\nExpected \"yay\", not \"boo\"." do
+ util_assert_triggered util_msg("yay", "boo", "In stdout") do
@tc.assert_output "yay", "blah" do
print "boo"
$stderr.print "blah blah"
@@ -645,7 +929,7 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase
end
def test_assert_output_triggered_err
- util_assert_triggered "In stderr.\nExpected \"blah\", not \"blah blah\"." do
+ util_assert_triggered util_msg("blah", "blah blah", "In stderr") do
@tc.assert_output nil, "blah" do
$stderr.print "blah blah"
end
@@ -653,7 +937,7 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase
end
def test_assert_output_triggered_out
- util_assert_triggered "In stdout.\nExpected \"blah\", not \"blah blah\"." do
+ util_assert_triggered util_msg("blah", "blah blah", "In stdout") do
@tc.assert_output "blah" do
print "blah blah"
end
@@ -832,7 +1116,7 @@ FILE:LINE:in `test_assert_raises_triggered_subclass'
def test_assert_silent_triggered_err
@assertion_count = 2
- util_assert_triggered "In stderr.\nExpected \"\", not \"blah blah\"." do
+ util_assert_triggered util_msg("", "blah blah", "In stderr") do
@tc.assert_silent do
$stderr.print "blah blah"
end
@@ -840,7 +1124,7 @@ FILE:LINE:in `test_assert_raises_triggered_subclass'
end
def test_assert_silent_triggered_out
- util_assert_triggered "In stdout.\nExpected \"\", not \"blah blah\"." do
+ util_assert_triggered util_msg("", "blah blah", "In stdout") do
@tc.assert_silent do
print "blah blah"
end
@@ -945,6 +1229,11 @@ FILE:LINE:in `test_assert_raises_triggered_subclass'
@tc.pass
end
+ def test_prints
+ printer = Class.new { extend MiniTest::Assertions }
+ @tc.assert_equal '"test"', printer.mu_pp(ImmutableString.new 'test')
+ end
+
def test_refute
@assertion_count = 2
@@ -1076,6 +1365,13 @@ FILE:LINE:in `test_assert_raises_triggered_subclass'
@tc.refute_operator 2, :<, 1
end
+ def test_refute_operator_bad_object
+ bad = Object.new
+ def bad.==(other) true end
+
+ @tc.refute_operator true, :equal?, bad
+ end
+
def test_refute_operator_triggered
util_assert_triggered "Expected 2 to not be > 1." do
@tc.refute_operator 2, :>, 1
@@ -1148,4 +1444,19 @@ FILE:LINE:in `test_assert_raises_triggered_subclass'
assert_equal expected, msg
end
+
+ def util_msg exp, act, msg = nil
+ s = "Expected: #{exp.inspect}\n Actual: #{act.inspect}"
+ s = "#{msg}.\n#{s}" if msg
+ s
+ end
+
+ def without_diff
+ old_diff = MiniTest::Assertions.diff
+ MiniTest::Assertions.diff = nil
+
+ yield
+ ensure
+ MiniTest::Assertions.diff = old_diff
+ end
end
--
ruby-minitest.git
More information about the Pkg-ruby-extras-commits
mailing list