class RSpec::TapBaseFormatter

Constants

REVISION

TAP-Y/J Revision

Attributes

example_group_stack[RW]

Public Class Methods

new(output) click to toggle source
Calls superclass method
# File lib/rspec/ontap.rb, line 17
def initialize(output)
  super(output)
  @example_group_stack = []
end

Public Instance Methods

close(null_notification) click to toggle source

(not used)

Calls superclass method
# File lib/rspec/ontap.rb, line 299
def close(null_notification)
  # there is a super method for this
  super(null_notification)
end
dump_failures(examples_notification) click to toggle source

(not used)

# File lib/rspec/ontap.rb, line 295
def dump_failures(examples_notification)
end
dump_pending(examples_notification) click to toggle source

(not used)

# File lib/rspec/ontap.rb, line 291
def dump_pending(examples_notification)
end
dump_summary(summary_notification) click to toggle source

This method is invoked after the dumping of examples and failures.

# File lib/rspec/ontap.rb, line 221
def dump_summary(summary_notification)
  #super(summary_notification)

  duration      = summary_notification.duration
  example_count = summary_notification.examples.size
  failure_count = summary_notification.failed_examples.size
  pending_count = summary_notification.pending_examples.size

  failed_examples = summary_notification.failed_examples

  error_count = 0

  failed_examples.each do |e|
    if RSpec::Expectations::ExpectationNotMetError === e.exception
      #failure_count += 1
    else
      failure_count -= 1
      error_count += 1
    end
  end

  passing_count = example_count - failure_count - error_count - pending_count

  doc = {
    'type' => 'final',
    'time' => duration,
    'counts' => {
      'total' => example_count,
      'pass'  => passing_count,
      'fail'  => failure_count,
      'error' => error_count,
      'omit'  => 0,
      'todo'  => pending_count
    }
  }
  return doc
end
example_failed(notification) click to toggle source
# File lib/rspec/ontap.rb, line 152
def example_failed(notification)
  #super(notification)

  example = notification.example

  file, line = example.location.split(':')

  file = relative_path(file)
  line = line.to_i

  if RSpec::Expectations::ExpectationNotMetError === example.exception
    status = 'fail'
    if md = /expected:\s*(.*?)\n\s*got:\s*(.*?)\s+/.match(example.exception.to_s)
      expected, returned = md[1], md[2]
    else
      expected, returned = nil, nil
    end
  else
    status = 'error'
  end

  backtrace = format_backtrace(example.exception.backtrace, example.metadata)

  efile, eline = parse_source_location(backtrace)

  doc = {
    'type'        => 'test',
    'subtype'     => 'it',
    'status'      => status,
    'label'       => "#{example.description}",
    #'setup' => "foo instance",
    'file'    => file,
    'line'    => line,
    'source'  => source(file)[line-1].strip,
    'snippet' => code_snippet(file, line),
    #'coverage' =>
    #{
    #  'file' => lib/foo.rb
    #  'line' => 11..13
    #  'code' => Foo#*
    #}
  }

  if expected or returned
    doc.update(
      'expected' => expected,
      'returned' => returned,
    )
  end

  doc.update(
    'exception' => {
      'message'   => example.exception.to_s.strip,
      'class'     => example.exception.class.name,
      'file'      => efile,
      'line'      => eline,
      'source'    => source(efile)[eline-1].strip,
      'snippet'   => code_snippet(efile, eline),
      'backtrace' => backtrace
    },
    'time' => Time.now - @start_time
  )

  doc.update(captured_output)

  return doc
end
example_group_finished(notification) click to toggle source

This method is invoked at the end of the execution of each example group. example_group is the example_group.

# File lib/rspec/ontap.rb, line 68
def example_group_finished(notification)
  #super(notification)
  @example_group_stack.pop
end
example_group_started(notification) click to toggle source

This method is invoked at the beginning of the execution of each example group. example_group is the example_group.

The next method to be invoked after this is example_passed, example_pending, or example_finished

Calls superclass method
# File lib/rspec/ontap.rb, line 53
def example_group_started(notification)
  # there is a super method for this
  super(notification)
  doc = {
    'type'    => 'case',
    'subtype' => 'describe',
    'label'   => "#{notification.group.description}",
    'level'   => @example_group_stack.size
  }
  @example_group_stack << example_group
  return doc
end
example_passed(notification) click to toggle source
# File lib/rspec/ontap.rb, line 82
def example_passed(notification)
  #super(notification)

  example = notification.example

  file, line = example.location.split(':')
  #file = self.class.relative_path(file)
  file = relative_path(file)
  line = line.to_i

  doc = {
    'type'     => 'test',
    'subtype'  => 'it',
    'status'   => 'pass',
    #'setup': foo instance
    'label'    => "#{example.description}",
    #'expected' => 2
    #'returned' => 2
    'file'     => file,
    'line'     => line,
    'source'   => source(file)[line-1].strip,
    'snippet'  => code_snippet(file, line),
    #'coverage' => {
    #  file: lib/foo.rb
    #  line: 11..13
    #  code: Foo#*
    #}
    'time' => Time.now - @start_time
  }

  doc.update(captured_output)
   
  return doc
