Class: MiniTest::Unit

Inherits:
Object show all
Defined in:
lib/minitest/unit.rb,
lib/minitest/benchmark.rb,
lib/minitest/parallel_each.rb

Overview

:nodoc:

Defined Under Namespace

Modules: Guard, LifecycleHooks Classes: TestCase

Constant Summary collapse

VERSION =

:nodoc:

"4.7.5"
@@out =
$stdout
@@after_tests =
[]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeUnit

:nodoc:


1003
1004
1005
1006
1007
1008
1009
# File 'lib/minitest/unit.rb', line 1003

def initialize # :nodoc:
  @report = []
  @errors = @failures = @skips = 0
  @verbose = false
  @mutex = defined?(Mutex) ? Mutex.new : nil
  @info_signal = Signal.list['INFO']
end

Instance Attribute Details

#assertion_countObject

Returns the value of attribute assertion_count


744
745
746
# File 'lib/minitest/unit.rb', line 744

def assertion_count
  @assertion_count
end

#errorsObject

Returns the value of attribute errors


743
744
745
# File 'lib/minitest/unit.rb', line 743

def errors
  @errors
end

#failuresObject

Returns the value of attribute failures


743
744
745
# File 'lib/minitest/unit.rb', line 743

def failures
  @failures
end

#helpObject

Returns the value of attribute help


747
748
749
# File 'lib/minitest/unit.rb', line 747

def help
  @help
end

#info_signalObject

:attr:

if true, installs an “INFO” signal handler (only available to BSD and OS X users) which prints diagnostic information about the test run.

This is auto-detected by default but may be overridden by custom runners.


760
761
762
# File 'lib/minitest/unit.rb', line 760

def info_signal
  @info_signal
end

#optionsObject

Lazy accessor for options.


765
766
767
# File 'lib/minitest/unit.rb', line 765

def options
  @options ||= {}
end

#reportObject

Returns the value of attribute report


743
744
745
# File 'lib/minitest/unit.rb', line 743

def report
  @report
end

#skipsObject

Returns the value of attribute skips


743
744
745
# File 'lib/minitest/unit.rb', line 743

def skips
  @skips
end

#start_timeObject

Returns the value of attribute start_time


746
747
748
# File 'lib/minitest/unit.rb', line 746

def start_time
  @start_time
end

#test_countObject

:nodoc:


863
864
865
# File 'lib/minitest/unit.rb', line 863

def test_count # :nodoc:
  @test_count ||= 0
end

#verboseObject

Returns the value of attribute verbose


748
749
750
# File 'lib/minitest/unit.rb', line 748

def verbose
  @verbose
end

Class Method Details

.after_tests(&block) ⇒ Object

A simple hook allowing you to run a block of code after all of the tests are done. Eg:

MiniTest::Unit.after_tests { p $debugging_info }

779
780
781
# File 'lib/minitest/unit.rb', line 779

def self.after_tests &block
  @@after_tests << block
end

.autorunObject

Registers MiniTest::Unit to run tests at process exit


786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
# File 'lib/minitest/unit.rb', line 786

def self.autorun
  at_exit {
    # don't run if there was a non-exit exception
    next if $! and not $!.kind_of? SystemExit

    # the order here is important. The at_exit handler must be
    # installed before anyone else gets a chance to install their
    # own, that way we can be assured that our exit will be last
    # to run (at_exit stacks).
    exit_code = nil

    at_exit {
      @@after_tests.reverse_each(&:call)
      exit false if exit_code && exit_code != 0
    }

    exit_code = MiniTest::Unit.new.run ARGV
  } unless @@installed_at_exit
  @@installed_at_exit = true
end

.outputObject

Returns the stream to use for output.


810
811
812
# File 'lib/minitest/unit.rb', line 810

def self.output
  @@out
end

.output=(stream) ⇒ Object

Sets MiniTest::Unit to write output to stream. $stdout is the default output


818
819
820
# File 'lib/minitest/unit.rb', line 818

def self.output= stream
  @@out = stream
end

.pluginsObject

Return all plugins' run methods (methods that start with “run_”).


842
843
844
845
846
# File 'lib/minitest/unit.rb', line 842

def self.plugins
  @@plugins ||= (["run_tests"] +
                 public_instance_methods(false).
                 grep(/^run_/).map { |s| s.to_s }).uniq
end

.runnerObject

Returns the MiniTest::Unit subclass instance that will be used to run the tests. A MiniTest::Unit instance is the default runner.


835
836
837
# File 'lib/minitest/unit.rb', line 835

def self.runner
  @@runner ||= self.new
end

.runner=(runner) ⇒ Object

Tells MiniTest::Unit to delegate to runner, an instance of a MiniTest::Unit subclass, when MiniTest::Unit#run is called.


826
827
828
# File 'lib/minitest/unit.rb', line 826

def self.runner= runner
  @@runner = runner
end

Instance Method Details

#_old_run_suitesObject


67
# File 'lib/minitest/parallel_each.rb', line 67

alias _old_run_suites _run_suites

#_run(args = []) ⇒ Object

Top level driver, controls all output and filtering.


1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
# File 'lib/minitest/unit.rb', line 1072

def _run args = []
  args = process_args args # ARGH!! blame test/unit process_args
  self.options.merge! args

  puts "Run options: #{help}"

  self.class.plugins.each do |plugin|
    send plugin
    break unless report.empty?
  end

  return failures + errors if self.test_count > 0 # or return nil...
rescue Interrupt
  abort 'Interrupted'
end

#_run_anything(type) ⇒ Object

Runner for a given type (eg, test vs bench).


