lib/qed/reporter/abstract.rb in qed-2.3.0 vs lib/qed/reporter/abstract.rb in qed-2.4.0
- old
+ new
@@ -5,44 +5,56 @@
require 'ansi/code'
# = Reporter Absract Base Class
#
# Serves as the base class for all other output formats.
- #
class Abstract
attr :io
- attr :steps
- attr :omit
+ attr :record
def initialize(options={})
@io = options[:io] || STDOUT
@trace = options[:trace]
- @demos = 0
- @steps = 0
- @omit = []
- @pass = []
- @fail = []
- @error = []
+ @record = {
+ :demo => [],
+ :step => [],
+ :omit => [],
+ :pass => [],
+ :fail => [],
+ :error => []
+ }
+
+ #@demos = 0
+ #@steps = 0
+ #@omit = []
+ #@pass = []
+ #@fail = []
+ #@error = []
+
+ @source = {}
end
- def passes ; @pass ; end
- def errors ; @error ; end
- def failures ; @fail ; end
+ def demos ; @record[:demo] ; end
+ def steps ; @record[:step] ; end
+ def omits ; @record[:omit] ; end
+ def passes ; @record[:pass] ; end
+ def errors ; @record[:error] ; end
+ def fails ; @record[:fail] ; end
#
def trace?
@trace
end
#
def update(type, *args)
+ __send__("count_#{type}", *args) if respond_to?("count_#{type}")
__send__("#{type}", *args)
end
-
def self.When(type, &block)
#raise ArgumentError unless %w{session demo demonstration step}.include?(type.to_s)
#type = :demonstration if type.to_s == 'demo'
define_method(type, &block)
end
@@ -69,17 +81,43 @@
#def After(type, target, *args)
# type = :demonstration if type.to_s == 'demo'
# __send__("after_#{type}", target, *args)
#end
+ def count_demo(demo)
+ @record[:demo] << demo
+ end
+
+ def count_desc(step)
+ @record[:step] << step
+ end
+
+ def count_code(step)
+ @record[:step] << step
+ end
+
+ def count_pass(step)
+ @record[:pass] << step
+ end
+
+ def count_fail(step, exception)
+ @record[:fail] << [step, exception]
+ end
+
+ def count_error(step, exception)
+ @record[:error] << [step, exception]
+ end
+
+
# At the start of a session, before running any demonstrations.
def before_session(session)
+ @start_time = Time.now
end
# Beginning of a demonstration.
def before_demo(demo) #demo(demo)
- @demos += 1
+ #demos << demo
end
#
def load(demo)
end
@@ -89,49 +127,95 @@
end
#def comment(elem)
#end
+ #
+ def before_step(step)
+ #@steps += 1
+ end
+
+ #
+ def before_head(step)
+ end
+
+ #
+ def before_desc(step)
+ #steps << step
+ end
+
+ #
+ def before_data(step)
+ end
+
# Before running a step that is omitted.
- #def omit_step(step)
+ #def before_omit(step)
# @omit << step
#end
#
- def before_step(step, file)
- @steps += 1
+ def before_code(step)
+ #steps << step
end
- # Right before running code.
- def code(section)
+ # Reight before demo.
+ def demo(demo)
end
+ # Right before header.
+ def head(step)
+ end
+
# Right before text section.
- def text(section)
+ def desc(step) #text ?
end
+ # Right before date section.
+ def data(step)
+ end
+
+ # Right before running code.
+ def code(step)
+ end
+
# After running a step that passed.
def pass(step)
- @pass << step
+ #@pass << step
end
# After running a step that failed.
def fail(step, assertion)
- @fail << [step, assertion]
+ #@fail << [step, assertion]
end
# After running a step that raised an error.
def error(step, exception)
raise exception if $DEBUG
- @error << [step, exception]
+ #@error << [step, exception]
end
#
- def after_step(step, file)
+ def after_data(step)
end
#
+ def after_code(step)
+ end
+
+ #
+ def after_desc(step)
+ end
+
+ #
+ def after_head(step)
+ end
+
+ #
+ def after_step(step)
+ end
+
+ #
def unload
end
# End of a demonstration.
def after_demo(demo) #demo(demo)
@@ -140,18 +224,84 @@
# After running all demonstrations. This is the place
# to output a summary of the session, if applicable.
def after_session(session)
end
- #
+ # TODO: should we rename b/c of keyword?
def when(*args)
end
private
+ def print_time
+ io.puts "\nFinished in %.5f seconds.\n\n" % [Time.now - @start_time]
+ end
+
+ def print_tally
+ mask = "%s demos, %s steps: %s failures, %s errors (%s/%s assertions)"
+ vars = [demos.size, steps.size, fails.size, errors.size, $assertions-$failures, $assertions] #, @pass.size ]
+
+ io.puts mask % vars
+ end
+
#
def clean_backtrace(btrace)
btrace.chomp(":in \`__binding__'")
+ end
+
+ #
+ INTERNALS = /(lib|bin)[\\\/]qed/
+
+=begin
+ # Clean the backtrace of any reference to ko/ paths and code.
+ def clean_backtrace(backtrace)
+ trace = backtrace.reject{ |bt| bt =~ INTERNALS }
+ trace.map do |bt|
+ if i = bt.index(':in')
+ bt[0...i]
+ else
+ bt
+ end
+ end
+ end
+=end
+
+ #
+ def code_snippet(exception, bredth=3)
+ backtrace = exception.backtrace.reject{ |bt| bt =~ INTERNALS }
+ backtrace.first =~ /(.+?):(\d+(?=:|\z))/ or return ""
+ source_file, source_line = $1, $2.to_i
+
+ source = source(source_file)
+
+ radius = bredth # number of surrounding lines to show
+ region = [source_line - radius, 1].max ..
+ [source_line + radius, source.length].min
+
+ # ensure proper alignment by zero-padding line numbers
+ format = " %2s %0#{region.last.to_s.length}d %s"
+
+ pretty = region.map do |n|
+ format % [('=>' if n == source_line), n, source[n-1].chomp]
+ end #.unshift "[#{region.inspect}] in #{source_file}"
+
+ pretty
+ end
+
+ #
+ def source(file)
+ @source[file] ||= (
+ File.readlines(file)
+ )
+ end
+
+ # TODO: Show more of the file name than just the basename.
+ def file_and_line(exception)
+ line = exception.backtrace[0]
+ return "" unless line
+ i = line.rindex(':in')
+ line = i ? line[0...i] : line
+ File.basename(line)
end
end
end