end
example_pending(notification) click to toggle source
# File lib/rspec/ontap.rb, line 118
def example_pending(notification)
  #super(notification)

  example = notification.example

  file, line = example.location.split(':')
  #file = self.class.relative_path(file)
  file = relative_path(file)
  line = line.to_i

  doc = {
    'type'    => 'test',
    'subtype' => 'it',
    'status'  => 'todo',
    #'setup': foo instance
    'label'   => "#{example.description}",
    'file'    => file,
    'line'    => line,
    'source'  => source(file)[line-1].strip,
    'snippet' => code_snippet(file, line),
    #'coverage' => {
    #  file: lib/foo.rb
    #  line: 11..13
    #  code: Foo#*
    #}
    'time' => Time.now - @start_time
  }

  doc.update(captured_output)

  return doc
end
example_started(notification) click to toggle source

Set up stdout and stderr to be captured.

IMPORTANT: Comment out the ‘reset_output` line to debug!!!!!!!!!

# File lib/rspec/ontap.rb, line 77
def example_started(notification)
  reset_output
end
message(message_notification) click to toggle source

Add any messages as notes.

# File lib/rspec/ontap.rb, line 268
def message(message_notification)
  doc = {
    'type' => 'note',
    'text' => message_notification.message
  }
  return doc
end
seed(notification) click to toggle source
This gets invoked after the summary if option is set to do so.

def dump_pending end

# File lib/rspec/ontap.rb, line 263
def seed(notification)
  @seed = notification.seed
end
start(notification) click to toggle source

This method is invoked before any examples are run, right after they have all been collected. This can be useful for special formatters that need to provide progress on feedback (graphical ones)

This will only be invoked once, and the next one to be invoked is example_group_started

Calls superclass method
# File lib/rspec/ontap.rb, line 30
def start(notification)
  # there is a super method for this
  super(notification)

  @start_time = Time.now

  doc = {
    'type'  => 'suite',
    'start' => @start_time.strftime('%Y-%m-%d %H:%M:%S'),
    'count' => notification.count,
    'seed'  => @seed,
    'rev'   => REVISION
  }
  return doc
end
start_dump(null_notification) click to toggle source

(not used)

# File lib/rspec/ontap.rb, line 287
def start_dump(null_notification)
end
stop(examples_notification) click to toggle source

(not used)

Calls superclass method
# File lib/rspec/ontap.rb, line 282
def stop(examples_notification)
  super(examples_notification)
end

Private Instance Methods

backtrace_formatter() click to toggle source
# File lib/rspec/ontap.rb, line 413
def backtrace_formatter
  RSpec.configuration.backtrace_formatter
end
capture_io() { || ... } click to toggle source
# File lib/rspec/ontap.rb, line 375
def capture_io
  ostdout, ostderr = $stdout, $stderr
  cstdout, cstderr = StringIO.new, StringIO.new
  $stdout, $stderr = cstdout, cstderr

  yield

  return cstdout.string.chomp("\n"), cstderr.string.chomp("\n")
ensure
  $stdout = ostdout
  $stderr = ostderr
end
captured_output() click to toggle source
# File lib/rspec/ontap.rb, line 358
def captured_output
  return unless (@_newout && @_newerr)

  stdout = @_newout.string.chomp("\n")
  stderr = @_newerr.string.chomp("\n")

  doc = {}
  doc['stdout'] = stdout unless stdout.empty?
  doc['stderr'] = stderr unless stderr.empty?

  $stdout = @_oldout
  $stderr = @_olderr

  return doc
end
code_snippet(file, line) click to toggle source

Returns a String of source code.

# File lib/rspec/ontap.rb, line 307
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
format_backtrace(*args) click to toggle source
# File lib/rspec/ontap.rb, line 408
def format_backtrace(*args)
  backtrace_formatter.format_backtrace(*args)
end
parse_source_location(caller) click to toggle source

Parse source location from caller, caller or an Exception object.

# File lib/rspec/ontap.rb, line 332
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
relative_path(line) click to toggle source

Get relative path of file.

line - current code line [String]

Returns relative path to line. [String]

# File lib/rspec/ontap.rb, line 398
def relative_path(line)
  line = line.sub(relative_path_regex, "\\1.\\2".freeze)
  line = line.sub(/\A([^:]+:\d+)$/, '\\1'.freeze)
  return nil if line == '-e:1'.freeze
  line
rescue SecurityError
  nil
end
relative_path_regex() click to toggle source
# File lib/rspec/ontap.rb, line 389
def relative_path_regex
  @relative_path_regex ||= /(\A|\s)#{File.expand_path('.')}(#{File::SEPARATOR}|\s|\Z)/
end
reset_output() click to toggle source
# File lib/rspec/ontap.rb, line 346
def reset_output
  @_oldout = $stdout
  @_olderr = $stderr

  @_newout = StringIO.new
  @_newerr = StringIO.new

  $stdout = @_newout
  $stderr = @_newerr
end
source(file) click to toggle source

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/rspec/ontap.rb, line 324
def source(file)
  @_source_cache ||= {}
  @_source_cache[file] ||= (
    File.readlines(file)
  )
end