From 3632f4cf1cfda24d81e1dbe0576fbce52fcb85af Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 30 Nov 2010 22:45:53 +0000 Subject: Imported minitest 2.0.0 r5952 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29986 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 + lib/minitest/benchmark.rb | 330 +++++++++ lib/minitest/mock.rb | 21 +- lib/minitest/pride.rb | 41 ++ lib/minitest/spec.rb | 13 +- lib/minitest/unit.rb | 281 +++++--- test/minitest/test_mini_mock.rb | 83 --- test/minitest/test_mini_spec.rb | 225 ------ test/minitest/test_mini_test.rb | 1126 ------------------------------ test/minitest/test_minitest_benchmark.rb | 104 +++ test/minitest/test_minitest_mock.rb | 112 +++ test/minitest/test_minitest_spec.rb | 235 +++++++ test/minitest/test_minitest_unit.rb | 1104 +++++++++++++++++++++++++++++ 13 files changed, 2145 insertions(+), 1535 deletions(-) create mode 100644 lib/minitest/benchmark.rb create mode 100644 lib/minitest/pride.rb delete mode 100644 test/minitest/test_mini_mock.rb delete mode 100644 test/minitest/test_mini_spec.rb delete mode 100644 test/minitest/test_mini_test.rb create mode 100644 test/minitest/test_minitest_benchmark.rb create mode 100644 test/minitest/test_minitest_mock.rb create mode 100644 test/minitest/test_minitest_spec.rb create mode 100644 test/minitest/test_minitest_unit.rb diff --git a/ChangeLog b/ChangeLog index 440ee3d9e0..53ff86dd08 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed Dec 1 07:42:42 2010 Ryan Davis + + * lib/minitest/*.rb: Imported minitest 2.0.0 r5952. + * test/minitest/*.rb: ditto. + Wed Dec 1 01:29:15 2010 NARUSE, Yui * string.c (rb_str_inspect): inspect as a dummy encoding string diff --git a/lib/minitest/benchmark.rb b/lib/minitest/benchmark.rb new file mode 100644 index 0000000000..2bf8dd9c00 --- /dev/null +++ b/lib/minitest/benchmark.rb @@ -0,0 +1,330 @@ +############################################################ +# This file is imported from a different project. +# DO NOT make modifications in this repo. +# File a patch instead and assign it to Ryan Davis +############################################################ + +require 'minitest/unit' +require 'minitest/spec' + +class MiniTest::Unit + attr_accessor :runner + + def run_benchmarks + _run_anything :benchmark + end + + def benchmark_suite_header suite + "\n#{suite}\t#{suite.bench_range.join("\t")}" + end + + class TestCase + ## + # Returns a set of ranges stepped exponentially from +min+ to + # +max+ by powers of +base+. Eg: + # + # bench_exp(2, 16, 2) # => [2, 4, 8, 16] + + def self.bench_exp min, max, base = 10 + min = (Math.log10(min) / Math.log10(base)).to_i + max = (Math.log10(max) / Math.log10(base)).to_i + + (min..max).map { |m| base ** m }.to_a + end + + ## + # Returns a set of ranges stepped linearly from +min+ to +max+ by + # +step+. Eg: + # + # bench_linear(20, 40, 10) # => [20, 30, 40] + + def self.bench_linear min, max, step = 10 + (min..max).step(step).to_a + rescue LocalJumpError # 1.8.6 + r = []; (min..max).step(step) { |n| r << n }; r + end + + ## + # Returns the benchmark methods (methods that start with bench_) + # for that class. + + def self.benchmark_methods # :nodoc: + public_instance_methods(true).grep(/^bench_/).map { |m| m.to_s }.sort + end + + ## + # Returns all test suites that have benchmark methods. + + def self.benchmark_suites + TestCase.test_suites.reject { |s| s.benchmark_methods.empty? } + end + + ## + # Specifies the ranges used for benchmarking for that class. + # Defaults to exponential growth from 1 to 10k by powers of 10. + # Override if you need different ranges for your benchmarks. + # + # See also: ::bench_exp and ::bench_linear. + + def self.bench_range + bench_exp 1, 10_000 + end + + ## + # Runs the given +work+, gathering the times of each run. Range + # and times are then passed to a given +validation+ proc. Outputs + # the benchmark name and times in tab-separated format, making it + # easy to paste into a spreadsheet for graphing or further + # analysis. + # + # Ranges are specified by ::bench_range. + # + # Eg: + # + # def bench_algorithm + # validation = proc { |x, y| ... } + # assert_performance validation do |x| + # @obj.algorithm + # end + # end + + def assert_performance validation, &work + range = self.class.bench_range + + io.print "#{__name__}" + + times = [] + + range.each do |x| + GC.start + t0 = Time.now + instance_exec(x, &work) + t = Time.now - t0 + + io.print "\t%9.6f" % t + times << t + end + io.puts + + validation[range, times] + end + + ## + # Runs the given +work+ and asserts that the times gathered fit to + # match a constant rate (eg, linear slope == 0) within a given error + # +threshold+. + # + # Fit is calculated by #fit_constant. + # + # Ranges are specified by ::bench_range. + # + # Eg: + # + # def bench_algorithm + # assert_performance_constant 0.9999 do |x| + # @obj.algorithm + # end + # end + + def assert_performance_constant threshold = 0.99, &work + validation = proc do |range, times| + a, b, rr = fit_linear range, times + assert_in_delta 0, b, 1 - threshold + [a, b, rr] + end + + assert_performance validation, &work + end + + ## + # Runs the given +work+ and asserts that the times gathered fit to + # match a exponential curve within a given error +threshold+. + # + # Fit is calculated by #fit_exponential. + # + # Ranges are specified by ::bench_range. + # + # Eg: + # + # def bench_algorithm + # assert_performance_exponential 0.9999 do |x| + # @obj.algorithm + # end + # end + + def assert_performance_exponential threshold = 0.99, &work + assert_performance validation_for_fit(:exponential, threshold), &work + end + + ## + # Runs the given +work+ and asserts that the times gathered fit to + # match a straight line within a given error +threshold+. + # + # Fit is calculated by #fit_linear. + # + # Ranges are specified by ::bench_range. + # + # Eg: + # + # def bench_algorithm + # assert_performance_linear 0.9999 do |x| + # @obj.algorithm + # end + # end + + def assert_performance_linear threshold = 0.99, &work + assert_performance validation_for_fit(:linear, threshold), &work + end + + ## + # Runs the given +work+ and asserts that the times gathered curve + # fit to match a power curve within a given error +threshold+. + # + # Fit is calculated by #fit_power. + # + # Ranges are specified by ::bench_range. + # + # Eg: + # + # def bench_algorithm + # assert_performance_power 0.9999 do |x| + # @obj.algorithm + # end + # end + + def assert_performance_power threshold = 0.99, &work + assert_performance validation_for_fit(:power, threshold), &work + end + + ## + # Takes an array of x/y pairs and calculates the general R^2 value. + # + # See: http://en.wikipedia.org/wiki/Coefficient_of_determination + + def fit_error xys + y_bar = sigma(xys) { |x, y| y } / xys.size.to_f + ss_tot = sigma(xys) { |x, y| (y - y_bar) ** 2 } + ss_err = sigma(xys) { |x, y| (yield(x) - y) ** 2 } + + 1 - (ss_err / ss_tot) + end + + ## + # To fit a functional form: y = ae^(bx). + # + # Takes x and y values and returns [a, b, r^2]. + # + # See: http://mathworld.wolfram.com/LeastSquaresFittingExponential.html + + def fit_exponential xs, ys + n = xs.size + xys = xs.zip(ys) + sxlny = sigma(xys) { |x,y| x * Math.log(y) } + slny = sigma(xys) { |x,y| Math.log(y) } + sx2 = sigma(xys) { |x,y| x * x } + sx = sigma xs + + c = n * sx2 - sx ** 2 + a = (slny * sx2 - sx * sxlny) / c + b = ( n * sxlny - sx * slny ) / c + + return Math.exp(a), b, fit_error(xys) { |x| Math.exp(a + b * x) } + end + + ## + # Fits the functional form: a + bx. + # + # Takes x and y values and returns [a, b, r^2]. + # + # See: http://mathworld.wolfram.com/LeastSquaresFitting.html + + def fit_linear xs, ys + n = xs.size + xys = xs.zip(ys) + sx = sigma xs + sy = sigma ys + sx2 = sigma(xs) { |x| x ** 2 } + sxy = sigma(xys) { |x,y| x * y } + + c = n * sx2 - sx**2 + a = (sy * sx2 - sx * sxy) / c + b = ( n * sxy - sx * sy ) / c + + return a, b, fit_error(xys) { |x| a + b * x } + end + + ## + # To fit a functional form: y = ax^b. + # + # Takes x and y values and returns [a, b, r^2]. + # + # See: http://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html + + def fit_power xs, ys + n = xs.size + xys = xs.zip(ys) + slnxlny = sigma(xys) { |x, y| Math.log(x) * Math.log(y) } + slnx = sigma(xs) { |x | Math.log(x) } + slny = sigma(ys) { | y| Math.log(y) } + slnx2 = sigma(xs) { |x | Math.log(x) ** 2 } + + b = (n * slnxlny - slnx * slny) / (n * slnx2 - slnx ** 2); + a = (slny - b * slnx) / n + + return Math.exp(a), b, fit_error(xys) { |x| (Math.exp(a) * (x ** b)) } + end + + ## + # Enumerates over +enum+ mapping +block+ if given, returning the + # sum of the result. Eg: + # + # sigma([1, 2, 3]) # => 1 + 2 + 3 => 7 + # sigma([1, 2, 3]) { |n| n ** 2 } # => 1 + 4 + 9 => 14 + + def sigma enum, &block + enum = enum.map(&block) if block + enum.inject { |sum, n| sum + n } + end + + ## + # Returns a proc that calls the specified fit method and asserts + # that the error is within a tolerable threshold. + + def validation_for_fit msg, threshold + proc do |range, times| + a, b, rr = send "fit_#{msg}", range, times + assert_operator rr, :>=, threshold + [a, b, rr] + end + end + end +end + +class MiniTest::Spec + def self.bench name, &block + define_method "bench_#{name.gsub(/\W+/, '_')}", &block + end + + def self.bench_range &block + meta = (class << self; self; end) + meta.send :define_method, "bench_range", &block + end + + def self.bench_performance_linear name, threshold = 0.9, &work + bench name do + assert_performance_linear threshold, &work + end + end + + def self.bench_performance_constant name, threshold = 0.99, &work + bench name do + assert_performance_constant threshold, &work + end + end + + def self.bench_performance_exponential name, threshold = 0.99, &work + bench name do + assert_performance_exponential threshold, &work + end + end +end diff --git a/lib/minitest/mock.rb b/lib/minitest/mock.rb index 4871e8b183..99f7992aa9 100644 --- a/lib/minitest/mock.rb +++ b/lib/minitest/mock.rb @@ -14,14 +14,7 @@ module MiniTest end def expect(name, retval, args=[]) - n, r = name, retval # for the closure below @expected_calls[name] = { :retval => retval, :args => args } - self.class.__send__ :remove_method, name if respond_to? name - self.class.__send__(:define_method, name) { |*x| - raise ArgumentError unless @expected_calls[n][:args].size == x.size - @actual_calls[n] << { :retval => r, :args => x } - retval - } self end @@ -34,5 +27,19 @@ module MiniTest end true end + + def method_missing(sym, *args) + 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 } + retval + end + + alias :original_respond_to? :respond_to? + def respond_to?(sym) + return true if @expected_calls.has_key?(sym) + return original_respond_to?(sym) + end end end diff --git a/lib/minitest/pride.rb b/lib/minitest/pride.rb new file mode 100644 index 0000000000..3cb4e1564c --- /dev/null +++ b/lib/minitest/pride.rb @@ -0,0 +1,41 @@ +############################################################ +# This file is imported from a different project. +# DO NOT make modifications in this repo. +# File a patch instead and assign it to Ryan Davis +############################################################ + +require "minitest/unit" + +## +# Show your testing pride! + +class PrideIO + attr_reader :io + + # stolen from /System/Library/Perl/5.10.0/Term/ANSIColor.pm + COLORS = (31..36).to_a + CHARS = ["*"] + + def initialize io + @io = io + @colors = COLORS.cycle + @chars = CHARS.cycle + end + + def print o + case o + when "." then + io.print "\e[#{@colors.next}m#{@chars.next}\e[0m" + when "E", "F" then + io.print "\e[41m\e[37m#{o}\e[0m" + else + io.print o + end + end + + def method_missing msg, *args + io.send(msg, *args) + end +end + +MiniTest::Unit.output = PrideIO.new(MiniTest::Unit.output) diff --git a/lib/minitest/spec.rb b/lib/minitest/spec.rb index 2050337015..8e2412e5ea 100644 --- a/lib/minitest/spec.rb +++ b/lib/minitest/spec.rb @@ -66,10 +66,13 @@ module Kernel def describe desc, &block stack = MiniTest::Spec.describe_stack - name = desc.to_s.split(/\W+/).map { |s| s.capitalize }.join + "Spec" - prev = stack.last - name = "#{prev == MiniTest::Spec ? nil : prev}::#{name}" - cls = Object.class_eval "class #{name} < #{prev}; end; #{name}" + name = [stack.last, desc].compact.join("::") + cls = Class.new(stack.last || MiniTest::Spec) + + # :stopdoc: + # omg this sucks + (class << cls; self; end).send(:define_method, :to_s) { name } + # :startdoc: cls.nuke_test_methods! @@ -96,7 +99,7 @@ end class MiniTest::Spec < MiniTest::Unit::TestCase - @@describe_stack = [MiniTest::Spec] + @@describe_stack = [] def self.describe_stack # :nodoc: @@describe_stack end diff --git a/lib/minitest/unit.rb b/lib/minitest/unit.rb index 80c76c45f3..65e84230dd 100644 --- a/lib/minitest/unit.rb +++ b/lib/minitest/unit.rb @@ -8,6 +8,8 @@ require 'optparse' ## # Minimal (mostly drop-in) replacement for test-unit. +# +# :include: README.txt module MiniTest @@ -27,7 +29,8 @@ module MiniTest require 'pathname' pwd = Pathname.new Dir.pwd pn = Pathname.new File.expand_path(__FILE__) - pn = File.join(".", pn.relative_path_from(pwd)) unless pn.relative? + relpath = pn.relative_path_from(pwd) rescue pn + pn = File.join ".", relpath unless pn.relative? pn.to_s else # assume both are expanded __FILE__ @@ -40,13 +43,19 @@ module MiniTest return ["No backtrace"] unless bt new_bt = [] - bt.each do |line| - break if line.rindex(MINI_DIR, 0) - new_bt << line + + unless $DEBUG then + bt.each do |line| + break if line.rindex MINI_DIR, 0 + new_bt << line + end + + new_bt = bt.reject { |line| line.rindex MINI_DIR, 0 } if new_bt.empty? + new_bt = bt.dup if new_bt.empty? + else + new_bt = bt.dup end - new_bt = bt.reject { |line| line.rindex(MINI_DIR, 0) } if new_bt.empty? - new_bt = bt.dup if new_bt.empty? new_bt end @@ -62,7 +71,7 @@ module MiniTest def mu_pp obj s = obj.inspect - s = s.force_encoding(Encoding.default_external) if defined? Encoding + s = s.force_encoding Encoding.default_external if defined? Encoding s end @@ -91,15 +100,14 @@ module MiniTest # Fails unless the block returns a true value. def assert_block msg = nil - msg = message(msg) { "Expected block to return true value" } - assert yield, msg + assert yield, "Expected block to return true value." end ## # Fails unless +obj+ is empty. def assert_empty obj, msg = nil - msg = message(msg) { "Expected #{obj.inspect} to be empty" } + msg = message(msg) { "Expected #{mu_pp(obj)} to be empty" } assert_respond_to obj, :empty? assert obj.empty?, msg end @@ -249,8 +257,8 @@ module MiniTest def assert_respond_to obj, meth, msg = nil msg = message(msg) { - "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}" - } + "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}" + } assert obj.respond_to?(meth), msg end @@ -512,27 +520,61 @@ module MiniTest end class Unit - VERSION = "1.7.2" # :nodoc: + VERSION = "2.0.0" # :nodoc: attr_accessor :report, :failures, :errors, :skips # :nodoc: attr_accessor :test_count, :assertion_count # :nodoc: attr_accessor :start_time # :nodoc: + attr_accessor :help # :nodoc: + attr_accessor :verbose # :nodoc: + attr_writer :options # :nodoc: + + def options + @options ||= {} + end @@installed_at_exit ||= false @@out = $stdout + ## + # A simple hook allowing you to run a block of code after the + # tests are done. Eg: + # + # MiniTest::Unit.after_tests { p $debugging_info } + + def self.after_tests + at_exit { at_exit { yield } } + end + ## # Registers MiniTest::Unit to run tests at process exit def self.autorun at_exit { next if $! # don't run if there was an exception - exit_code = MiniTest::Unit.new.run(ARGV) + exit_code = MiniTest::Unit.new.run ARGV exit false if exit_code && exit_code != 0 } unless @@installed_at_exit @@installed_at_exit = true end + ## + # Returns the stream to use for output. + + def self.output + @@out + end + + ## + # Returns the stream to use for output. + # + # DEPRECATED: use ::output instead. + + def self.out + warn "::out deprecated, use ::output instead." if $VERBOSE + output + end + ## # Sets MiniTest::Unit to write output to +stream+. $stdout is the default # output @@ -541,6 +583,93 @@ module MiniTest @@out = stream end + ## + # Return all plugins' run methods (methods that start with "run_"). + + def self.plugins + @@plugins ||= (["run_tests"] + + public_instance_methods(false). + grep(/^run_/).map { |s| s.to_s }).uniq + end + + def output + self.class.output + end + + def puts *a # :nodoc: + output.puts(*a) + end + + def print *a # :nodoc: + output.print(*a) + end + + def _run_anything type + suites = TestCase.send "#{type}_suites" + return if suites.empty? + + start = Time.now + + puts + puts "# Running #{type}s:" + puts + + @test_count, @assertion_count = 0, 0 + sync = output.respond_to? :"sync=" # stupid emacs + old_sync, output.sync = output.sync, true if sync + + results = _run_suites suites, type + + @test_count = results.inject(0) { |sum, (tc, ac)| sum + tc } + @assertion_count = results.inject(0) { |sum, (tc, ac)| sum + ac } + + output.sync = old_sync if sync + + t = Time.now - start + + puts + puts + puts "Finished #{type}s in %.6fs, %.4f tests/s, %.4f assertions/s." % + [t, test_count / t, assertion_count / t] + + report.each_with_index do |msg, i| + puts "\n%3d) %s" % [i + 1, msg] + end + + puts + + status + end + + def _run_suites suites, type + suites.map { |suite| _run_suite suite, type } + end + + def _run_suite suite, type + header = "#{type}_suite_header" + puts send(header, suite) if respond_to? header + + filter = options[:filter] || '/./' + filter = Regexp.new $1 if filter =~ /\/(.*)\// + + assertions = suite.send("#{type}_methods").grep(filter).map { |method| + inst = suite.new method + inst._assertions = 0 + + start_time = Time.now + result = inst.run self + time = Time.now - start_time + + print "#{suite}##{method} = %.2f s = " % time if @verbose + print result + puts if @verbose + + inst._assertions + } + + return assertions.size, assertions.inject(0) { |sum, n| sum + n } + end + def location e # :nodoc: last_before_assertion = "" e.backtrace.reverse_each do |s| @@ -564,7 +693,7 @@ module MiniTest "Failure:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n" else @errors += 1 - bt = MiniTest::filter_backtrace(e.backtrace).join("\n ") + bt = MiniTest::filter_backtrace(e.backtrace).join "\n " "Error:\n#{meth}(#{klass}):\n#{e.class}: #{e.message}\n #{bt}\n" end @report << e @@ -579,6 +708,7 @@ module MiniTest def process_args args = [] options = {} + orig_args = args.dup OptionParser.new do |opts| opts.banner = 'minitest options:' @@ -601,9 +731,21 @@ module MiniTest options[:filter] = a end - opts.parse args + opts.parse! args + orig_args -= args + end + + unless options[:seed] then + srand + options[:seed] = srand % 0xFFFF + orig_args << "--seed" << options[:seed].to_s end + srand options[:seed] + + self.verbose = options[:verbose] + @help = orig_args.map { |s| s =~ /[\s|&<>$()]/ ? s.inspect : s }.join " " + options end @@ -611,89 +753,40 @@ module MiniTest # Top level driver, controls all output and filtering. def run args = [] - options = process_args args - - @verbose = options[:verbose] + self.options = process_args args - filter = options[:filter] || '/./' - filter = Regexp.new $1 if filter and filter =~ /\/(.*)\// + puts "Run options: #{help}" - seed = options[:seed] - unless seed then - srand - seed = srand % 0xFFFF + self.class.plugins.each do |plugin| + send plugin + break unless report.empty? end - srand seed - - help = ["--seed", seed] - help.push "--verbose" if @verbose - help.push("--name", options[:filter].inspect) if options[:filter] - - @@out.puts "Test run options: #{help.join(" ")}" - @@out.puts - @@out.puts "Loaded suite #{$0.sub(/\.rb$/, '')}\nStarted" - - start = Time.now - run_test_suites filter - - @@out.puts - @@out.puts "Finished in #{'%.6f' % (Time.now - start)} seconds." - - @report.each_with_index do |msg, i| - @@out.puts "\n%3d) %s" % [i + 1, msg] - end - - @@out.puts - - status - - @@out.puts - - @@out.puts "Test run options: #{help.join(" ")}" - return failures + errors if @test_count > 0 # or return nil... rescue Interrupt abort 'Interrupted' end ## - # Writes status to +io+ + # Runs test suites matching +filter+. - def status io = @@out - format = "%d tests, %d assertions, %d failures, %d errors, %d skips" - io.puts format % [test_count, assertion_count, failures, errors, skips] + def run_tests + _run_anything :test end ## - # Runs test suites matching +filter+ + # Writes status to +io+ - def run_test_suites filter = /./ - @test_count, @assertion_count = 0, 0 - old_sync, @@out.sync = @@out.sync, true if @@out.respond_to? :sync= - TestCase.test_suites.each do |suite| - suite.test_methods.grep(filter).each do |test| - inst = suite.new test - inst._assertions = 0 - @@out.print "#{suite}##{test}: " if @verbose - - @start_time = Time.now - result = inst.run(self) - - @@out.print "%.2f s: " % (Time.now - @start_time) if @verbose - @@out.print result - @@out.puts if @verbose - @test_count += 1 - @assertion_count += inst._assertions - end - end - @@out.sync = old_sync if @@out.respond_to? :sync= - [@test_count, @assertion_count] + def status io = self.output + format = "%d tests, %d assertions, %d failures, %d errors, %d skips" + io.puts format % [test_count, assertion_count, failures, errors, skips] end ## - # Subclass TestCase to create your own tests. Typically you'll want a + # Subclass TestCase to create your own tests. Typically you'll want a # TestCase subclass per implementation class. + # + # See MiniTest::Assertions class TestCase attr_reader :__name__ # :nodoc: @@ -707,30 +800,31 @@ module MiniTest # Runs the tests reporting the status to +runner+ def run runner - trap 'INFO' do - warn '%s#%s %.2fs' % [self.class, self.__name__, - (Time.now - runner.start_time)] + trap "INFO" do + time = Time.now - runner.start_time + warn "%s#%s %.2fs" % [self.class, self.__name__, time] runner.status $stderr end if SUPPORTS_INFO_SIGNAL - result = '.' + result = "" begin @passed = nil self.setup self.__send__ self.__name__ + result = "." unless io? @passed = true rescue *PASSTHROUGH_EXCEPTIONS raise rescue Exception => e @passed = false - result = runner.puke(self.class, self.__name__, e) + result = runner.puke self.class, self.__name__, e ensure begin self.teardown rescue *PASSTHROUGH_EXCEPTIONS raise rescue Exception => e - result = runner.puke(self.class, self.__name__, e) + result = runner.puke self.class, self.__name__, e end trap 'INFO', 'DEFAULT' if SUPPORTS_INFO_SIGNAL end @@ -739,9 +833,19 @@ module MiniTest def initialize name # :nodoc: @__name__ = name + @__io__ = nil @passed = nil end + def io + @__io__ = true + MiniTest::Unit.output + end + + def io? + @__io__ + end + def self.reset # :nodoc: @@test_suites = {} end @@ -762,7 +866,7 @@ module MiniTest end def self.test_suites # :nodoc: - @@test_suites.keys.sort_by { |ts| ts.name } + @@test_suites.keys.sort_by { |ts| ts.name.to_s } end def self.test_methods # :nodoc: @@ -771,7 +875,7 @@ module MiniTest case self.test_order when :random then max = methods.size - methods.sort.sort_by { rand(max) } + methods.sort.sort_by { rand max } when :alpha, :sorted then methods.sort else @@ -813,4 +917,3 @@ if $DEBUG then end end end - diff --git a/test/minitest/test_mini_mock.rb b/test/minitest/test_mini_mock.rb deleted file mode 100644 index 0f16ae930e..0000000000 --- a/test/minitest/test_mini_mock.rb +++ /dev/null @@ -1,83 +0,0 @@ -############################################################ -# This file is imported from a different project. -# DO NOT make modifications in this repo. -# File a patch instead and assign it to Ryan Davis -############################################################ - -require 'minitest/mock' -require 'minitest/unit' - -MiniTest::Unit.autorun - -class TestMiniMock < MiniTest::Unit::TestCase - def setup - @mock = MiniTest::Mock.new.expect(:foo, nil) - @mock.expect(:meaning_of_life, 42) - end - - def test_should_create_stub_method - assert_nil @mock.foo - end - - def test_should_allow_return_value_specification - assert_equal 42, @mock.meaning_of_life - end - - def test_should_blow_up_if_not_called - @mock.foo - - util_verify_bad - end - - def test_should_not_blow_up_if_everything_called - @mock.foo - @mock.meaning_of_life - - assert @mock.verify - end - - def test_should_allow_expectations_to_be_added_after_creation - @mock.expect(:bar, true) - assert @mock.bar - end - - def test_should_not_verify_if_new_expected_method_is_not_called - @mock.foo - @mock.meaning_of_life - @mock.expect(:bar, true) - - util_verify_bad - end - - def test_should_not_verify_if_unexpected_method_is_called - assert_raises NoMethodError do - @mock.unexpected - end - end - - def test_should_blow_up_on_wrong_number_of_arguments - @mock.foo - @mock.meaning_of_life - @mock.expect(:sum, 3, [1, 2]) - - assert_raises ArgumentError do - @mock.sum - end - end - - def test_should_blow_up_on_wrong_arguments - @mock.foo - @mock.meaning_of_life - @mock.expect(:sum, 3, [1, 2]) - - @mock.sum(2, 4) - - util_verify_bad - end - - def util_verify_bad - assert_raises MockExpectationError do - @mock.verify - end - end -end diff --git a/test/minitest/test_mini_spec.rb b/test/minitest/test_mini_spec.rb deleted file mode 100644 index f2e30c66d0..0000000000 --- a/test/minitest/test_mini_spec.rb +++ /dev/null @@ -1,225 +0,0 @@ -############################################################ -# This file is imported from a different project. -# DO NOT make modifications in this repo. -# File a patch instead and assign it to Ryan Davis -############################################################ - -require 'minitest/spec' - -MiniTest::Unit.autorun - -describe MiniTest::Spec do - before do - @assertion_count = 4 - end - - after do - self._assertions.must_equal @assertion_count - end - - # TODO: figure out how the hell to write a test for this - # it "will skip if there is no block" - - it "needs to have all methods named well" do - @assertion_count = 2 - - methods = Object.public_instance_methods.find_all { |n| n =~ /^must|^wont/ } - methods.map! { |m| m.to_s } if Symbol === methods.first - - musts, wonts = methods.sort.partition { |m| m =~ /^must/ } - - expected_musts = %w(must_be - must_be_close_to - must_be_empty - must_be_instance_of - must_be_kind_of - must_be_nil - must_be_same_as - must_be_silent - must_be_within_delta - must_be_within_epsilon - must_equal - must_include - must_match - must_output - must_raise - must_respond_to - must_send - must_throw) - - bad = %w[not raise throw send output be_silent] - - expected_wonts = expected_musts.map { |m| m.sub(/^must/, 'wont') } - expected_wonts.reject! { |m| m =~ /wont_#{Regexp.union(*bad)}/ } - - musts.must_equal expected_musts - wonts.must_equal expected_wonts - end - - it "needs to verify equality" do - (6 * 7).must_equal(42).must_equal true - proc { (6 * 9).must_equal(42) }.must_raise MiniTest::Assertion - end - - it "needs to verify floats within a delta" do - (6.0 * 7).must_be_close_to(42.0).must_equal true - proc { 42.002.must_be_close_to 42.0 }.must_raise MiniTest::Assertion - end - - it "needs to verify types of objects" do - (6 * 7).must_be_instance_of(Fixnum).must_equal true - proc { (6 * 7).must_be_instance_of String }.must_raise MiniTest::Assertion - end - - it "needs to verify kinds of objects" do - @assertion_count = 6 - - (6 * 7).must_be_kind_of(Fixnum).must_equal true - (6 * 7).must_be_kind_of(Numeric).must_equal true - proc { (6 * 7).must_be_kind_of String }.must_raise MiniTest::Assertion - end - - it "needs to verify regexp matches" do - @assertion_count = 6 - - "blah".must_match(/\w+/).must_equal true - proc { "blah".must_match(/\d+/) }.must_raise MiniTest::Assertion - end - - it "needs to verify nil" do - nil.must_be_nil.must_equal true - proc { 42.must_be_nil }.must_raise MiniTest::Assertion - end - - it "needs to verify using any operator" do - 41.must_be(:<, 42).must_equal true - proc { 42.must_be(:<, 41) }.must_raise MiniTest::Assertion - end - - it "needs to catch an expected exception" do - @assertion_count = 2 - - proc { raise "blah" }.must_raise RuntimeError - proc { raise MiniTest::Assertion }.must_raise MiniTest::Assertion - end - - it "needs to catch an unexpected exception" do - @assertion_count = 2 - - proc { - proc { raise MiniTest::Assertion }.must_raise(RuntimeError) - }.must_raise MiniTest::Assertion - end - - it "needs raise if an expected exception is not raised" do - @assertion_count = 2 - - proc { proc { 42 }.must_raise(RuntimeError) }.must_raise MiniTest::Assertion - end - - it "needs to be able to catch a MiniTest::Assertion exception" do - @assertion_count = 2 - - proc { 1.wont_equal 1 }.must_raise MiniTest::Assertion - end - - it "needs to verify using respond_to" do - 42.must_respond_to(:+).must_equal true - proc { 42.must_respond_to(:clear) }.must_raise MiniTest::Assertion - end - - it "needs to verify identity" do - 1.must_be_same_as(1).must_equal true - proc { 1.must_be_same_as 2 }.must_raise MiniTest::Assertion - end - - it "needs to verify throw" do - @assertion_count = 6 - - proc { throw :blah }.must_throw(:blah).must_equal true - proc { proc { }.must_throw(:blah) }.must_raise MiniTest::Assertion - proc { proc { throw :xxx }.must_throw(:blah) }.must_raise MiniTest::Assertion - end - - it "needs to verify inequality" do - 42.wont_equal(6 * 9).must_equal false - proc { 1.wont_equal 1 }.must_raise MiniTest::Assertion - end - - it "needs to verify mismatch" do - @assertion_count = 6 - "blah".wont_match(/\d+/).must_equal false - proc { "blah".wont_match(/\w+/) }.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 - end - - it "needs to verify non-identity" do - 1.wont_be_same_as(2).must_equal false - proc { 1.wont_be_same_as 1 }.must_raise MiniTest::Assertion - end - - it "needs to verify output in stdout" do - proc { print "blah" }.must_output("blah").must_equal true - - proc { - proc { print "xxx" }.must_output("blah") - }.must_raise MiniTest::Assertion - end - - it "needs to verify output in stderr" do - proc { $stderr.print "blah" }.must_output(nil, "blah").must_equal true - - proc { - proc { $stderr.print "xxx" }.must_output(nil, "blah") - }.must_raise MiniTest::Assertion - end - - it "needs to ensure silence" do - @assertion_count = 5 - - proc { }.must_be_silent.must_equal true - - proc { - proc { print "xxx" }.must_be_silent - }.must_raise MiniTest::Assertion - end - - it "needs to be sensible about must_include order" do - @assertion_count = 6 - [1, 2, 3].must_include(2).must_equal true - proc { [1, 2, 3].must_include 5 }.must_raise MiniTest::Assertion - end - - it "needs to be sensible about wont_include order" do - @assertion_count = 6 - [1, 2, 3].wont_include(5).must_equal false - proc { [1, 2, 3].wont_include 2 }.must_raise MiniTest::Assertion - end -end - -class TestMeta < MiniTest::Unit::TestCase - def test_structure - x = y = nil - x = describe "top-level thingy" do - before {} - after {} - - it "top-level-it" do end - - y = describe "inner thingy" do - before {} - it "inner-it" do end - end - end - - top_methods = %w(setup teardown test_0001_top_level_it) - inner_methods = %w(setup test_0001_inner_it) - - 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 } - end -end diff --git a/test/minitest/test_mini_test.rb b/test/minitest/test_mini_test.rb deleted file mode 100644 index 176f6ec26f..0000000000 --- a/test/minitest/test_mini_test.rb +++ /dev/null @@ -1,1126 +0,0 @@ -############################################################ -# This file is imported from a different project. -# DO NOT make modifications in this repo. -# File a patch instead and assign it to Ryan Davis -############################################################ - -require 'stringio' -require 'pathname' -require 'minitest/unit' - -MiniTest::Unit.autorun - -module M; end -class E < StandardError; include M; end - -class TestMiniTest < MiniTest::Unit::TestCase - pwd = Pathname.new(File.expand_path(Dir.pwd)) - basedir = Pathname.new(File.expand_path(MiniTest::MINI_DIR)) + 'mini' - basedir = basedir.relative_path_from(pwd).to_s - MINITEST_BASE_DIR = basedir[/\A\./] ? basedir : "./#{basedir}" - BT_MIDDLE = ["#{MINITEST_BASE_DIR}/test.rb:165:in `run_test_suites'", - "#{MINITEST_BASE_DIR}/test.rb:161:in `each'", - "#{MINITEST_BASE_DIR}/test.rb:161:in `run_test_suites'", - "#{MINITEST_BASE_DIR}/test.rb:158:in `each'", - "#{MINITEST_BASE_DIR}/test.rb:158:in `run_test_suites'", - "#{MINITEST_BASE_DIR}/test.rb:139:in `run'", - "#{MINITEST_BASE_DIR}/test.rb:106:in `run'"] - - def assert_report expected = nil - expected ||= "Test run options: --seed 42 - -Loaded suite blah -Started -. -Finished in 0.00 - -1 tests, 1 assertions, 0 failures, 0 errors, 0 skips - -Test run options: --seed 42 -" - output = @output.string.sub(/Finished in .*/, "Finished in 0.00") - output.sub!(/Loaded suite .*/, 'Loaded suite blah') - output.sub!(/^(\s+)(?:#{Regexp.union(__FILE__, File.expand_path(__FILE__))}):\d+:/o, '\1FILE:LINE:') - output.sub!(/\[(?:#{Regexp.union(__FILE__, File.expand_path(__FILE__))}):\d+\]/o, '[FILE:LINE]') - assert_equal(expected, output) - end - - def setup - srand 42 - MiniTest::Unit::TestCase.reset - @tu = MiniTest::Unit.new - @output = StringIO.new("") - MiniTest::Unit.output = @output - assert_equal [0, 0], @tu.run_test_suites - end - - def teardown - MiniTest::Unit.output = $stdout - Object.send :remove_const, :ATestCase if defined? ATestCase - 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) - end - - def test_class_puke_with_assertion_failed_and_long_backtrace - bt = (["test/test_some_class.rb:615:in `method_name'", - "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raises'", - "test/test_some_class.rb:615:in `each'", - "test/test_some_class.rb:614:in `test_method_name'", - "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/test.rb:29"]) - bt = util_expand_bt bt - - ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first - - exception = MiniTest::Assertion.new "Oh no!" - exception.set_backtrace bt - 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) - end - - def test_class_puke_with_assertion_failed_and_user_defined_assertions - bt = (["lib/test/my/util.rb:16:in `another_method_name'", - "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raises'", - "lib/test/my/util.rb:15:in `block in assert_something'", - "lib/test/my/util.rb:14:in `each'", - "lib/test/my/util.rb:14:in `assert_something'", - "test/test_some_class.rb:615:in `each'", - "test/test_some_class.rb:614:in `test_method_name'", - "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/test.rb:29"]) - bt = util_expand_bt bt - - ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first - - exception = MiniTest::Assertion.new "Oh no!" - exception.set_backtrace bt - 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) - end - - def test_class_puke_with_failure_and_flunk_in_backtrace - exception = begin - MiniTest::Unit::TestCase.new('fake tc').flunk - rescue MiniTest::Assertion => failure - failure - end - assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception) - refute @tu.report.any?{|line| line =~ /in .flunk/} - end - - def test_class_puke_with_flunk_and_user_defined_assertions - bt = (["lib/test/my/util.rb:16:in `flunk'", - "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raises'", - "lib/test/my/util.rb:15:in `block in assert_something'", - "lib/test/my/util.rb:14:in `each'", - "lib/test/my/util.rb:14:in `assert_something'", - "test/test_some_class.rb:615:in `each'", - "test/test_some_class.rb:614:in `test_method_name'", - "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/test.rb:29"]) - bt = util_expand_bt bt - - ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first - - exception = MiniTest::Assertion.new "Oh no!" - exception.set_backtrace bt - 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) - end - - def test_class_puke_with_non_failure_exception - exception = Exception.new("Oh no again!") - assert_equal 'E', @tu.puke('SomeClass', 'method_name', exception) - assert_equal 1, @tu.errors - assert_match(/^Exception.*Oh no again!/m, @tu.report.first) - end - - def test_class_run_test_suites - tc = Class.new(MiniTest::Unit::TestCase) do - def test_something - assert true - end - end - - Object.const_set(:ATestCase, tc) - - assert_equal [1, 1], @tu.run_test_suites - end - - def test_filter_backtrace - # this is a semi-lame mix of relative paths. - # I cheated by making the autotest parts not have ./ - bt = (["lib/autotest.rb:571:in `add_exception'", - "test/test_autotest.rb:62:in `test_add_exception'", - "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/test.rb:29", - "test/test_autotest.rb:422"]) - bt = util_expand_bt bt - - ex = ["lib/autotest.rb:571:in `add_exception'", - "test/test_autotest.rb:62:in `test_add_exception'"] - ex = util_expand_bt ex - - fu = MiniTest::filter_backtrace(bt) - - assert_equal ex, fu - end - - def test_filter_backtrace_all_unit - bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/test.rb:29"]) - ex = bt.clone - fu = MiniTest::filter_backtrace(bt) - assert_equal ex, fu - end - - def test_filter_backtrace_unit_starts - bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/mini/test.rb:29", - "-e:1"]) - - bt = util_expand_bt bt - - ex = ["-e:1"] - fu = MiniTest::filter_backtrace(bt) - assert_equal ex, fu - end - - def test_run_error - tc = Class.new(MiniTest::Unit::TestCase) do - def test_something - assert true - end - - def test_error - raise "unhandled exception" - end - end - - Object.const_set(:ATestCase, tc) - - @tu.run %w[-s 42] - - expected = "Test run options: --seed 42 - -Loaded suite blah -Started -E. -Finished in 0.00 - - 1) Error: -test_error(ATestCase): -RuntimeError: unhandled exception - FILE:LINE:in `test_error' - -2 tests, 1 assertions, 0 failures, 1 errors, 0 skips - -Test run options: --seed 42 -" - assert_report expected - end - - def test_run_error_teardown - tc = Class.new(MiniTest::Unit::TestCase) do - def test_something - assert true - end - - def teardown - raise "unhandled exception" - end - end - - Object.const_set(:ATestCase, tc) - - @tu.run %w[-s 42] - - expected = "Test run options: --seed 42 - -Loaded suite blah -Started -E -Finished in 0.00 - - 1) Error: -test_something(ATestCase): -RuntimeError: unhandled exception - FILE:LINE:in `teardown' - -1 tests, 1 assertions, 0 failures, 1 errors, 0 skips - -Test run options: --seed 42 -" - assert_report expected - end - - def test_run_failing # TODO: add error test - tc = Class.new(MiniTest::Unit::TestCase) do - def test_something - assert true - end - - def test_failure - assert false - end - end - - Object.const_set(:ATestCase, tc) - - @tu.run %w[-s 42] - - expected = "Test run options: --seed 42 - -Loaded suite blah -Started -F. -Finished in 0.00 - - 1) Failure: -test_failure(ATestCase) [FILE:LINE]: -Failed assertion, no message given. - -2 tests, 2 assertions, 1 failures, 0 errors, 0 skips - -Test run options: --seed 42 -" - assert_report expected - end - - def test_run_failing_filtered - tc = Class.new(MiniTest::Unit::TestCase) do - def test_something - assert true - end - - def test_failure - assert false - end - end - - Object.const_set(:ATestCase, tc) - - @tu.run %w[-n /something/ -s 42] - - expected = "Test run options: --seed 42 --name \"/something/\" - -Loaded suite blah -Started -. -Finished in 0.00 - -1 tests, 1 assertions, 0 failures, 0 errors, 0 skips - -Test run options: --seed 42 --name \"/something/\" -" - assert_report expected - end - - def test_run_passing - tc = Class.new(MiniTest::Unit::TestCase) do - def test_something - assert true - end - end - - Object.const_set(:ATestCase, tc) - - @tu.run %w[-s 42] - - assert_report - end - - def test_run_skip - 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[-s 42] - - expected = "Test run options: --seed 42 - -Loaded suite blah -Started -S. -Finished in 0.00 - - 1) Skipped: -test_skip(ATestCase) [FILE:LINE]: -not yet - -2 tests, 1 assertions, 0 failures, 0 errors, 1 skips - -Test run options: --seed 42 -" - assert_report expected - end - - def util_expand_bt bt - if RUBY_VERSION =~ /^1\.9/ then - bt.map { |f| (f =~ /^\./) ? File.expand_path(f) : f } - else - bt - end - end -end - -class TestMiniTestTestCase < MiniTest::Unit::TestCase - def setup - MiniTest::Unit::TestCase.reset - - @tc = MiniTest::Unit::TestCase.new 'fake tc' - @zomg = "zomg ponies!" - @assertion_count = 1 - end - - def teardown - assert_equal(@assertion_count, @tc._assertions, - "expected #{@assertion_count} assertions to be fired during the test, not #{@tc._assertions}") if @tc._assertions - Object.send :remove_const, :ATestCase if defined? ATestCase - end - - def test_assert - @assertion_count = 2 - - @tc.assert_equal true, @tc.assert(true), "returns true on success" - end - - def test_assert__triggered - util_assert_triggered "Failed assertion, no message given." do - @tc.assert false - end - end - - def test_assert__triggered_message - util_assert_triggered @zomg do - @tc.assert false, @zomg - end - end - - def test_assert_block - @tc.assert_block do - true - end - end - - def test_assert_block_triggered - util_assert_triggered 'Expected block to return true value.' do - @tc.assert_block do - false - end - end - end - - def test_assert_empty - @assertion_count = 2 - - @tc.assert_empty [] - end - - def test_assert_empty_triggered - @assertion_count = 2 - - util_assert_triggered "Expected [1] to be empty." do - @tc.assert_empty [1] - end - end - - def test_assert_equal - @tc.assert_equal 1, 1 - end - - def test_assert_equal_different - util_assert_triggered "Expected 1, not 2." do - @tc.assert_equal 1, 2 - end - end - - def test_assert_in_delta - @tc.assert_in_delta 0.0, 1.0 / 1000, 0.1 - end - - def test_assert_in_delta_triggered - util_assert_triggered 'Expected 0.0 - 0.001 (0.001) to be < 1.0e-06.' do - @tc.assert_in_delta 0.0, 1.0 / 1000, 0.000001 - end - end - - def test_assert_in_epsilon - @assertion_count = 8 - - @tc.assert_in_epsilon 10000, 9991 - @tc.assert_in_epsilon 9991, 10000 - @tc.assert_in_epsilon 1.0, 1.001 - @tc.assert_in_epsilon 1.001, 1.0 - - @tc.assert_in_epsilon 10000, 9999.1, 0.0001 - @tc.assert_in_epsilon 9999.1, 10000, 0.0001 - @tc.assert_in_epsilon 1.0, 1.0001, 0.0001 - @tc.assert_in_epsilon 1.0001, 1.0, 0.0001 - end - - def test_assert_in_epsilon_triggered - util_assert_triggered 'Expected 10000 - 9990 (10) to be < 9.99.' do - @tc.assert_in_epsilon 10000, 9990 - end - end - - def test_assert_includes - @assertion_count = 2 - - @tc.assert_includes [true], true - end - - def test_assert_includes_triggered - @assertion_count = 3 - - e = @tc.assert_raises MiniTest::Assertion do - @tc.assert_includes [true], false - end - - expected = "Expected [true] to include false." - assert_equal expected, e.message - end - - def test_assert_instance_of - @tc.assert_instance_of String, "blah" - end - - def test_assert_instance_of_triggered - util_assert_triggered 'Expected "blah" to be an instance of Array, not String.' do - @tc.assert_instance_of Array, "blah" - end - end - - def test_assert_kind_of - @tc.assert_kind_of String, "blah" - end - - def test_assert_kind_of_triggered - util_assert_triggered 'Expected "blah" to be a kind of Array, not String.' do - @tc.assert_kind_of Array, "blah" - end - end - - def test_assert_match - @assertion_count = 2 - @tc.assert_match(/\w+/, "blah blah blah") - end - - def test_assert_match_object - @assertion_count = 2 - - pattern = Object.new - def pattern.=~(other) true end - - @tc.assert_match pattern, 5 - end - - def test_assert_match_object_triggered - @assertion_count = 2 - - pattern = Object.new - def pattern.=~(other) false end - def pattern.inspect; "<>" end - - util_assert_triggered 'Expected <> to match 5.' do - @tc.assert_match pattern, 5 - end - end - - def test_assert_match_triggered - @assertion_count = 2 - util_assert_triggered 'Expected /\d+/ to match "blah blah blah".' do - @tc.assert_match(/\d+/, "blah blah blah") - end - end - - def test_assert_nil - @tc.assert_nil nil - end - - def test_assert_nil_triggered - util_assert_triggered 'Expected 42 to be nil.' do - @tc.assert_nil 42 - end - end - - def test_assert_operator - @tc.assert_operator 2, :>, 1 - end - - def test_assert_operator_triggered - util_assert_triggered "Expected 2 to be < 1." do - @tc.assert_operator 2, :<, 1 - end - end - - def test_assert_output_both - @assertion_count = 2 - - @tc.assert_output "yay", "blah" do - print "yay" - $stderr.print "blah" - end - end - - def test_assert_output_err - @tc.assert_output nil, "blah" do - $stderr.print "blah" - end - end - - def test_assert_output_neither - @assertion_count = 0 - - @tc.assert_output do - # do nothing - end - end - - def test_assert_output_out - @tc.assert_output "blah" do - print "blah" - end - end - - def test_assert_output_triggered_both - util_assert_triggered "In stdout.\nExpected \"yay\", not \"boo\"." do - @tc.assert_output "yay", "blah" do - print "boo" - $stderr.print "blah blah" - end - end - end - - def test_assert_output_triggered_err - util_assert_triggered "In stderr.\nExpected \"blah\", not \"blah blah\"." do - @tc.assert_output nil, "blah" do - $stderr.print "blah blah" - end - end - end - - def test_assert_output_triggered_out - util_assert_triggered "In stdout.\nExpected \"blah\", not \"blah blah\"." do - @tc.assert_output "blah" do - print "blah blah" - end - end - end - - def test_assert_raises - @tc.assert_raises RuntimeError do - raise "blah" - end - end - - ## - # *sigh* This is quite an odd scenario, but it is from real (albeit - # ugly) test code in ruby-core: - # - # http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=29259 - - def test_assert_raises_skip - @assertion_count = 0 - - util_assert_triggered "skipped", MiniTest::Skip do - @tc.assert_raises ArgumentError do - begin - raise "blah" - rescue - skip "skipped" - end - end - end - end - - def test_assert_raises_module - @tc.assert_raises M do - raise E - end - end - - def test_assert_raises_triggered_different - e = assert_raises MiniTest::Assertion do - @tc.assert_raises RuntimeError do - raise SyntaxError, "icky" - end - end - - expected = "[RuntimeError] exception expected, not -Class: -Message: <\"icky\"> ----Backtrace--- -FILE:LINE:in `test_assert_raises_triggered_different' ----------------" - - actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE') - actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION =~ /^1\.9/ - - assert_equal expected, actual - end - - def test_assert_raises_triggered_different_msg - e = assert_raises MiniTest::Assertion do - @tc.assert_raises RuntimeError, "XXX" do - raise SyntaxError, "icky" - end - end - - expected = "XXX -[RuntimeError] exception expected, not -Class: -Message: <\"icky\"> ----Backtrace--- -FILE:LINE:in `test_assert_raises_triggered_different_msg' ----------------" - - actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE') - actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION =~ /^1\.9/ - - assert_equal expected, actual - end - - def test_assert_raises_triggered_none - e = assert_raises MiniTest::Assertion do - @tc.assert_raises MiniTest::Assertion do - # do nothing - end - end - - expected = "MiniTest::Assertion expected but nothing was raised." - - assert_equal expected, e.message - end - - def test_assert_raises_triggered_none_msg - e = assert_raises MiniTest::Assertion do - @tc.assert_raises MiniTest::Assertion, "XXX" do - # do nothing - end - end - - expected = "XXX\nMiniTest::Assertion expected but nothing was raised." - - assert_equal expected, e.message - end - - def test_assert_raises_triggered_subclass - e = assert_raises MiniTest::Assertion do - @tc.assert_raises StandardError do - raise E - end - end - - expected = "[StandardError] exception expected, not -Class: -Message: <\"E\"> ----Backtrace--- -FILE:LINE:in `test_assert_raises_triggered_subclass' ----------------" - - actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE') - actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION =~ /^1\.9/ - - assert_equal expected, actual - end - - def test_assert_respond_to - @tc.assert_respond_to "blah", :empty? - end - - def test_assert_respond_to_triggered - util_assert_triggered 'Expected "blah" (String) to respond to #rawr!.' do - @tc.assert_respond_to "blah", :rawr! - end - end - - def test_assert_same - @assertion_count = 3 - - o = "blah" - @tc.assert_same 1, 1 - @tc.assert_same :blah, :blah - @tc.assert_same o, o - end - - def test_assert_same_triggered - @assertion_count = 2 - - util_assert_triggered 'Expected 2 (oid=N) to be the same as 1 (oid=N).' do - @tc.assert_same 1, 2 - end - - s1 = "blah" - s2 = "blah" - - util_assert_triggered 'Expected "blah" (oid=N) to be the same as "blah" (oid=N).' do - @tc.assert_same s1, s2 - end - end - - def test_assert_send - @tc.assert_send [1, :<, 2] - end - - def test_assert_send_bad - util_assert_triggered "Expected 1.>(*[2]) to return true." do - @tc.assert_send [1, :>, 2] - end - end - - def test_assert_silent - @assertion_count = 2 - - @tc.assert_silent do - # do nothing - end - end - - def test_assert_silent_triggered_err - @assertion_count = 2 - - util_assert_triggered "In stderr.\nExpected \"\", not \"blah blah\"." do - @tc.assert_silent do - $stderr.print "blah blah" - end - end - end - - def test_assert_silent_triggered_out - util_assert_triggered "In stdout.\nExpected \"\", not \"blah blah\"." do - @tc.assert_silent do - print "blah blah" - end - end - end - - def test_assert_throws - @tc.assert_throws(:blah) do - throw :blah - end - end - - def test_assert_throws_different - util_assert_triggered 'Expected :blah to have been thrown, not :not_blah.' do - @tc.assert_throws(:blah) do - throw :not_blah - end - end - end - - def test_assert_throws_unthrown - util_assert_triggered 'Expected :blah to have been thrown.' do - @tc.assert_throws(:blah) do - # do nothing - end - end - end - - def test_capture_io - @assertion_count = 0 - - orig_verbose = $VERBOSE - $VERBOSE = false - out, err = capture_io do - puts 'hi' - warn 'bye!' - end - - assert_equal "hi\n", out - assert_equal "bye!\n", err - ensure - $VERBOSE = orig_verbose - end - - def test_class_asserts_match_refutes - @assertion_count = 0 - - methods = MiniTest::Assertions.public_instance_methods - methods.map! { |m| m.to_s } if Symbol === methods.first - - ignores = %w(assert_block assert_no_match assert_not_equal - assert_not_nil assert_not_same assert_nothing_raised - assert_nothing_thrown assert_output assert_raise - assert_raises assert_send assert_silent assert_throws) - - asserts = methods.grep(/^assert/).sort - ignores - refutes = methods.grep(/^refute/).sort - ignores - - assert_empty refutes.map { |n| n.sub(/^refute/, 'assert') } - asserts - assert_empty asserts.map { |n| n.sub(/^assert/, 'refute') } - refutes - end - - def test_class_inherited - @assertion_count = 0 - - Object.const_set(:ATestCase, Class.new(MiniTest::Unit::TestCase)) - - assert_equal [ATestCase], MiniTest::Unit::TestCase.test_suites - end - - def test_class_test_suites - @assertion_count = 0 - - Object.const_set(:ATestCase, Class.new(MiniTest::Unit::TestCase)) - - assert_equal 1, MiniTest::Unit::TestCase.test_suites.size - assert_equal [ATestCase], MiniTest::Unit::TestCase.test_suites - end - - def test_flunk - util_assert_triggered 'Epic Fail!' do - @tc.flunk - end - end - - def test_flunk_message - util_assert_triggered @zomg do - @tc.flunk @zomg - end - end - - def test_message - @assertion_count = 0 - - assert_equal "blah2.", @tc.message { "blah2" }.call - assert_equal "blah2.", @tc.message("") { "blah2" }.call - assert_equal "blah1.\nblah2.", @tc.message("blah1") { "blah2" }.call - end - - def test_pass - @tc.pass - end - - def test_refute - @assertion_count = 2 - - @tc.assert_equal false, @tc.refute(false), "returns false on success" - end - - def test_refute_empty - @assertion_count = 2 - - @tc.refute_empty [1] - end - - def test_refute_empty_triggered - @assertion_count = 2 - - util_assert_triggered "Expected [] to not be empty." do - @tc.refute_empty [] - end - end - - def test_refute_equal - @tc.refute_equal "blah", "yay" - end - - def test_refute_equal_triggered - util_assert_triggered 'Expected "blah" to not be equal to "blah".' do - @tc.refute_equal "blah", "blah" - end - end - - def test_refute_in_delta - @tc.refute_in_delta 0.0, 1.0 / 1000, 0.000001 - end - - def test_refute_in_delta_triggered - util_assert_triggered 'Expected 0.0 - 0.001 (0.001) to not be < 0.1.' 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 - 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 - fail - end - end - - def test_refute_includes - @assertion_count = 2 - - @tc.refute_includes [true], false - end - - def test_refute_includes_triggered - @assertion_count = 3 - - e = @tc.assert_raises MiniTest::Assertion do - @tc.refute_includes [true], true - end - - expected = "Expected [true] to not include true." - assert_equal expected, e.message - end - - def test_refute_instance_of - @tc.refute_instance_of Array, "blah" - end - - def test_refute_instance_of_triggered - util_assert_triggered 'Expected "blah" to not be an instance of String.' do - @tc.refute_instance_of String, "blah" - end - end - - def test_refute_kind_of - @tc.refute_kind_of Array, "blah" - end - - def test_refute_kind_of_triggered - util_assert_triggered 'Expected "blah" to not be a kind of String.' do - @tc.refute_kind_of String, "blah" - end - end - - def test_refute_match - @assertion_count = 2 - @tc.refute_match(/\d+/, "blah blah blah") - end - - def test_refute_match_object - @assertion_count = 2 - @tc.refute_match Object.new, 5 # default #=~ returns false - end - - def test_refute_match_object_triggered - @assertion_count = 2 - - pattern = Object.new - def pattern.=~(other) true end - def pattern.inspect; "<>" end - - util_assert_triggered 'Expected <> to not match 5.' do - @tc.refute_match pattern, 5 - end - end - - def test_refute_match_triggered - @assertion_count = 2 - util_assert_triggered 'Expected /\w+/ to not match "blah blah blah".' do - @tc.refute_match(/\w+/, "blah blah blah") - end - end - - def test_refute_nil - @tc.refute_nil 42 - end - - def test_refute_nil_triggered - util_assert_triggered 'Expected nil to not be nil.' do - @tc.refute_nil nil - end - end - - def test_refute_operator - @tc.refute_operator 2, :<, 1 - end - - def test_refute_operator_triggered - util_assert_triggered "Expected 2 to not be > 1." do - @tc.refute_operator 2, :>, 1 - end - end - - def test_refute_respond_to - @tc.refute_respond_to "blah", :rawr! - end - - def test_refute_respond_to_triggered - util_assert_triggered 'Expected "blah" to not respond to empty?.' do - @tc.refute_respond_to "blah", :empty? - end - end - - def test_refute_same - @tc.refute_same 1, 2 - end - - def test_refute_same_triggered - util_assert_triggered 'Expected 1 (oid=N) to not be the same as 1 (oid=N).' do - @tc.refute_same 1, 1 - end - end - - def test_skip - @assertion_count = 0 - - util_assert_triggered "haha!", MiniTest::Skip do - @tc.skip "haha!" - end - end - - def test_test_methods_random - @assertion_count = 0 - - sample_test_case = Class.new(MiniTest::Unit::TestCase) do - def test_test1; assert "does not matter" end - def test_test2; assert "does not matter" end - def test_test3; assert "does not matter" end - end - - srand 42 - expected = %w(test_test2 test_test1 test_test3) - assert_equal expected, sample_test_case.test_methods - end - - def test_test_methods_sorted - @assertion_count = 0 - - sample_test_case = Class.new(MiniTest::Unit::TestCase) do - def self.test_order; :sorted end - def test_test3; assert "does not matter" end - def test_test2; assert "does not matter" end - def test_test1; assert "does not matter" end - end - - expected = %w(test_test1 test_test2 test_test3) - assert_equal expected, sample_test_case.test_methods - end - - def util_assert_triggered expected, klass = MiniTest::Assertion - 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 -end diff --git a/test/minitest/test_minitest_benchmark.rb b/test/minitest/test_minitest_benchmark.rb new file mode 100644 index 0000000000..089d0b3ce0 --- /dev/null +++ b/test/minitest/test_minitest_benchmark.rb @@ -0,0 +1,104 @@ +############################################################ +# This file is imported from a different project. +# DO NOT make modifications in this repo. +# File a patch instead and assign it to Ryan Davis +############################################################ + +require 'minitest/autorun' +require 'minitest/benchmark' + +## +# Used to verify data: +# http://www.wolframalpha.com/examples/RegressionAnalysis.html + +class TestMiniTestBenchmark < MiniTest::Unit::TestCase + def test_cls_bench_exp + assert_equal [2, 4, 8, 16, 32], self.class.bench_exp(2, 32, 2) + end + + def test_cls_bench_linear + assert_equal [2, 4, 6, 8, 10], self.class.bench_linear(2, 10, 2) + end + + def test_cls_benchmark_methods + assert_equal [], self.class.benchmark_methods + + c = Class.new(MiniTest::Unit::TestCase) do + def bench_blah + end + end + + assert_equal ["bench_blah"], c.benchmark_methods + end + + def test_cls_bench_range + assert_equal [1, 10, 100, 1_000, 10_000], self.class.bench_range + end + + def test_fit_exponential_clean + x = [1.0, 2.0, 3.0, 4.0, 5.0] + y = x.map { |n| 1.1 * Math.exp(2.1 * n) } + + assert_fit :exponential, x, y, 1.0, 1.1, 2.1 + end + + def test_fit_exponential_noisy + x = [1.0, 1.9, 2.6, 3.4, 5.0] + y = [12, 10, 8.2, 6.9, 5.9] + + # verified with Numbers and R + assert_fit :exponential, x, y, 0.95, 13.81148, -0.1820 + end + + def test_fit_linear_clean + # y = m * x + b where m = 2.2, b = 3.1 + x = (1..5).to_a + y = x.map { |n| 2.2 * n + 3.1 } + + assert_fit :linear, x, y, 1.0, 3.1, 2.2 + end + + def test_fit_linear_noisy + x = [ 60, 61, 62, 63, 65] + y = [3.1, 3.6, 3.8, 4.0, 4.1] + + # verified in numbers and R + assert_fit :linear, x, y, 0.8315, -7.9635, 0.1878 + end + + def test_fit_power_clean + # y = A x ** B, where B = b and A = e ** a + # if, A = 1, B = 2, then + + x = [1.0, 2.0, 3.0, 4.0, 5.0] + y = [1.0, 4.0, 9.0, 16.0, 25.0] + + assert_fit :power, x, y, 1.0, 1.0, 2.0 + end + + def test_fit_power_noisy + # from www.engr.uidaho.edu/thompson/courses/ME330/lecture/least_squares.html + x = [10, 12, 15, 17, 20, 22, 25, 27, 30, 32, 35] + y = [95, 105, 125, 141, 173, 200, 253, 298, 385, 459, 602] + + # verified in numbers + assert_fit :power, x, y, 0.90, 2.6217, 1.4556 + + # income to % of households below income amount + # http://library.wolfram.com/infocenter/Conferences/6461/PowerLaws.nb + x = [15000, 25000, 35000, 50000, 75000, 100000] + y = [0.154, 0.283, 0.402, 0.55, 0.733, 0.843] + + # verified in numbers + assert_fit :power, x, y, 0.96, 3.119e-5, 0.8959 + end + + def assert_fit msg, x, y, fit, exp_a, exp_b + a, b, rr = send "fit_#{msg}", x, y + + assert_operator rr, :>=, fit + assert_in_delta exp_a, a + assert_in_delta exp_b, b + end +end + diff --git a/test/minitest/test_minitest_mock.rb b/test/minitest/test_minitest_mock.rb new file mode 100644 index 0000000000..bb4279c7d1 --- /dev/null +++ b/test/minitest/test_minitest_mock.rb @@ -0,0 +1,112 @@ +############################################################ +# This file is imported from a different project. +# DO NOT make modifications in this repo. +# File a patch instead and assign it to Ryan Davis +############################################################ + +require 'minitest/mock' +require 'minitest/unit' + +MiniTest::Unit.autorun + +class TestMiniTestMock < MiniTest::Unit::TestCase + def setup + @mock = MiniTest::Mock.new.expect(:foo, nil) + @mock.expect(:meaning_of_life, 42) + end + + def test_create_stub_method + assert_nil @mock.foo + end + + def test_allow_return_value_specification + assert_equal 42, @mock.meaning_of_life + end + + def test_blow_up_if_not_called + @mock.foo + + util_verify_bad + end + + def test_not_blow_up_if_everything_called + @mock.foo + @mock.meaning_of_life + + assert @mock.verify + end + + def test_allow_expectations_to_be_added_after_creation + @mock.expect(:bar, true) + assert @mock.bar + end + + def test_not_verify_if_new_expected_method_is_not_called + @mock.foo + @mock.meaning_of_life + @mock.expect(:bar, true) + + 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 + @mock.sum + end + end + + def test_blow_up_on_wrong_arguments + @mock.foo + @mock.meaning_of_life + @mock.expect(:sum, 3, [1, 2]) + + @mock.sum(2, 4) + + util_verify_bad + end + + def test_respond_appropriately + assert @mock.respond_to?(:foo) + assert !@mock.respond_to?(:bar) + end + + def test_no_method_error_on_unexpected_methods + assert_raises NoMethodError do + @mock.bar + end + 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 + + def test_do_not_create_stub_method_on_new_mocks + a = MiniTest::Mock.new + a.expect(:foo, :a) + + assert !MiniTest::Mock.new.respond_to?(:foo) + end + + def util_verify_bad + assert_raises MockExpectationError do + @mock.verify + end + end +end diff --git a/test/minitest/test_minitest_spec.rb b/test/minitest/test_minitest_spec.rb new file mode 100644 index 0000000000..733ce0f5c7 --- /dev/null +++ b/test/minitest/test_minitest_spec.rb @@ -0,0 +1,235 @@ +############################################################ +# This file is imported from a different project. +# DO NOT make modifications in this repo. +# File a patch instead and assign it to Ryan Davis +############################################################ + +require 'minitest/spec' + +MiniTest::Unit.autorun + +describe MiniTest::Spec do + before do + @assertion_count = 4 + end + + after do + self._assertions.must_equal @assertion_count + end + + # TODO: figure out how the hell to write a test for this + # it "will skip if there is no block" + + it "needs to have all methods named well" do + @assertion_count = 2 + + methods = Object.public_instance_methods.find_all { |n| n =~ /^must|^wont/ } + methods.map! { |m| m.to_s } if Symbol === methods.first + + musts, wonts = methods.sort.partition { |m| m =~ /^must/ } + + expected_musts = %w(must_be + must_be_close_to + must_be_empty + must_be_instance_of + must_be_kind_of + must_be_nil + must_be_same_as + must_be_silent + must_be_within_delta + must_be_within_epsilon + must_equal + must_include + must_match + must_output + must_raise + must_respond_to + must_send + must_throw) + + bad = %w[not raise throw send output be_silent] + + expected_wonts = expected_musts.map { |m| m.sub(/^must/, 'wont') } + expected_wonts.reject! { |m| m =~ /wont_#{Regexp.union(*bad)}/ } + + musts.must_equal expected_musts + wonts.must_equal expected_wonts + end + + it "needs to verify equality" do + (6 * 7).must_equal(42).must_equal true + proc { (6 * 9).must_equal(42) }.must_raise MiniTest::Assertion + end + + it "needs to verify floats within a delta" do + (6.0 * 7).must_be_close_to(42.0).must_equal true + proc { 42.002.must_be_close_to 42.0 }.must_raise MiniTest::Assertion + end + + it "needs to verify types of objects" do + (6 * 7).must_be_instance_of(Fixnum).must_equal true + proc { (6 * 7).must_be_instance_of String }.must_raise MiniTest::Assertion + end + + it "needs to verify kinds of objects" do + @assertion_count = 6 + + (6 * 7).must_be_kind_of(Fixnum).must_equal true + (6 * 7).must_be_kind_of(Numeric).must_equal true + proc { (6 * 7).must_be_kind_of String }.must_raise MiniTest::Assertion + end + + it "needs to verify regexp matches" do + @assertion_count = 6 + + "blah".must_match(/\w+/).must_equal true + proc { "blah".must_match(/\d+/) }.must_raise MiniTest::Assertion + end + + it "needs to verify nil" do + nil.must_be_nil.must_equal true + proc { 42.must_be_nil }.must_raise MiniTest::Assertion + end + + it "needs to verify using any operator" do + 41.must_be(:<, 42).must_equal true + proc { 42.must_be(:<, 41) }.must_raise MiniTest::Assertion + end + + it "needs to catch an expected exception" do + @assertion_count = 2 + + proc { raise "blah" }.must_raise RuntimeError + proc { raise MiniTest::Assertion }.must_raise MiniTest::Assertion + end + + it "needs to catch an unexpected exception" do + @assertion_count = 2 + + proc { + proc { raise MiniTest::Assertion }.must_raise(RuntimeError) + }.must_raise MiniTest::Assertion + end + + it "needs raise if an expected exception is not raised" do + @assertion_count = 2 + + proc { proc { 42 }.must_raise(RuntimeError) }.must_raise MiniTest::Assertion + end + + it "needs to be able to catch a MiniTest::Assertion exception" do + @assertion_count = 2 + + proc { 1.wont_equal 1 }.must_raise MiniTest::Assertion + end + + it "needs to verify using respond_to" do + 42.must_respond_to(:+).must_equal true + proc { 42.must_respond_to(:clear) }.must_raise MiniTest::Assertion + end + + it "needs to verify identity" do + 1.must_be_same_as(1).must_equal true + proc { 1.must_be_same_as 2 }.must_raise MiniTest::Assertion + end + + it "needs to verify throw" do + @assertion_count = 6 + + proc { throw :blah }.must_throw(:blah).must_equal true + proc { proc { }.must_throw(:blah) }.must_raise MiniTest::Assertion + proc { proc { throw :xxx }.must_throw(:blah) }.must_raise MiniTest::Assertion + end + + it "needs to verify inequality" do + 42.wont_equal(6 * 9).must_equal false + proc { 1.wont_equal 1 }.must_raise MiniTest::Assertion + end + + it "needs to verify mismatch" do + @assertion_count = 6 + "blah".wont_match(/\d+/).must_equal false + proc { "blah".wont_match(/\w+/) }.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 + end + + it "needs to verify non-identity" do + 1.wont_be_same_as(2).must_equal false + proc { 1.wont_be_same_as 1 }.must_raise MiniTest::Assertion + end + + it "needs to verify output in stdout" do + proc { print "blah" }.must_output("blah").must_equal true + + proc { + proc { print "xxx" }.must_output("blah") + }.must_raise MiniTest::Assertion + end + + it "needs to verify output in stderr" do + proc { $stderr.print "blah" }.must_output(nil, "blah").must_equal true + + proc { + proc { $stderr.print "xxx" }.must_output(nil, "blah") + }.must_raise MiniTest::Assertion + end + + it "needs to ensure silence" do + @assertion_count = 5 + + proc { }.must_be_silent.must_equal true + + proc { + proc { print "xxx" }.must_be_silent + }.must_raise MiniTest::Assertion + end + + it "needs to be sensible about must_include order" do + @assertion_count = 6 + [1, 2, 3].must_include(2).must_equal true + proc { [1, 2, 3].must_include 5 }.must_raise MiniTest::Assertion + end + + it "needs to be sensible about wont_include order" do + @assertion_count = 6 + [1, 2, 3].wont_include(5).must_equal false + proc { [1, 2, 3].wont_include 2 }.must_raise MiniTest::Assertion + end +end + +class TestMeta < MiniTest::Unit::TestCase + def test_structure + x = y = z = nil + x = describe "top-level thingy" do + before {} + after {} + + it "top-level-it" do end + + y = describe "inner thingy" do + before {} + it "inner-it" do end + + z = describe "very inner thingy" do + before {} + it "inner-it" do end + end + end + end + + assert_equal "top-level thingy", x.to_s + assert_equal "top-level thingy::inner thingy", y.to_s + assert_equal "top-level thingy::inner thingy::very inner thingy", z.to_s + + top_methods = %w(setup teardown test_0001_top_level_it) + inner_methods = %w(setup test_0001_inner_it) + + 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 } + end +end diff --git a/test/minitest/test_minitest_unit.rb b/test/minitest/test_minitest_unit.rb new file mode 100644 index 0000000000..a8187f2275 --- /dev/null +++ b/test/minitest/test_minitest_unit.rb @@ -0,0 +1,1104 @@ +############################################################ +# This file is imported from a different project. +# DO NOT make modifications in this repo. +# File a patch instead and assign it to Ryan Davis +############################################################ + +require 'stringio' +require 'pathname' +require 'minitest/unit' + +MiniTest::Unit.autorun + +module MyModule; end +class AnError < StandardError; include MyModule; end + +class TestMiniTestUnit < MiniTest::Unit::TestCase + pwd = Pathname.new(File.expand_path(Dir.pwd)) + basedir = Pathname.new(File.expand_path(MiniTest::MINI_DIR)) + 'mini' + basedir = basedir.relative_path_from(pwd).to_s + MINITEST_BASE_DIR = basedir[/\A\./] ? basedir : "./#{basedir}" + BT_MIDDLE = ["#{MINITEST_BASE_DIR}/test.rb:161:in `each'", + "#{MINITEST_BASE_DIR}/test.rb:158:in `each'", + "#{MINITEST_BASE_DIR}/test.rb:139:in `run'", + "#{MINITEST_BASE_DIR}/test.rb:106:in `run'"] + + def assert_report expected = nil + expected ||= "Run options: --seed 42 + +# Running tests: + +. + +Finished tests in 0.00 + +1 tests, 1 assertions, 0 failures, 0 errors, 0 skips +" + output = @output.string.sub(/Finished tests in .*/, "Finished tests in 0.00") + output.sub!(/Loaded suite .*/, 'Loaded suite blah') + output.sub!(/^(\s+)(?:#{Regexp.union(__FILE__, File.expand_path(__FILE__))}):\d+:/o, '\1FILE:LINE:') + output.sub!(/\[(?:#{Regexp.union(__FILE__, File.expand_path(__FILE__))}):\d+\]/o, '[FILE:LINE]') + assert_equal(expected, output) + end + + def setup + srand 42 + MiniTest::Unit::TestCase.reset + @tu = MiniTest::Unit.new + @output = StringIO.new("") + MiniTest::Unit.output = @output + end + + def teardown + MiniTest::Unit.output = $stdout + Object.send :remove_const, :ATestCase if defined? ATestCase + 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) + end + + def test_class_puke_with_assertion_failed_and_long_backtrace + bt = (["test/test_some_class.rb:615:in `method_name'", + "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raises'", + "test/test_some_class.rb:615:in `each'", + "test/test_some_class.rb:614:in `test_method_name'", + "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + + BT_MIDDLE + + ["#{MINITEST_BASE_DIR}/test.rb:29"]) + bt = util_expand_bt bt + + ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first + + exception = MiniTest::Assertion.new "Oh no!" + exception.set_backtrace bt + 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) + end + + def test_class_puke_with_assertion_failed_and_user_defined_assertions + bt = (["lib/test/my/util.rb:16:in `another_method_name'", + "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raises'", + "lib/test/my/util.rb:15:in `block in assert_something'", + "lib/test/my/util.rb:14:in `each'", + "lib/test/my/util.rb:14:in `assert_something'", + "test/test_some_class.rb:615:in `each'", + "test/test_some_class.rb:614:in `test_method_name'", + "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + + BT_MIDDLE + + ["#{MINITEST_BASE_DIR}/test.rb:29"]) + bt = util_expand_bt bt + + ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first + + exception = MiniTest::Assertion.new "Oh no!" + exception.set_backtrace bt + 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) + end + + def test_class_puke_with_failure_and_flunk_in_backtrace + exception = begin + MiniTest::Unit::TestCase.new('fake tc').flunk + rescue MiniTest::Assertion => failure + failure + end + assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception) + refute @tu.report.any?{|line| line =~ /in .flunk/} + end + + def test_class_puke_with_flunk_and_user_defined_assertions + bt = (["lib/test/my/util.rb:16:in `flunk'", + "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raises'", + "lib/test/my/util.rb:15:in `block in assert_something'", + "lib/test/my/util.rb:14:in `each'", + "lib/test/my/util.rb:14:in `assert_something'", + "test/test_some_class.rb:615:in `each'", + "test/test_some_class.rb:614:in `test_method_name'", + "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + + BT_MIDDLE + + ["#{MINITEST_BASE_DIR}/test.rb:29"]) + bt = util_expand_bt bt + + ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first + + exception = MiniTest::Assertion.new "Oh no!" + exception.set_backtrace bt + 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) + end + + def test_class_puke_with_non_failure_exception + exception = Exception.new("Oh no again!") + assert_equal 'E', @tu.puke('SomeClass', 'method_name', exception) + assert_equal 1, @tu.errors + assert_match(/^Exception.*Oh no again!/m, @tu.report.first) + end + + def test_filter_backtrace + # this is a semi-lame mix of relative paths. + # I cheated by making the autotest parts not have ./ + bt = (["lib/autotest.rb:571:in `add_exception'", + "test/test_autotest.rb:62:in `test_add_exception'", + "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + + BT_MIDDLE + + ["#{MINITEST_BASE_DIR}/test.rb:29", + "test/test_autotest.rb:422"]) + bt = util_expand_bt bt + + ex = ["lib/autotest.rb:571:in `add_exception'", + "test/test_autotest.rb:62:in `test_add_exception'"] + ex = util_expand_bt ex + + fu = MiniTest::filter_backtrace(bt) + + assert_equal ex, fu + end + + def test_filter_backtrace_all_unit + bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + + BT_MIDDLE + + ["#{MINITEST_BASE_DIR}/test.rb:29"]) + ex = bt.clone + fu = MiniTest::filter_backtrace(bt) + assert_equal ex, fu + end + + def test_filter_backtrace_unit_starts + bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + + BT_MIDDLE + + ["#{MINITEST_BASE_DIR}/mini/test.rb:29", + "-e:1"]) + + bt = util_expand_bt bt + + ex = ["-e:1"] + fu = MiniTest::filter_backtrace(bt) + assert_equal ex, fu + end + + def test_run_error + tc = Class.new(MiniTest::Unit::TestCase) do + def test_something + assert true + end + + def test_error + raise "unhandled exception" + end + end + + Object.const_set(:ATestCase, tc) + + @tu.run %w[--seed 42] + + expected = "Run options: --seed 42 + +# Running tests: + +E. + +Finished tests in 0.00 + + 1) Error: +test_error(ATestCase): +RuntimeError: unhandled exception + FILE:LINE:in `test_error' + +2 tests, 1 assertions, 0 failures, 1 errors, 0 skips +" + assert_report expected + end + + def test_run_error_teardown + tc = Class.new(MiniTest::Unit::TestCase) do + def test_something + assert true + end + + def teardown + raise "unhandled exception" + end + end + + Object.const_set(:ATestCase, tc) + + @tu.run %w[--seed 42] + + expected = "Run options: --seed 42 + +# Running tests: + +E + +Finished tests in 0.00 + + 1) Error: +test_something(ATestCase): +RuntimeError: unhandled exception + FILE:LINE:in `teardown' + +1 tests, 1 assertions, 0 failures, 1 errors, 0 skips +" + assert_report expected + end + + def test_run_failing # TODO: add error test + tc = Class.new(MiniTest::Unit::TestCase) do + def test_something + assert true + end + + def test_failure + assert false + end + end + + Object.const_set(:ATestCase, tc) + + @tu.run %w[--seed 42] + + expected = "Run options: --seed 42 + +# Running tests: + +F. + +Finished tests in 0.00 + + 1) Failure: +test_failure(ATestCase) [FILE:LINE]: +Failed assertion, no message given. + +2 tests, 2 assertions, 1 failures, 0 errors, 0 skips +" + assert_report expected + end + + def test_run_failing_filtered + tc = Class.new(MiniTest::Unit::TestCase) do + def test_something + assert true + end + + def test_failure + assert false + end + end + + Object.const_set(:ATestCase, tc) + + @tu.run %w[--name /some|thing/ --seed 42] + + expected = "Run options: --name \"/some|thing/\" --seed 42 + +# Running tests: + +. + +Finished tests in 0.00 + +1 tests, 1 assertions, 0 failures, 0 errors, 0 skips +" + assert_report expected + end + + def test_run_passing + tc = Class.new(MiniTest::Unit::TestCase) do + def test_something + assert true + end + end + + Object.const_set(:ATestCase, tc) + + @tu.run %w[--seed 42] + + assert_report + end + + def test_run_skip + 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] + + expected = "Run options: --seed 42 + +# Running tests: + +S. + +Finished tests in 0.00 + + 1) Skipped: +test_skip(ATestCase) [FILE:LINE]: +not yet + +2 tests, 1 assertions, 0 failures, 0 errors, 1 skips +" + assert_report expected + end + + def util_expand_bt bt + if RUBY_VERSION =~ /^1\.9/ then + bt.map { |f| (f =~ /^\./) ? File.expand_path(f) : f } + else + bt + end + end +end + +class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase + def setup + MiniTest::Unit::TestCase.reset + + @tc = MiniTest::Unit::TestCase.new 'fake tc' + @zomg = "zomg ponies!" + @assertion_count = 1 + end + + def teardown + assert_equal(@assertion_count, @tc._assertions, + "expected #{@assertion_count} assertions to be fired during the test, not #{@tc._assertions}") if @tc._assertions + Object.send :remove_const, :ATestCase if defined? ATestCase + end + + def test_assert + @assertion_count = 2 + + @tc.assert_equal true, @tc.assert(true), "returns true on success" + end + + def test_assert__triggered + util_assert_triggered "Failed assertion, no message given." do + @tc.assert false + end + end + + def test_assert__triggered_message + util_assert_triggered @zomg do + @tc.assert false, @zomg + end + end + + def test_assert_block + @tc.assert_block do + true + end + end + + def test_assert_block_triggered + util_assert_triggered 'Expected block to return true value.' do + @tc.assert_block do + false + end + end + end + + def test_assert_empty + @assertion_count = 2 + + @tc.assert_empty [] + end + + def test_assert_empty_triggered + @assertion_count = 2 + + util_assert_triggered "Expected [1] to be empty." do + @tc.assert_empty [1] + end + end + + def test_assert_equal + @tc.assert_equal 1, 1 + end + + def test_assert_equal_different + util_assert_triggered "Expected 1, not 2." do + @tc.assert_equal 1, 2 + end + end + + def test_assert_in_delta + @tc.assert_in_delta 0.0, 1.0 / 1000, 0.1 + end + + def test_assert_in_delta_triggered + util_assert_triggered 'Expected 0.0 - 0.001 (0.001) to be < 1.0e-06.' do + @tc.assert_in_delta 0.0, 1.0 / 1000, 0.000001 + end + end + + def test_assert_in_epsilon + @assertion_count = 8 + + @tc.assert_in_epsilon 10000, 9991 + @tc.assert_in_epsilon 9991, 10000 + @tc.assert_in_epsilon 1.0, 1.001 + @tc.assert_in_epsilon 1.001, 1.0 + + @tc.assert_in_epsilon 10000, 9999.1, 0.0001 + @tc.assert_in_epsilon 9999.1, 10000, 0.0001 + @tc.assert_in_epsilon 1.0, 1.0001, 0.0001 + @tc.assert_in_epsilon 1.0001, 1.0, 0.0001 + end + + def test_assert_in_epsilon_triggered + util_assert_triggered 'Expected 10000 - 9990 (10) to be < 9.99.' do + @tc.assert_in_epsilon 10000, 9990 + end + end + + def test_assert_includes + @assertion_count = 2 + + @tc.assert_includes [true], true + end + + def test_assert_includes_triggered + @assertion_count = 3 + + e = @tc.assert_raises MiniTest::Assertion do + @tc.assert_includes [true], false + end + + expected = "Expected [true] to include false." + assert_equal expected, e.message + end + + def test_assert_instance_of + @tc.assert_instance_of String, "blah" + end + + def test_assert_instance_of_triggered + util_assert_triggered 'Expected "blah" to be an instance of Array, not String.' do + @tc.assert_instance_of Array, "blah" + end + end + + def test_assert_kind_of + @tc.assert_kind_of String, "blah" + end + + def test_assert_kind_of_triggered + util_assert_triggered 'Expected "blah" to be a kind of Array, not String.' do + @tc.assert_kind_of Array, "blah" + end + end + + def test_assert_match + @assertion_count = 2 + @tc.assert_match(/\w+/, "blah blah blah") + end + + def test_assert_match_object + @assertion_count = 2 + + pattern = Object.new + def pattern.=~(other) true end + + @tc.assert_match pattern, 5 + end + + def test_assert_match_object_triggered + @assertion_count = 2 + + pattern = Object.new + def pattern.=~(other) false end + def pattern.inspect; "[Object]" end + + util_assert_triggered 'Expected [Object] to match 5.' do + @tc.assert_match pattern, 5 + end + end + + def test_assert_match_triggered + @assertion_count = 2 + util_assert_triggered 'Expected /\d+/ to match "blah blah blah".' do + @tc.assert_match(/\d+/, "blah blah blah") + end + end + + def test_assert_nil + @tc.assert_nil nil + end + + def test_assert_nil_triggered + util_assert_triggered 'Expected 42 to be nil.' do + @tc.assert_nil 42 + end + end + + def test_assert_operator + @tc.assert_operator 2, :>, 1 + end + + def test_assert_operator_triggered + util_assert_triggered "Expected 2 to be < 1." do + @tc.assert_operator 2, :<, 1 + end + end + + def test_assert_output_both + @assertion_count = 2 + + @tc.assert_output "yay", "blah" do + print "yay" + $stderr.print "blah" + end + end + + def test_assert_output_err + @tc.assert_output nil, "blah" do + $stderr.print "blah" + end + end + + def test_assert_output_neither + @assertion_count = 0 + + @tc.assert_output do + # do nothing + end + end + + def test_assert_output_out + @tc.assert_output "blah" do + print "blah" + end + end + + def test_assert_output_triggered_both + util_assert_triggered "In stdout.\nExpected \"yay\", not \"boo\"." do + @tc.assert_output "yay", "blah" do + print "boo" + $stderr.print "blah blah" + end + end + end + + def test_assert_output_triggered_err + util_assert_triggered "In stderr.\nExpected \"blah\", not \"blah blah\"." do + @tc.assert_output nil, "blah" do + $stderr.print "blah blah" + end + end + end + + def test_assert_output_triggered_out + util_assert_triggered "In stdout.\nExpected \"blah\", not \"blah blah\"." do + @tc.assert_output "blah" do + print "blah blah" + end + end + end + + def test_assert_raises + @tc.assert_raises RuntimeError do + raise "blah" + end + end + + ## + # *sigh* This is quite an odd scenario, but it is from real (albeit + # ugly) test code in ruby-core: + # + # http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=29259 + + def test_assert_raises_skip + @assertion_count = 0 + + util_assert_triggered "skipped", MiniTest::Skip do + @tc.assert_raises ArgumentError do + begin + raise "blah" + rescue + skip "skipped" + end + end + end + end + + def test_assert_raises_module + @tc.assert_raises MyModule do + raise AnError + end + end + + def test_assert_raises_triggered_different + e = assert_raises MiniTest::Assertion do + @tc.assert_raises RuntimeError do + raise SyntaxError, "icky" + end + end + + expected = "[RuntimeError] exception expected, not +Class: +Message: <\"icky\"> +---Backtrace--- +FILE:LINE:in `test_assert_raises_triggered_different' +---------------" + + actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE') + actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION =~ /^1\.9/ + + assert_equal expected, actual + end + + def test_assert_raises_triggered_different_msg + e = assert_raises MiniTest::Assertion do + @tc.assert_raises RuntimeError, "XXX" do + raise SyntaxError, "icky" + end + end + + expected = "XXX +[RuntimeError] exception expected, not +Class: +Message: <\"icky\"> +---Backtrace--- +FILE:LINE:in `test_assert_raises_triggered_different_msg' +---------------" + + actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE') + actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION =~ /^1\.9/ + + assert_equal expected, actual + end + + def test_assert_raises_triggered_none + e = assert_raises MiniTest::Assertion do + @tc.assert_raises MiniTest::Assertion do + # do nothing + end + end + + expected = "MiniTest::Assertion expected but nothing was raised." + + assert_equal expected, e.message + end + + def test_assert_raises_triggered_none_msg + e = assert_raises MiniTest::Assertion do + @tc.assert_raises MiniTest::Assertion, "XXX" do + # do nothing + end + end + + expected = "XXX\nMiniTest::Assertion expected but nothing was raised." + + assert_equal expected, e.message + end + + def test_assert_raises_triggered_subclass + e = assert_raises MiniTest::Assertion do + @tc.assert_raises StandardError do + raise AnError + end + end + + expected = "[StandardError] exception expected, not +Class: +Message: <\"AnError\"> +---Backtrace--- +FILE:LINE:in `test_assert_raises_triggered_subclass' +---------------" + + actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE') + actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION =~ /^1\.9/ + + assert_equal expected, actual + end + + def test_assert_respond_to + @tc.assert_respond_to "blah", :empty? + end + + def test_assert_respond_to_triggered + util_assert_triggered 'Expected "blah" (String) to respond to #rawr!.' do + @tc.assert_respond_to "blah", :rawr! + end + end + + def test_assert_same + @assertion_count = 3 + + o = "blah" + @tc.assert_same 1, 1 + @tc.assert_same :blah, :blah + @tc.assert_same o, o + end + + def test_assert_same_triggered + @assertion_count = 2 + + util_assert_triggered 'Expected 2 (oid=N) to be the same as 1 (oid=N).' do + @tc.assert_same 1, 2 + end + + s1 = "blah" + s2 = "blah" + + util_assert_triggered 'Expected "blah" (oid=N) to be the same as "blah" (oid=N).' do + @tc.assert_same s1, s2 + end + end + + def test_assert_send + @tc.assert_send [1, :<, 2] + end + + def test_assert_send_bad + util_assert_triggered "Expected 1.>(*[2]) to return true." do + @tc.assert_send [1, :>, 2] + end + end + + def test_assert_silent + @assertion_count = 2 + + @tc.assert_silent do + # do nothing + end + end + + def test_assert_silent_triggered_err + @assertion_count = 2 + + util_assert_triggered "In stderr.\nExpected \"\", not \"blah blah\"." do + @tc.assert_silent do + $stderr.print "blah blah" + end + end + end + + def test_assert_silent_triggered_out + util_assert_triggered "In stdout.\nExpected \"\", not \"blah blah\"." do + @tc.assert_silent do + print "blah blah" + end + end + end + + def test_assert_throws + @tc.assert_throws(:blah) do + throw :blah + end + end + + def test_assert_throws_different + util_assert_triggered 'Expected :blah to have been thrown, not :not_blah.' do + @tc.assert_throws(:blah) do + throw :not_blah + end + end + end + + def test_assert_throws_unthrown + util_assert_triggered 'Expected :blah to have been thrown.' do + @tc.assert_throws(:blah) do + # do nothing + end + end + end + + def test_capture_io + @assertion_count = 0 + + orig_verbose = $VERBOSE + $VERBOSE = false + out, err = capture_io do + puts 'hi' + warn 'bye!' + end + + assert_equal "hi\n", out + assert_equal "bye!\n", err + ensure + $VERBOSE = orig_verbose + end + + def test_class_asserts_match_refutes + @assertion_count = 0 + + methods = MiniTest::Assertions.public_instance_methods + methods.map! { |m| m.to_s } if Symbol === methods.first + + ignores = %w(assert_block assert_no_match assert_not_equal + assert_not_nil assert_not_same assert_nothing_raised + assert_nothing_thrown assert_output assert_raise + assert_raises assert_send assert_silent assert_throws) + + asserts = methods.grep(/^assert/).sort - ignores + refutes = methods.grep(/^refute/).sort - ignores + + assert_empty refutes.map { |n| n.sub(/^refute/, 'assert') } - asserts + assert_empty asserts.map { |n| n.sub(/^assert/, 'refute') } - refutes + end + + def test_class_inherited + @assertion_count = 0 + + Object.const_set(:ATestCase, Class.new(MiniTest::Unit::TestCase)) + + assert_equal [ATestCase], MiniTest::Unit::TestCase.test_suites + end + + def test_class_test_suites + @assertion_count = 0 + + Object.const_set(:ATestCase, Class.new(MiniTest::Unit::TestCase)) + + assert_equal 1, MiniTest::Unit::TestCase.test_suites.size + assert_equal [ATestCase], MiniTest::Unit::TestCase.test_suites + end + + def test_flunk + util_assert_triggered 'Epic Fail!' do + @tc.flunk + end + end + + def test_flunk_message + util_assert_triggered @zomg do + @tc.flunk @zomg + end + end + + def test_message + @assertion_count = 0 + + assert_equal "blah2.", @tc.message { "blah2" }.call + assert_equal "blah2.", @tc.message("") { "blah2" }.call + assert_equal "blah1.\nblah2.", @tc.message("blah1") { "blah2" }.call + end + + def test_pass + @tc.pass + end + + def test_refute + @assertion_count = 2 + + @tc.assert_equal false, @tc.refute(false), "returns false on success" + end + + def test_refute_empty + @assertion_count = 2 + + @tc.refute_empty [1] + end + + def test_refute_empty_triggered + @assertion_count = 2 + + util_assert_triggered "Expected [] to not be empty." do + @tc.refute_empty [] + end + end + + def test_refute_equal + @tc.refute_equal "blah", "yay" + end + + def test_refute_equal_triggered + util_assert_triggered 'Expected "blah" to not be equal to "blah".' do + @tc.refute_equal "blah", "blah" + end + end + + def test_refute_in_delta + @tc.refute_in_delta 0.0, 1.0 / 1000, 0.000001 + end + + def test_refute_in_delta_triggered + util_assert_triggered 'Expected 0.0 - 0.001 (0.001) to not be < 0.1.' 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 + 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 + fail + end + end + + def test_refute_includes + @assertion_count = 2 + + @tc.refute_includes [true], false + end + + def test_refute_includes_triggered + @assertion_count = 3 + + e = @tc.assert_raises MiniTest::Assertion do + @tc.refute_includes [true], true + end + + expected = "Expected [true] to not include true." + assert_equal expected, e.message + end + + def test_refute_instance_of + @tc.refute_instance_of Array, "blah" + end + + def test_refute_instance_of_triggered + util_assert_triggered 'Expected "blah" to not be an instance of String.' do + @tc.refute_instance_of String, "blah" + end + end + + def test_refute_kind_of + @tc.refute_kind_of Array, "blah" + end + + def test_refute_kind_of_triggered + util_assert_triggered 'Expected "blah" to not be a kind of String.' do + @tc.refute_kind_of String, "blah" + end + end + + def test_refute_match + @assertion_count = 2 + @tc.refute_match(/\d+/, "blah blah blah") + end + + def test_refute_match_object + @assertion_count = 2 + @tc.refute_match Object.new, 5 # default #=~ returns false + end + + def test_refute_match_object_triggered + @assertion_count = 2 + + pattern = Object.new + def pattern.=~(other) true end + def pattern.inspect; "[Object]" end + + util_assert_triggered 'Expected [Object] to not match 5.' do + @tc.refute_match pattern, 5 + end + end + + def test_refute_match_triggered + @assertion_count = 2 + util_assert_triggered 'Expected /\w+/ to not match "blah blah blah".' do + @tc.refute_match(/\w+/, "blah blah blah") + end + end + + def test_refute_nil + @tc.refute_nil 42 + end + + def test_refute_nil_triggered + util_assert_triggered 'Expected nil to not be nil.' do + @tc.refute_nil nil + end + end + + def test_refute_operator + @tc.refute_operator 2, :<, 1 + end + + def test_refute_operator_triggered + util_assert_triggered "Expected 2 to not be > 1." do + @tc.refute_operator 2, :>, 1 + end + end + + def test_refute_respond_to + @tc.refute_respond_to "blah", :rawr! + end + + def test_refute_respond_to_triggered + util_assert_triggered 'Expected "blah" to not respond to empty?.' do + @tc.refute_respond_to "blah", :empty? + end + end + + def test_refute_same + @tc.refute_same 1, 2 + end + + def test_refute_same_triggered + util_assert_triggered 'Expected 1 (oid=N) to not be the same as 1 (oid=N).' do + @tc.refute_same 1, 1 + end + end + + def test_skip + @assertion_count = 0 + + util_assert_triggered "haha!", MiniTest::Skip do + @tc.skip "haha!" + end + end + + def test_test_methods_random + @assertion_count = 0 + + sample_test_case = Class.new(MiniTest::Unit::TestCase) do + def test_test1; assert "does not matter" end + def test_test2; assert "does not matter" end + def test_test3; assert "does not matter" end + end + + srand 42 + expected = %w(test_test2 test_test1 test_test3) + assert_equal expected, sample_test_case.test_methods + end + + def test_test_methods_sorted + @assertion_count = 0 + + sample_test_case = Class.new(MiniTest::Unit::TestCase) do + def self.test_order; :sorted end + def test_test3; assert "does not matter" end + def test_test2; assert "does not matter" end + def test_test1; assert "does not matter" end + end + + expected = %w(test_test1 test_test2 test_test3) + assert_equal expected, sample_test_case.test_methods + end + + def util_assert_triggered expected, klass = MiniTest::Assertion + 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 +end -- cgit v1.2.3