870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
# File 'lib/minitest/unit.rb', line 870

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, _)| sum + tc }
  @assertion_count = results.inject(0) { |sum, (_, 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

#_run_suite(suite, type) ⇒ Object

Run a single suite for a given type.


920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
# File 'lib/minitest/unit.rb', line 920

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 =~ /\/(.*)\//

  all_test_methods = suite.send "#{type}_methods"

  filtered_test_methods = all_test_methods.find_all { |m|
    filter === m || filter === "#{suite}##{m}"
  }

  assertions = filtered_test_methods.map { |method|
    inst = suite.new method
    inst._assertions = 0

    print "#{suite}##{method} = " if @verbose

    start_time = Time.now if @verbose
    result = inst.run self

    print "%.2f s = " % (Time.now - start_time) if @verbose
    print result
    puts if @verbose

    inst._assertions
  }

  return assertions.size, assertions.inject(0) { |sum, n| sum + n }
end

#_run_suites(suites, type) ⇒ Object

Runs all the suites for a given type.

NOTE: this method is redefined in parallel_each.rb, which is loaded if a test-suite calls parallelize_me!.


74
75
76
77
78
79
# File 'lib/minitest/parallel_each.rb', line 74

def _run_suites suites, type
  parallel, serial = suites.partition { |s| s.test_order == :parallel }

  ParallelEach.new(parallel).map { |suite| _run_suite suite, type } +
   serial.map { |suite| _run_suite suite, type }
end

#benchmark_suite_header(suite) ⇒ Object

:nodoc:


16
17
18
# File 'lib/minitest/benchmark.rb', line 16

def benchmark_suite_header suite # :nodoc:
  "\n#{suite}\t#{suite.bench_range.join("\t")}"
end

#location(e) ⇒ Object

:nodoc:


972
973
974
975
976
977
978
979
# File 'lib/minitest/unit.rb', line 972

def location e # :nodoc:
  last_before_assertion = ""
  e.backtrace.reverse_each do |s|
    break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
    last_before_assertion = s
  end
  last_before_assertion.sub(/:in .*$/, '')
end

#outputObject

Return the IO for output.


851
852
853
# File 'lib/minitest/unit.rb', line 851

def output
  self.class.output
end

:nodoc:


859
860
861
# File 'lib/minitest/unit.rb', line 859

def print *a # :nodoc:
  output.print(*a)
end

#process_args(args = []) ⇒ Object

:nodoc:


1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
# File 'lib/minitest/unit.rb', line 1019

def process_args args = [] # :nodoc:
  options = {}
  orig_args = args.dup

  OptionParser.new do |opts|
    opts.banner  = 'minitest options:'
    opts.version = MiniTest::Unit::VERSION

    opts.on '-h', '--help', 'Display this help.' do
      puts opts
      exit
    end

    opts.on '-s', '--seed SEED', Integer, "Sets random seed" do |m|
      options[:seed] = m.to_i
    end

    opts.on '-v', '--verbose', "Verbose. Show progress processing files." do
      options[:verbose] = true
    end

    opts.on '-n', '--name PATTERN', "Filter test names on pattern (e.g. /foo/)" do |a|
      options[:filter] = a
    end

    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

#puke(klass, meth, e) ⇒ Object

Writes status for failed test meth in klass which finished with exception e


985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
# File 'lib/minitest/unit.rb', line 985

def puke klass, meth, e
  e = case e
      when MiniTest::Skip then
        @skips += 1
        return "S" unless @verbose
        "Skipped:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n"
      when MiniTest::Assertion then
        @failures += 1
        "Failure:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n"
      else
        @errors += 1
        bt = MiniTest::filter_backtrace(e.backtrace).join "\n    "
        "Error:\n#{klass}##{meth}:\n#{e.class}: #{e.message}\n    #{bt}\n"
      end
  @report << e
  e[0, 1]
end

#puts(*a) ⇒ Object

:nodoc:


855
856
857
# File 'lib/minitest/unit.rb', line 855

def puts *a  # :nodoc:
  output.puts(*a)
end

#record(suite, method, assertions, time, error) ⇒ Object

Record the result of a single test. Makes it very easy to gather information. Eg:

class StatisticsRecorder < MiniTest::Unit
  def record suite, method, assertions, time, error
    # ... record the results somewhere ...
  end
end

MiniTest::Unit.runner = StatisticsRecorder.new

NOTE: record might be sent more than once per test. It will be sent once with the results from the test itself. If there is a failure or error in teardown, it will be sent again with the error or failure.


969
970
# File 'lib/minitest/unit.rb', line 969

def record suite, method, assertions, time, error
end

#run(args = []) ⇒ Object

Begins the full test run. Delegates to runner's #_run method.


1065
1066
1067
# File 'lib/minitest/unit.rb', line 1065

def run args = []
  self.class.runner._run(args)
end

#run_benchmarksObject

:nodoc: :nodoc:


12
13
14
# File 'lib/minitest/benchmark.rb', line 12

def run_benchmarks # :nodoc:
  _run_anything :benchmark
end

#run_testsObject

Runs test suites matching filter.


1091
1092
1093
# File 'lib/minitest/unit.rb', line 1091

def run_tests
  _run_anything :test
end

#status(io = self.output) ⇒ Object

Writes status to io


1098
1099
1100
1101
# File 'lib/minitest/unit.rb', line 1098

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

#synchronizeObject

:nodoc:


1011
1012
1013
1014
1015
1016
1017
# File 'lib/minitest/unit.rb', line 1011

def synchronize # :nodoc:
  if @mutex then
    @mutex.synchronize { yield }
  else
    yield
  end
end