class Minitest::Minitap
Constants
- IGNORE_CALLERS
Backtrace patterns to be omitted.
- REVISION
TAP-Y/J Revision
Attributes
Test results.
attr_reader :test_results
Public Class Methods
Initialize new Minitap
Minitest
reporter.
# File lib/minitap/minitest5.rb, line 39 def initialize(options = {}) io = options.delete(:io) || $stdout super(io, options) # since tapout uses a unix pipe, we don't want any buffering io.sync = true #@_stdout = StringIO.new #@_stderr = StringIO.new #@test_results = {} #self.assertion_count = 0 @_source_cache = {} end
Public Instance Methods
# File lib/minitap/minitest5.rb, line 147 def after_case(test_case) tapout_after_case(test_case) end
# File lib/minitap/minitest5.rb, line 138 def after_suite() #(test_cases) tapout_after_suite() end
# File lib/minitap/minitest5.rb, line 156 def after_test(result) tapout_after_test(result) end
# File lib/minitap/minitest5.rb, line 142 def before_case(test_case) @case_start_time = Time.now tapout_before_case(test_case) end
# File lib/minitap/minitest5.rb, line 132 def before_suite(test_cases) @suite_start_time = Time.now count_tests!(test_cases) tapout_before_suite() end
# File lib/minitap/minitest5.rb, line 151 def before_test(result) @test_start_time = Time.now tapout_before_test(result) end
Stub out the three IO methods used by the built-in reporter.
# File lib/minitap/minitest5.rb, line 231 def p(*args) args.each{ |a| io.print(a.inspect); puts } end
# File lib/minitap/minitest5.rb, line 239 def print(*args) io.print(*args) end
# File lib/minitap/minitest5.rb, line 235 def puts(*args) io.puts(*args) end
Process a test result.
# File lib/minitap/minitest5.rb, line 76 def record(minitest_result) super(minitest_result) result = TestResult.new(minitest_result) #if exception #&& ENV['minitap_debug'] # STDERR.puts exception # STDERR.puts exception.backtrace.join("\n") #end #@test_results[suite] ||= {} #@test_results[suite][test.to_sym] = record case_change = false if @previous_case != result.test_case case_change = true before_case(result.test_case) end #before_test(result) case result.type when :skip test_skip(result) when :pass test_pass(result) when :fail test_fail(result) when :err test_err(result) end after_test(result) if case_change after_case(result.test_case) end @previous_case = result.test_case end
Minitest’s finalization hook.
# File lib/minitap/minitest5.rb, line 119 def report super uncapture_io after_suite() end
Minitest’s initial hook ran just before testing begins.
# File lib/minitap/minitest5.rb, line 59 def start super @test_cases = Runnable.runnables capture_io #@_stdout, @_stderr = capture_io do # super_result = super(suite, type) #end before_suite(@test_cases) end
# File lib/minitap/minitest5.rb, line 172 def test_err(result) tapout_test_error(result) end
# File lib/minitap/minitest5.rb, line 168 def test_fail(result) tapout_test_failure(result) end
# File lib/minitap/minitest5.rb, line 164 def test_pass(result) tapout_test_pass(result) end
# File lib/minitap/minitest5.rb, line 160 def test_skip(result) tapout_test_skip(result) end
Private Instance Methods
# File lib/minitap/minitest5.rb, line 624 def capture_io @_stdout, @_stderr = $stdout, $stderr $stdout, $stderr = StringIO.new, StringIO.new end
# File lib/minitap/minitest5.rb, line 605 def clean_message(message) message.strip #.gsub(/\s*\n\s*/, "\n") end
Returns a String of source code.
# File lib/minitap/minitest5.rb, line 555 def code_snippet(file, line) s = [] if File.file?(file) source = source(file) radius = 2 # TODO: make customizable (number of surrounding lines to show) region = [line - radius, 1].max .. [line + radius, source.length].min s = region.map do |n| {n => source[n-1].chomp} end end return s end
# def add_test_result(suite, test, test_runner)
self.report[suite] ||= {} self.report[suite][test.to_sym] = test_runner self.assertion_count += test_runner.assertions case test_runner.result when :skip then self.skips += 1 when :failure then self.failures += 1 when :error then self.errors += 1 end
end
# File lib/minitap/minitest5.rb, line 270 def count_tests!(test_cases) filter = options[:filter] || '/./' filter = Regexp.new $1 if filter =~ /\/(.*)\// @test_count = test_cases.inject(0) do |acc, test_case| acc + test_case.runnable_methods.grep(filter).length end end
Clean the backtrace of any reference to test framework itself.
# File lib/minitap/minitest5.rb, line 537 def filter_backtrace(backtrace) ## remove backtraces that match any pattern in IGNORE_CALLERS trace = backtrace.reject{|b| IGNORE_CALLERS.any?{|i| i=~b}} ## remove `:in ...` portion of backtraces trace = trace.map do |bt| i = bt.index(':in') i ? bt[0...i] : bt end ## now apply MiniTest's own filter (note: doesn't work if done first, why?) trace = Minitest::filter_backtrace(trace) ## if the backtrace is empty now then revert to the original trace = backtrace if trace.empty? ## simplify paths to be relative to current workding diectory trace = trace.map{ |bt| bt.sub(Dir.pwd+File::SEPARATOR,'') } return trace end
# File lib/minitap/minitest5.rb, line 248 def filtered_tests(test_case) #suite, type filter = options[:filter] || '/./' filter = Regexp.new($1) if filter =~ /\/(.*)\// test_case.runnable_methods.grep(filter) end
Parse source location from caller, caller or an Exception object.
# File lib/minitap/minitest5.rb, line 579 def parse_source_location(caller) case caller when Exception trace = caller.backtrace.reject{ |bt| bt =~ INTERNALS } caller = trace.first when Array caller = caller.first end caller =~ /(.+?):(\d+(?=:|\z))/ or return "" source_file, source_line = $1, $2.to_i return source_file, source_line end
# File lib/minitap/minitest5.rb, line 515 def record_stdcom(doc) begin doc['stdout'] = $stdout.string unless $stdout.length == 0 #empty? doc['stderr'] = $stderr.string unless $stderr.length == 0 #empty? $stdout.close; $stderr.close $stdout, $stderr = StringIO.new, StringIO.new #end rescue => err uncapture_io raise err end end
Cache source file text. This is only used if the TAP-Y stream doesn not provide a snippet and the test file is locatable.
# File lib/minitap/minitest5.rb, line 572 def source(file) @_source_cache[file] ||= ( File.readlines(file) ) end
# File lib/minitap/minitest5.rb, line 327 def tapout_after_case(test_case) end
# File lib/minitap/minitest5.rb, line 296 def tapout_after_suite() doc = { 'type' => 'final', 'time' => Time.now - self.suite_start_time, 'counts' => { 'total' => self.test_count, 'pass' => self.test_count - self.failures - self.errors - self.skips, 'fail' => self.failures, 'error' => self.errors, 'omit' => self.skips, 'todo' => 0 # TODO: does minitest support pending tests? } } return doc end
# File lib/minitap/minitest5.rb, line 335 def tapout_after_test(result) end
# File lib/minitap/minitest5.rb, line 313 def tapout_before_case(test_case) doc = { 'type' => 'case', 'subtype' => '', 'label' => "#{test_case}", 'level' => 0 } record_stdcom(doc) return doc end
# File lib/minitap/minitest5.rb, line 284 def tapout_before_suite() doc = { 'type' => 'suite', 'start' => self.suite_start_time.strftime('%Y-%m-%d %H:%M:%S'), 'count' => self.test_count, 'seed' => self.options[:seed], 'rev' => REVISION } return doc end
# File lib/minitap/minitest5.rb, line 331 def tapout_before_test(result) end
TAP record for error.
Returns [Hash].
# File lib/minitap/minitest5.rb, line 465 def tapout_test_error(result) e = result.exception e_file, e_line = location(e) r_file = e_file.sub(Dir.pwd+'/', '') doc = { 'type' => 'test', 'subtype' => '', 'status' => 'error', 'label' => "#{result.label}", #'setup' => "foo instance", #'expected' => 2, #'returned' => 1, #'file' => test/test_foo.rb #'line' => 45 #'source' => ok 1, 2 #'snippet' => # - 44: ok 0,0 # - 45: ok 1,2 # - 46: ok 2,4 #'coverage' => # 'file' => lib/foo.rb # 'line' => 11..13 # 'code' => Foo#* 'exception' => { 'message' => clean_message(e.error.message), 'class' => e.error.class.name, 'file' => r_file, 'line' => e_line, 'source' => source(e_file)[e_line-1].strip, 'snippet' => code_snippet(e_file, e_line), 'backtrace' => filter_backtrace(e.backtrace) }, 'time' => Time.now - self.suite_start_time # result.time } record_stdcom(doc) #stdout, stderr = @_stdout, @_stderr #doc['stdout'] = stdout unless stdout.empty? #doc['stderr'] = stderr unless stderr.empty? return doc end
TAP record for failure.
Returns [Hash].
# File lib/minitap/minitest5.rb, line 417 def tapout_test_failure(result) e = result.exception e_file, e_line = location(result.exception) r_file = e_file.sub(Dir.pwd+'/', '') doc = { 'type' => 'test', 'subtype' => '', 'status' => 'fail', 'label' => "#{result.label}", #'setup' => "foo instance", #'expected' => 2, #'returned' => 1, #'file' => test/test_foo.rb #'line' => 45 #'source' => ok 1, 2 #'snippet' => # - 44: ok 0,0 # - 45: ok 1,2 # - 46: ok 2,4 #'coverage' => # 'file' => lib/foo.rb # 'line' => 11..13 # 'code' => Foo#* 'exception' => { 'message' => clean_message(e.message), 'class' => e.class.name, 'file' => r_file, 'line' => e_line, 'source' => source(e_file)[e_line-1].strip, 'snippet' => code_snippet(e_file, e_line), 'backtrace' => filter_backtrace(e.backtrace) }, 'time' => Time.now - self.suite_start_time # result.time } record_stdcom(doc) #stdout, stderr = @_stdout, @_stderr #doc['stdout'] = stdout unless stdout.empty? #doc['stderr'] = stderr unless stderr.empty? return doc end
TAP record for pass.
Returns [Hash].
# File lib/minitap/minitest5.rb, line 341 def tapout_test_pass(result) #suite, test, test_runner doc = { 'type' => 'test', 'subtype' => '', 'status' => 'pass', #'setup': foo instance 'label' => "#{result.label}", #'expected' => 2 #'returned' => 2 #'file' => 'test/test_foo.rb' #'line': 45 #'source': ok 1, 2 #'snippet': # - 44: ok 0,0 # - 45: ok 1,2 # - 46: ok 2,4 #'coverage': # file: lib/foo.rb # line: 11..13 # code: Foo#* 'time' => Time.now - self.suite_start_time } record_stdcom(doc) #stdout, stderr = @_stdout, @_stderr #doc['stdout'] = stdout unless stdout.empty? #doc['stderr'] = stderr unless stderr.empty? return doc end
TAP record for skip.
Returns [Hash].
# File lib/minitap/minitest5.rb, line 376 def tapout_test_skip(result) #suite, test, test_runner e = result.exception e_file, e_line = location(result.exception) r_file = e_file.sub(Dir.pwd+'/', '') doc = { 'type' => 'test', 'subtype' => '', 'status' => 'skip', 'label' => "#{result.label}", #'setup' => "foo instance", #'expected' => 2, #'returned' => 1, #'file' => test/test_foo.rb #'line' => 45 #'source' => ok 1, 2 #'snippet' => # - 44: ok 0,0 # - 45: ok 1,2 # - 46: ok 2,4 #'coverage' => # 'file' => lib/foo.rb # 'line' => 11..13 # 'code' => Foo#* 'exception' => { 'message' => clean_message(e.message), 'class' => e.class.name, 'file' => r_file, 'line' => e_line, 'source' => source(e_file)[e_line-1].strip, 'snippet' => code_snippet(e_file, e_line), 'backtrace' => filter_backtrace(e.backtrace) }, 'time' => Time.now - self.suite_start_time } return doc end
# File lib/minitap/minitest5.rb, line 630 def uncapture_io $stdout, $stderr = @_stdout, @_stderr end