Files
ruby_koans/koans/edgecase.rb
2010-08-16 16:57:13 -04:00

247 lines
5.0 KiB
Ruby

#!/usr/bin/env ruby
# -*- ruby -*-
require 'test/unit/assertions'
class FillMeInError < StandardError
end
def in_ruby_version(version)
yield if RUBY_VERSION =~ /^#{version}/
end
def __(value="FILL ME IN", value19=:mu)
if RUBY_VERSION < "1.9"
value
else
(value19 == :mu) ? value : value19
end
end
def _n_(value=999999, value19=:mu)
if RUBY_VERSION < "1.9"
value
else
(value19 == :mu) ? value : value19
end
end
def ___(value=FillMeInError)
value
end
class Object
def ____(method=nil)
if method
self.send(method)
end
end
in_ruby_version("1.9") do
public :method_missing
end
end
module EdgeCase
class Sensei
attr_reader :failure, :failed_test
in_ruby_version("1.8") do
AssertionError = Test::Unit::AssertionFailedError
end
in_ruby_version("1.9") do
if defined?(MiniTest)
AssertionError = MiniTest::Assertion
else
AssertionError = Test::Unit::AssertionFailedError
end
end
def initialize
@pass_count = 0
@failure = nil
@failed_test = nil
end
def accumulate(test)
if test.passed?
@pass_count += 1
puts " #{test.name} has expanded your awareness."
else
puts " #{test.name} has damaged your karma."
@failed_test = test
@failure = test.failure
throw :edgecase_exit
end
end
def failed?
! @failure.nil?
end
def assert_failed?
failure.is_a?(AssertionError)
end
def report
if failed?
puts
puts "You have not yet reached enlightenment ..."
puts failure.message
puts
puts "Please meditate on the following code:"
if assert_failed?
puts find_interesting_lines(failure.backtrace)
else
puts failure.backtrace
end
puts
end
say_something_zenlike
end
def find_interesting_lines(backtrace)
backtrace.reject { |line|
line =~ /test\/unit\/|edgecase\.rb/
}
end
# Hat's tip to Ara T. Howard for the zen statements from his
# metakoans Ruby Quiz (http://rubyquiz.com/quiz67.html)
def say_something_zenlike
puts
if !failed?
puts "Mountains are again merely mountains"
else
case (@pass_count % 10)
when 0
puts "mountains are merely mountains"
when 1, 2
puts "learn the rules so you know how to break them properly"
when 3, 4
puts "remember that silence is sometimes the best answer"
when 5, 6
puts "sleep is the best meditation"
when 7, 8
puts "when you lose, don't lose the lesson"
else
puts "things are not what they appear to be: nor are they otherwise"
end
end
end
end
class Koan
include Test::Unit::Assertions
attr_reader :name, :failure
def initialize(name)
@name = name
@failure = nil
end
def passed?
@failure.nil?
end
def failed(failure)
@failure = failure
end
def setup
end
def teardown
end
# Class methods for the EdgeCase test suite.
class << self
def inherited(subclass)
subclasses << subclass
end
def method_added(name)
testmethods << name unless tests_disabled?
end
def run_tests(accumulator)
puts
puts "Thinking #{self}"
testmethods.each do |m|
self.run_test(m, accumulator) if Koan.test_pattern =~ m.to_s
end
end
def run_test(method, accumulator)
test = self.new(method)
test.setup
begin
test.send(method)
rescue StandardError, EdgeCase::Sensei::AssertionError => ex
test.failed(ex)
ensure
begin
test.teardown
rescue StandardError, EdgeCase::Sensei::AssertionError => ex
test.failed(ex) if test.passed?
end
end
accumulator.accumulate(test)
end
def end_of_enlightenment
@tests_disabled = true
end
def command_line(args)
args.each do |arg|
case arg
when /^-n\/(.*)\/$/
@test_pattern = Regexp.new($1)
when /^-n(.*)$/
@test_pattern = Regexp.new(Regexp.quote($1))
else
if File.exist?(arg)
load(arg)
else
fail "Unknown command line argument '#{arg}'"
end
end
end
end
# Lazy initialize list of subclasses
def subclasses
@subclasses ||= []
end
# Lazy initialize list of test methods.
def testmethods
@test_methods ||= []
end
def tests_disabled?
@tests_disabled ||= false
end
def test_pattern
@test_pattern ||= /^test_/
end
end
end
end
END {
EdgeCase::Koan.command_line(ARGV)
zen_master = EdgeCase::Sensei.new
catch(:edgecase_exit) {
EdgeCase::Koan.subclasses.each do |sc|
sc.run_tests(zen_master)
end
}
zen_master.report
}