| | 292 | |
| | 293 | |
| | 294 | module Test |
| | 295 | @@start = nil |
| | 296 | @@cases = Hash.new {|hash,key| hash[key] = [0,0,0] } |
| | 297 | @@count = 0 |
| | 298 | @@data = nil |
| | 299 | |
| | 300 | if ENV["TERM"] =~ /color/i && $stdout.stat.chardev? |
| | 301 | module Color |
| | 302 | SUCCESS = "\e[0;32m" |
| | 303 | FAIL = "\e[1;33m" |
| | 304 | ERROR = "\e[0;31m" |
| | 305 | NORMAL = "\e[00m" |
| | 306 | end |
| | 307 | else |
| | 308 | module Color |
| | 309 | SUCCESS = "" |
| | 310 | FAIL = "" |
| | 311 | ERROR = "" |
| | 312 | NORMAL = "" |
| | 313 | end |
| | 314 | end |
| | 315 | |
| | 316 | def self.report |
| | 317 | proc { |
| | 318 | finish = Time.now |
| | 319 | puts "\n1..#{@@count}" |
| | 320 | puts "Finished in #{finish - @@start} seconds." |
| | 321 | puts "" |
| | 322 | succes = @@cases.to_a.inject(0) {|r,(n,c)| r + c[0] } |
| | 323 | failure = @@cases.to_a.inject(0) {|r,(n,c)| r + c[1] } |
| | 324 | error = @@cases.to_a.inject(0) {|r,(n,c)| r + c[2] } |
| | 325 | # FIXME color |
| | 326 | puts "#{@@cases.size} tests, " + |
| | 327 | "#{succes+failure+error} assertions, " + |
| | 328 | "#{failure} failures, " + |
| | 329 | "#{error} errors" |
| | 330 | } |
| | 331 | end |
| | 332 | |
| | 333 | def self.included(*mod) |
| | 334 | ObjectSpace.define_finalizer(mod, report) |
| | 335 | @@start = Time.now |
| | 336 | end |
| | 337 | |
| | 338 | def test(name, directive = nil, &block) |
| | 339 | @@count += 1 |
| | 340 | if yield |
| | 341 | tap(Color::SUCCESS, "ok", @@count, name, directive) |
| | 342 | @@cases[name][0] += 1 |
| | 343 | else |
| | 344 | tap(Color::FAIL, "not ok", @@count, name, directive) |
| | 345 | print_backtrace(caller, "test failed") |
| | 346 | @@cases[name][1] += 1 |
| | 347 | end |
| | 348 | rescue |
| | 349 | tap(Color::ERROR, "not ok", @@count, name, directive) |
| | 350 | print_backtrace($!.backtrace, "#{$!} (#{$!.class})") |
| | 351 | @@cases[name][2] += 1 |
| | 352 | end |
| | 353 | |
| | 354 | def data |
| | 355 | require 'yaml' |
| | 356 | @@data ||= YAML.load_stream(DATA.read.gsub(/(^\t+)/) { |
| | 357 | ' ' * $+.length |
| | 358 | }).documents.map {|obj| |
| | 359 | obj.each_pair {|k,v| |
| | 360 | (class<<obj; self; end).instance_eval do |
| | 361 | define_method(k) { v } |
| | 362 | end rescue nil |
| | 363 | } rescue obj |
| | 364 | } |
| | 365 | end |
| | 366 | |
| | 367 | def run(&block) |
| | 368 | data.each {|d| |
| | 369 | yield d |
| | 370 | } |
| | 371 | end |
| | 372 | |
| | 373 | private |
| | 374 | def tap(color, stat, count, name, directive = nil) |
| | 375 | if directive |
| | 376 | directive = " # #{directive.to_s.upcase}" |
| | 377 | end |
| | 378 | print "#{color}\n#{stat} #{count} #{name}#{directive}\n#{Color::NORMAL}" |
| | 379 | end |
| | 380 | |
| | 381 | def print_backtrace(trace, msg) |
| | 382 | puts "#{trace.shift}: #{msg}" |
| | 383 | trace.each {|c| |
| | 384 | unless c.to_s.include?(__FILE__) |
| | 385 | puts "\tfrom #{c}" |
| | 386 | end |
| | 387 | } |
| | 388 | end |
| | 389 | end |
| | 390 | |