Permalink
Browse files

refactored into separate files

  • Loading branch information...
1 parent d456399 commit 5eb1a51fa5ca460f64c6004271c01d0f0ffb6ac2 @quackingduck quackingduck committed Mar 31, 2010
Showing with 337 additions and 305 deletions.
  1. +39 −0 lib/checker.rb
  2. +9 −0 lib/command.rb
  3. +101 −0 lib/environment.rb
  4. +62 −0 lib/examples.rb
  5. +44 −305 lib/exemplor.rb
  6. +15 −0 lib/ext.rb
  7. +67 −0 lib/result_printer.rb
View
@@ -0,0 +1,39 @@
+module Exemplor
+ class Check
+
+ attr_reader :expectation, :value, :status
+
+ def initialize(name, value)
+ @name = name
+ @value = value
+ @status = :info
+ end
+
+ def [](disambiguate)
+ @disambiguate = disambiguate
+ self
+ end
+
+ def name
+ @name + (defined?(@disambiguate) ? " #{@disambiguate}" : '')
+ end
+
+ def is(expectation)
+ @expectation = expectation
+ @status = (value == expectation) ? :success : :failure
+ end
+
+ def success?
+ status == :success
+ end
+
+ def failure?
+ status == :failure
+ end
+
+ def info?
+ status == :info
+ end
+
+ end
+end
View
@@ -0,0 +1,9 @@
+# takes an array of command line arguments
+def Exemplor(args)
+ args = args.dup
+ if args.delete('--list') || args.delete('-l')
+ Exemplor.examples.list(args)
+ else
+ exit Exemplor.examples.run(args)
+ end
+end
View
@@ -0,0 +1,101 @@
+module Exemplor
+
+ class ExampleEnv
+
+ class << self
+
+ alias_method :helpers, :class_eval
+ attr_accessor :setup_block
+
+ def setup(&blk) self.setup_block = blk end
+
+ # runs the block in the example environment, returns triple:
+ # [status, result, stderr]
+ def run(&code)
+ env = self.new
+ stderr = StringIO.new
+ status, result = begin
+ real_stderr = $stderr ; $stderr = stderr # swap stderr
+
+ env.instance_eval(&self.setup_block) if self.setup_block
+ value = env.instance_eval(&code)
+ result = env._status == :info ?
+ render_value(value) : render_checks(env._checks)
+ [env._status, result]
+
+ rescue Object => error
+ [:error, render_error(error)]
+ ensure
+ $stderr = real_stderr # swap stderr back
+ end
+ [status, result, stderr.rewind && stderr.read]
+ end
+
+ # -- these "render" methods could probably be factored away
+
+ # yaml doesn't want to print a class
+ def render_value(value)
+ value.kind_of?(Class) ? value.inspect : value
+ end
+
+ def render_checks(checks)
+ failure = nil
+ out = []
+ checks.each do |check|
+ failure = check if check.failure?
+ break if failure
+ out << OrderedHash do |o|
+ o['name'] = check.name
+ o['status'] = check.status.to_s
+ o['result'] = render_value check.value
+ end
+ end
+ if failure
+ out << OrderedHash do |o|
+ o['name'] = failure.name
+ o['status'] = failure.status.to_s
+ o['expected'] = failure.expectation
+ o['actual'] = render_value failure.value
+ end
+ end
+ out
+ end
+
+ def render_error(error)
+ OrderedHash do |o|
+ o['class'] = error.class.name
+ o['message'] = error.message
+ o['backtrace'] = error.backtrace
+ end
+ end
+
+ end
+
+ attr_accessor :_checks
+
+ def initialize
+ @_checks = []
+ end
+
+ def Check(value)
+ file, line_number = caller.first.match(/^(.+):(\d+)/).captures
+ line = File.readlines(file)[line_number.to_i - 1].strip
+ name = line[/Check\((.+?)\)\s*($|#|\[|\.is.+)/,1]
+ check = Check.new(name, value)
+ _checks << check
+ check
+ end
+
+ def _status
+ (:info if _checks.empty?) ||
+ (:failure if _checks.any? { |c| c.failure? }) ||
+ (:success if _checks.all? { |c| c.success? }) ||
+ :infos
+ end
+
+ end
+
+ def environment
+ ExampleEnv
+ end
+end
View
@@ -0,0 +1,62 @@
+module Exemplor
+
+ def examples
+ @examples ||= Examples.new
+ end
+
+ # sets @example_file to first file that calls the `eg` method
+ def set_example_file_from(caller_trace)
+ @example_file ||= caller_trace.first.split(":").first
+ end
+
+ def example_file_set?
+ !!@example_file
+ end
+
+ def run_directly?
+ @example_file == $0
+ end
+
+ class ExampleDefinitionError < StandardError ; end
+
+ def make_example_name_from(caller_trace)
+ file, line_number = caller_trace.first.match(/^(.+):(\d+)/).captures
+ line = File.readlines(file)[line_number.to_i - 1].strip
+ name = line[/^eg\s*\{\s*(.+?)\s*\}$/,1]
+ raise Exemplor::ExampleDefinitionError, "example at #{caller_trace.first} has no name so must be on one line" if name.nil?
+ name
+ end
+
+ class Examples
+
+ def initialize
+ @examples = OrderedHash.new
+ end
+
+ def add(name, &body)
+ @examples[name] = body
+ end
+
+ def run(patterns)
+ fails = 0
+ # unoffically supports multiple patterns
+ patterns = Regexp.new(patterns.join('|'))
+ examples_to_run = @examples.select { |name,_| name =~ patterns }
+ return 0 if examples_to_run.empty?
+ examples_to_run.each do |name, code|
+ result = ResultPrinter.new(name, *ExampleEnv.run(&code))
+ fails +=1 if result.failure?
+ puts($stdout.tty? ? result.fancy : result.yaml)
+ end
+ (fails.to_f/examples_to_run.size)*100
+ end
+
+ def list(patterns)
+ patterns = Regexp.new(patterns.join('|'))
+ list = @examples.keys.select { |name| name =~ patterns }
+ print YAML.without_header(list)
+ end
+
+ end
+
+end
Oops, something went wrong.

0 comments on commit 5eb1a51

Please sign in to comment.