instiki/vendor/bluecloth-1.0.0/tests/bctestcase.rb
2005-01-15 20:26:54 +00:00

275 lines
7.2 KiB
Ruby
Executable file

#!/usr/bin/ruby
#
# This is an abstract test case class for building Test::Unit unit tests for the
# BlueCloth module. It consolidates most of the maintenance work that must be
# done to build a test file by adjusting the $LOAD_PATH appropriately, as well
# as adding some other useful methods that make building, maintaining, and using
# the tests for programming much easier (IMHO). See the docs for Test::Unit for
# more info on the particulars of unit testing.
#
# == Synopsis
#
# # Allow the test to be run from anywhere:
# if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
# basedir = File::dirname( __FILE__ )
# require File::join( basedir, 'bctestcase' )
# end
#
# class MySomethingTest < BlueCloth::TestCase
# def setup
# super()
# @foo = 'bar'
# end
#
# def test_00_something
# obj = nil
# assert_nothing_raised { obj = MySomething::new }
# assert_instance_of MySomething, obj
# assert_respond_to :myMethod, obj
# end
#
# end
#
# == Rcsid
#
# $Id: bctestcase.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
#
# == Authors
#
# * Michael Granger <ged@FaerieMUD.org>
#
#:include: COPYRIGHT
#
#---
#
# Please see the file COPYRIGHT in the 'docs' directory for licensing details.
#
$DebugPattern ||= nil
begin
basedir = File::dirname( File::dirname(__FILE__) )
unless $LOAD_PATH.include?( "#{basedir}/lib" )
$LOAD_PATH.unshift "#{basedir}/lib"
end
end
require "test/unit"
require "bluecloth"
class BlueCloth
### The abstract base class for BlueCloth test cases.
class TestCase < Test::Unit::TestCase
@methodCounter = 0
@setupBlocks = []
@teardownBlocks = []
class << self
attr_accessor :methodCounter, :setupBlocks, :teardownBlocks
end
### Inheritance callback -- adds @setupBlocks and @teardownBlocks ivars
### and accessors to the inheriting class.
def self::inherited( klass )
klass.module_eval {
@setupBlocks = []
@teardownBlocks = []
class << self
attr_accessor :setupBlocks, :teardownBlocks
end
}
klass.methodCounter = 0
end
### Output the specified <tt>msgs</tt> joined together to
### <tt>STDERR</tt> if <tt>$DEBUG</tt> is set.
def self::debugMsg( *msgs )
return unless $DEBUG
self.message "DEBUG>>> %s" % msgs.join('')
end
### Output the specified <tt>msgs</tt> joined together to
### <tt>STDOUT</tt>.
def self::message( *msgs )
$stderr.puts msgs.join('')
$stderr.flush
end
### Add a setup block for the current testcase
def self::addSetupBlock( &block )
self.methodCounter += 1
newMethodName = "setup_#{self.methodCounter}".intern
define_method( newMethodName, &block )
self.setupBlocks.push newMethodName
end
### Add a teardown block for the current testcase
def self::addTeardownBlock( &block )
self.methodCounter += 1
newMethodName = "teardown_#{self.methodCounter}".intern
define_method( newMethodName, &block )
self.teardownBlocks.unshift newMethodName
end
#############################################################
### I N S T A N C E M E T H O D S
#############################################################
### A dummy test method to allow this Test::Unit::TestCase to be
### subclassed without complaining about the lack of tests.
def test_0_dummy
end
### Forward-compatibility method for namechange in Test::Unit
def setup( *args )
self.class.setupBlocks.each {|sblock|
debugMsg "Calling setup block method #{sblock}"
self.send( sblock )
}
super( *args )
end
alias_method :set_up, :setup
### Forward-compatibility method for namechange in Test::Unit
def teardown( *args )
super( *args )
self.class.teardownBlocks.each {|tblock|
debugMsg "Calling teardown block method #{tblock}"
self.send( tblock )
}
end
alias_method :tear_down, :teardown
### Skip the current step (called from #setup) with the +reason+ given.
def skip( reason=nil )
if reason
msg = "Skipping %s: %s" % [ @method_name, reason ]
else
msg = "Skipping %s: No reason given." % @method_name
end
$stderr.puts( msg ) if $VERBOSE
@method_name = :skipped_test
end
def skipped_test # :nodoc:
end
### Add the specified +block+ to the code that gets executed by #setup.
def addSetupBlock( &block ); self.class.addSetupBlock( &block ); end
### Add the specified +block+ to the code that gets executed by #teardown.
def addTeardownBlock( &block ); self.class.addTeardownBlock( &block ); end
### Instance alias for the like-named class method.
def message( *msgs )
self.class.message( *msgs )
end
### Instance alias for the like-named class method
def debugMsg( *msgs )
self.class.debugMsg( *msgs )
end
### Output a separator line made up of <tt>length</tt> of the specified
### <tt>char</tt>.
def writeLine( length=75, char="-" )
$stderr.puts "\r" + (char * length )
end
### Output a header for delimiting tests
def printTestHeader( desc )
return unless $VERBOSE || $DEBUG
message ">>> %s <<<" % desc
end
### Try to force garbage collection to start.
def collectGarbage
a = []
1000.times { a << {} }
a = nil
GC.start
end
### Output the name of the test as it's running if in verbose mode.
def run( result )
$stderr.puts self.name if $VERBOSE || $DEBUG
# Support debugging for individual tests
olddb = nil
if $DebugPattern && $DebugPattern =~ @method_name
olddb = $DEBUG
$DEBUG = true
end
super
$DEBUG = olddb unless olddb.nil?
end
#############################################################
### E X T R A A S S E R T I O N S
#############################################################
### Negative of assert_respond_to
def assert_not_respond_to( obj, meth )
msg = "%s expected NOT to respond to '%s'" %
[ obj.inspect, meth ]
assert_block( msg ) {
!obj.respond_to?( meth )
}
end
### Assert that the instance variable specified by +sym+ of an +object+
### is equal to the specified +value+. The '@' at the beginning of the
### +sym+ will be prepended if not present.
def assert_ivar_equal( value, object, sym )
sym = "@#{sym}".intern unless /^@/ =~ sym.to_s
msg = "Instance variable '%s'\n\tof <%s>\n\texpected to be <%s>\n" %
[ sym, object.inspect, value.inspect ]
msg += "\tbut was: <%s>" % object.instance_variable_get(sym)
assert_block( msg ) {
value == object.instance_variable_get(sym)
}
end
### Assert that the specified +object+ has an instance variable which
### matches the specified +sym+. The '@' at the beginning of the +sym+
### will be prepended if not present.
def assert_has_ivar( sym, object )
sym = "@#{sym}" unless /^@/ =~ sym.to_s
msg = "Object <%s> expected to have an instance variable <%s>" %
[ object.inspect, sym ]
assert_block( msg ) {
object.instance_variables.include?( sym.to_s )
}
end
end # class TestCase
end # class BlueCloth