Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add customizable observer. [major]

  • Loading branch information...
commit 7236a550dd37a177a1fc4fbb2e45aca1afbcc669 1 parent a1bcfc1
@trans trans authored
View
0  NOTICE.md → LICENSE.txt
File renamed without changes
View
0  .test → Testfile
File renamed without changes
View
4 lib/rubytest.rb
@@ -11,6 +11,7 @@
require 'rubytest/code_snippet'
require 'rubytest/config'
require 'rubytest/recorder'
+ require 'rubytest/advice'
require 'rubytest/runner'
require 'rubytest/cli'
require 'rubytest/reporters/abstract'
@@ -18,8 +19,9 @@
else
require_relative 'rubytest/core_ext'
require_relative 'rubytest/code_snippet'
- require_relative 'rubytest/recorder'
require_relative 'rubytest/config'
+ require_relative 'rubytest/recorder'
+ require_relative 'rubytest/advice'
require_relative 'rubytest/runner'
require_relative 'rubytest/cli'
require_relative 'rubytest/reporters/abstract'
View
98 lib/rubytest/advice.rb
@@ -0,0 +1,98 @@
+module Test
+
+ # The Advice class is an observer that can be customized to
+ # initiate before, after and upon procedures for all of RubyTests
+ # observable points.
+ #
+ # Only one procedure is allowed per-point.
+ #
+ class Advice
+
+ #
+ def self.joinpoints
+ @joinpoints ||= []
+ end
+
+ #
+ def self.joinpoint(name)
+ joinpoints << name.to_sym
+
+ class_eval %{
+ def #{name}(*args)
+ @table[:#{name}].call(*args) if @table.key?(:#{name})
+ end
+ }
+ end
+
+ #
+ def initialize
+ @table = {}
+ end
+
+ #
+ joinpoint :before_suite
+
+ #
+ joinpoint :before_case
+
+ #
+ joinpoint :skip_test
+
+ #
+ joinpoint :before_test
+
+ #
+ joinpoint :pass
+
+ #
+ joinpoint :fail
+
+ #
+ joinpoint :error
+
+ #
+ joinpoint :todo
+
+ #
+ joinpoint :after_test
+
+ #
+ joinpoint :after_case
+
+ #
+ joinpoint :after_suite
+
+ #
+ #def [](key)
+ # @table[key.to_sym]
+ #end
+
+ # Add a procedure to one of the join-points.
+ def join(type, &block)
+ type = valid_type(type)
+ @table[type] = block
+ end
+
+ # Ignore any other signals (precautionary).
+ def method_missing(*)
+ end
+
+ private
+
+ #def invoke(symbol, *args)
+ # if @table.key?(symbol)
+ # self[symbol].call(*args)
+ # end
+ #end
+
+ def valid_type(type)
+ type = type.to_sym
+ unless self.class.joinpoints.include?(type)
+ raise ArgumentError, "not a valid advice type -- #{type}"
+ end
+ type
+ end
+
+ end
+
+end
View
2  lib/rubytest/cli.rb
@@ -23,6 +23,8 @@ def self.cli(*argv)
end
end
+ # TODO: replace dynamic preset options with `-p` option
+
#
def self.cli_options(runner, argv)
require 'optparse'
View
13 lib/rubytest/config.rb
@@ -10,21 +10,21 @@ def self.config
@config ||= {}
end
+ # TODO: Add optional support for Confection.
+
#
class Config
# Test configuration file.
#
- # The name of the file is an ode to the original Ruby cli test tool.
- #
# @example
# .test
- # .testrb
# .test.rb
- # .config/test.rb
+ # task/test.rb
+ # Testfile
#
# @todo Too many options for ruby-test configuration file.
- GLOB_RC = '{.testrb,.test.rb,.test,.config/test.rb,config/test.rb}'
+ GLOB_RC = '{,.,task/}test{,file}{.rb,}'
#
GLOB_ROOT = '{.ruby,.git,.hg}'
@@ -44,7 +44,8 @@ def self.rc_file
dir = Dir.pwd
file = nil
loop do
- file = Dir[File.join(dir, glob)].first
+ files = Dir.glob(File.join(dir, glob), File::FNM_CASEFOLD)
+ file = files.find{ |f| File.file?(f) }
break file if file
break if dir == stop
dir = File.dirname(dir)
View
10 lib/rubytest/recorder.rb
@@ -14,8 +14,8 @@ def [](key)
end
#
- def skip(test)
- self[:skip] << test
+ def skip_test(test, reason)
+ self[:skip] << [test, reason]
end
# Add `test` to pass set.
@@ -35,9 +35,9 @@ def todo(test, exception)
self[:todo] << [test, exception]
end
- def omit(test, exception)
- self[:omit] << [test, exception]
- end
+ #def omit(test, exception)
+ # self[:omit] << [test, exception]
+ #end
# Returns true if their are no test errors or failures.
def success?
View
6 lib/rubytest/reporters/abstract.rb
@@ -63,7 +63,7 @@ def pass(test)
def fail(test, exception)
end
- #
+ # Report a test error.
def error(test, exception)
end
@@ -71,10 +71,6 @@ def error(test, exception)
def todo(test, exception)
end
- # Report an omitted test.
- def omit(test, exception)
- end
-
#
def end_test(test)
end
View
17 lib/rubytest/reporters/dotprogress.rb
@@ -5,6 +5,10 @@ module Test::Reporters
# Simple Dot-Progress Reporter
class Dotprogress < Abstract
+ def skip_test(unit, reason)
+ print "S".ansi(:cyan) if runner.verbose?
+ end
+
def pass(unit)
print "."
$stdout.flush
@@ -25,11 +29,6 @@ def todo(unit, exception)
$stdout.flush
end
- def omit(unit, exception)
- print "O".ansi(:cyan)
- $stdout.flush
- end
-
def end_suite(suite)
puts; puts
puts timestamp
@@ -37,12 +36,10 @@ def end_suite(suite)
if runner.verbose?
unless record[:omit].empty?
- puts "OMISSIONS\n\n"
- record[:omit].each do |test, exception|
+ puts "SKIPPED\n\n"
+ record[:skip].each do |test, reason|
puts " #{test}".ansi(:bold)
- puts " #{exception}"
- puts " #{file_and_line(exception)}"
- #puts code(exception)
+ puts " #{reason}" if String===reason
puts
end
end
View
38 lib/rubytest/runner.rb
@@ -113,6 +113,29 @@ def hard=(boolean)
@hard = !!boolean
end
+ # Instance of Advice is a special customizable observer.
+ def advice
+ @advice
+ end
+
+ # Define universal before advice.
+ def before(type, &block)
+ advice.join("begin_#{type}", &block)
+ end
+
+ # Define universal after advice. Can be used by mock libraries,
+ # for example to run mock verification.
+ def after(type, &block)
+ advice.join("end_#{type}", &block)
+ end
+
+ # Define universal upon advice.
+ #
+ # See {Advice} for valid join-points.
+ def upon(type, &block)
+ advice.join(type, &block)
+ end
+
# New Runner.
#
# @param [Array] suite
@@ -128,13 +151,15 @@ def initialize(options={}, &block)
@verbose = options[:verbose] || self.class.verbose
@hard = options[:hard] || self.class.hard
+ @advice = Advice.new
+
block.call(self) if block
end
# The reporter to use for ouput.
attr :reporter
- # Record pass, fail, error, pending and omitted tests.
+ # Record pass, fail, error and pending tests.
attr :recorder
# Array of observers, typically this just contains the recorder and
@@ -155,7 +180,8 @@ def run
@reporter = reporter_load(format)
@recorder = Recorder.new
- @observers = [@reporter, @recorder]
+
+ @observers = [advice, @recorder, @reporter]
#cd_tmp do
observers.each{ |o| o.begin_suite(suite) }
@@ -196,8 +222,8 @@ def run_thru(list)
# Run a test case.
#
def run_case(tcase)
- if tcase.respond_to?(:skip?) && tcase.skip?
- return observers.each{ |o| o.skip_case(tcase) }
+ if tcase.respond_to?(:skip?) && (reason = tcase.skip?)
+ return observers.each{ |o| o.skip_case(tcase, reason) }
end
observers.each{ |o| o.begin_case(tcase) }
@@ -219,8 +245,8 @@ def run_case(tcase)
# The test to run, must repsond to #call.
#
def run_test(test)
- if test.respond_to?(:skip?) && test.skip?
- return observers.each{ |o| o.skip_test(test) }
+ if test.respond_to?(:skip?) && (reason = test.skip?)
+ return observers.each{ |o| o.skip_test(test, reason) }
end
observers.each{ |o| o.begin_test(test) }
Please sign in to comment.
Something went wrong with that request. Please try again.