Class: TapOut::Reporters::Abstract
- Inherits:
-
Object
- Object
- TapOut::Reporters::Abstract
- Defined in:
- lib/tapout/reporters/abstract.rb
Overview
The Abstract class serves as a base class for all reporters. Reporters must sublcass Abstract in order to be added the the Reporters Index.
TODO: Simplify this class and have the sublcasses handle more of the load.
Direct Known Subclasses
BreakdownReporter, DotReporter, Html, Outline, PrettyReporter, ProgressReporter, TapReporter, TurnReporter
Constant Summary collapse
- INTERNALS =
Used to clean-up backtrace.
TODO: Use Rubinius global system instead.
/(lib|bin)#{Regexp.escape(File::SEPARATOR)}tapout/
Class Method Summary collapse
-
.inherited(subclass) ⇒ Object
When Abstract is inherited it saves a reference to it in ‘Reporters.index`.
Instance Method Summary collapse
- #<<(entry) ⇒ Object
-
#clean_backtrace(backtrace) ⇒ Object
Clean the backtrace of any reference to ko/ paths and code.
-
#code_snippet(entry) ⇒ Object
Returns a String of source code.
- #complete_cases(case_entry = nil) ⇒ Object
-
#error(entry) ⇒ Object
Handle test with error status.
-
#exit_code ⇒ Object
Get the exit code.
-
#fail(entry) ⇒ Object
Handle test with fail status.
-
#finalize ⇒ Object
When all is said and done.
-
#finish_case(entry) ⇒ Object
When a test case is complete.
-
#finish_suite(entry) ⇒ Object
Handle final entry.
-
#finish_test(entry) ⇒ Object
When a test unit is complete.
-
#handle(entry) ⇒ Object
Handler method.
-
#initialize ⇒ Abstract
constructor
New reporter.
-
#note(entry) ⇒ Object
Handle an arbitray note.
-
#omit(entry) ⇒ Object
Handle test with omit status.
-
#parse_source_location(caller) ⇒ Object
Parse source location from caller, caller or an Exception object.
-
#pass(entry) ⇒ Object
Handle test with pass status.
-
#skip(entry) ⇒ Object
Handle test with skip or pending status.
-
#source(file) ⇒ Object
Cache source file text.
-
#start_case(entry) ⇒ Object
At the start of a new test case.
-
#start_suite(entry) ⇒ Object
Handle header.
-
#start_test(entry) ⇒ Object
Handle test.
-
#tally(entry) ⇒ Object
Handle running tally.
-
#tally_message(entry) ⇒ String
Generate a tally message given a tally or final entry.
Constructor Details
#initialize ⇒ Abstract
New reporter.
40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/tapout/reporters/abstract.rb', line 40 def initialize @passed = [] @failed = [] @raised = [] @skipped = [] @omitted = [] @case_stack = [] @source = {} @exit_code = 0 # assume passing end |
Class Method Details
.inherited(subclass) ⇒ Object
When Abstract is inherited it saves a reference to it in ‘Reporters.index`.
33 34 35 36 37 |
# File 'lib/tapout/reporters/abstract.rb', line 33 def self.inherited(subclass) name = subclass.name.split('::').last.downcase name = name.chomp('reporter') Reporters.index[name] = subclass end |
Instance Method Details
#<<(entry) ⇒ Object
117 118 119 |
# File 'lib/tapout/reporters/abstract.rb', line 117 def <<(entry) handle(entry) end |
#clean_backtrace(backtrace) ⇒ Object
Clean the backtrace of any reference to ko/ paths and code.
211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/tapout/reporters/abstract.rb', line 211 def clean_backtrace(backtrace) trace = backtrace.reject{ |bt| bt =~ INTERNALS } trace = trace.map do |bt| if i = bt.index(':in') bt[0...i] else bt end end trace = backtrace if trace.empty? trace = trace.map{ |bt| bt.sub(Dir.pwd+File::SEPARATOR,'') } trace end |
#code_snippet(entry) ⇒ Object
Returns a String of source code.
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/tapout/reporters/abstract.rb', line 226 def code_snippet(entry) file = entry['file'] line = entry['line'] snippet = entry['snippet'] s = [] case snippet when String lines = snippet.lines.to_a index = line - ((lines.size - 1) / 2) lines.each do |line| s << [index, line] index += 1 end when Array snippet.each do |h| s << [h.keys.first, h.values.first] end else ##backtrace = exception.backtrace.reject{ |bt| bt =~ INTERNALS } ##backtrace.first =~ /(.+?):(\d+(?=:|\z))/ or return "" #caller =~ /(.+?):(\d+(?=:|\z))/ or return "" #source_file, source_line = $1, $2.to_i if file && File.file?(file) source = source(file) radius = 3 # number of surrounding lines to show region = [line - radius, 1].max .. [line + radius, source.length].min #len = region.last.to_s.length s = region.map do |n| #format % [n, source[n-1].chomp] [n, source[n-1].chomp] end end end len = s.map{ |(n,t)| n }.max.to_s.length # ensure proper alignment by zero-padding line numbers format = " %5s %0#{len}d %s" #s = s.map{|n,t|[n,t]}.sort{|a,b|a[0]<=>b[0]} pretty = s.map do |(n,t)| format % [('=>' if n == line), n, t.rstrip] end #.unshift "[#{region.inspect}] in #{source_file}" return pretty end |
#complete_cases(case_entry = nil) ⇒ Object
304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/tapout/reporters/abstract.rb', line 304 def complete_cases(case_entry=nil) if case_entry while @case_stack.last and @case_stack.last['level'].to_i >= case_entry['level'].to_i finish_case(@case_stack.pop) end else while @case_stack.last finish_case(@case_stack.pop) end end end |
#error(entry) ⇒ Object
Handle test with error status.
80 81 82 |
# File 'lib/tapout/reporters/abstract.rb', line 80 def error(entry) @raised << entry end |
#exit_code ⇒ Object
Get the exit code.
159 160 161 |
# File 'lib/tapout/reporters/abstract.rb', line 159 def exit_code @exit_code end |
#fail(entry) ⇒ Object
Handle test with fail status.
75 76 77 |
# File 'lib/tapout/reporters/abstract.rb', line 75 def fail(entry) @failed << entry end |
#finalize ⇒ Object
When all is said and done.
53 54 55 |
# File 'lib/tapout/reporters/abstract.rb', line 53 def finalize @exit_code end |
#finish_case(entry) ⇒ Object
When a test case is complete.
107 108 |
# File 'lib/tapout/reporters/abstract.rb', line 107 def finish_case(entry) end |
#finish_suite(entry) ⇒ Object
Handle final entry.
111 112 |
# File 'lib/tapout/reporters/abstract.rb', line 111 def finish_suite(entry) end |
#finish_test(entry) ⇒ Object
When a test unit is complete.
103 104 |
# File 'lib/tapout/reporters/abstract.rb', line 103 def finish_test(entry) end |
#handle(entry) ⇒ Object
Handler method. This dispatches a given entry to the appropriate report methods.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/tapout/reporters/abstract.rb', line 123 def handle(entry) case entry['type'] when 'suite' start_suite(entry) when 'case' complete_cases(entry) @case_stack << entry start_case(entry) when 'note' note(entry) when 'test' start_test(entry) case entry['status'] when 'pass' pass(entry) when 'fail' @exit_code = -1 fail(entry) when 'error' @exit_code = -1 error(entry) when 'omit' omit(entry) when 'todo', 'skip', 'pending' skip(entry) end finish_test(entry) when 'tally' tally(entry) when 'final' complete_cases finish_suite(entry) end end |
#note(entry) ⇒ Object
Handle an arbitray note.
95 96 |
# File 'lib/tapout/reporters/abstract.rb', line 95 def note(entry) end |
#omit(entry) ⇒ Object
Handle test with omit status.
85 86 87 |
# File 'lib/tapout/reporters/abstract.rb', line 85 def omit(entry) @omitted << entry end |
#parse_source_location(caller) ⇒ Object
Parse source location from caller, caller or an Exception object.
290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/tapout/reporters/abstract.rb', line 290 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 returnf source_file, source_line end |
#pass(entry) ⇒ Object
Handle test with pass status.
70 71 72 |
# File 'lib/tapout/reporters/abstract.rb', line 70 def pass(entry) @passed << entry end |
#skip(entry) ⇒ Object
Handle test with skip or pending status.
90 91 92 |
# File 'lib/tapout/reporters/abstract.rb', line 90 def skip(entry) @skipped << entry end |
#source(file) ⇒ Object
Cache source file text. This is only used if the TAP-Y stream doesn not provide a snippet and the test file is locatable.
283 284 285 286 287 |
# File 'lib/tapout/reporters/abstract.rb', line 283 def source(file) @source[file] ||= ( File.readlines(file) ) end |
#start_case(entry) ⇒ Object
At the start of a new test case.
62 63 |
# File 'lib/tapout/reporters/abstract.rb', line 62 def start_case(entry) end |
#start_suite(entry) ⇒ Object
Handle header.
58 59 |
# File 'lib/tapout/reporters/abstract.rb', line 58 def start_suite(entry) end |
#start_test(entry) ⇒ Object
Handle test. This is run before the status handlers.
66 67 |
# File 'lib/tapout/reporters/abstract.rb', line 66 def start_test(entry) end |
#tally(entry) ⇒ Object
Handle running tally.
99 100 |
# File 'lib/tapout/reporters/abstract.rb', line 99 def tally(entry) end |
#tally_message(entry) ⇒ String
Generate a tally message given a tally or final entry.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/tapout/reporters/abstract.rb', line 166 def (entry) total = @passed.size + @failed.size + @raised.size #+ @skipped.size + @omitted.size if entry['counts'] total = entry['counts']['total'] || total count_fail = entry['counts']['fail'] || 0 count_error = entry['counts']['error'] || 0 else count_fail = @failed.size count_error = @raised.size end if tally = entry['counts'] sums = %w{pass fail error todo omit}.map{ |e| tally[e] || 0 } else sums = [@passed, @failed, @raised, @skipped, @omitted].map{ |e| e.size } end # ??? assertions = entry['assertions'] failures = entry['failures'] if assertions text = "%s tests: %s pass, %s fail, %s err, %s todo, %omit (%s/%s assertions)" text = text % [total, *sums] + [assertions - failures, assertions] else text = "%s tests: %s pass, %s fail, %s err, %s todo, %s omit" text = text % [total, *sums] end if count_fail > 0 text.ansi(:red) elsif count_error > 0 text.ansi(:yellow) else text.ansi(:green) end end |