| 94 | | |
| 95 | | |
| 96 | | ### Output the specified <tt>msgs</tt> joined together to |
| 97 | | ### <tt>STDOUT</tt>. |
| 98 | | def self::message( *msgs ) |
| 99 | | $stderr.puts msgs.join('') |
| 100 | | $stderr.flush |
| 101 | | end |
| 102 | | |
| 103 | | |
| 104 | | ### Add a setup block for the current testcase |
| 105 | | def self::addSetupBlock( &block ) |
| 106 | | self.methodCounter += 1 |
| 107 | | newMethodName = "setup_#{self.methodCounter}".intern |
| 108 | | define_method( newMethodName, &block ) |
| 109 | | self.setupBlocks.push newMethodName |
| 110 | | end |
| 111 | | |
| 112 | | |
| 113 | | ### Add a teardown block for the current testcase |
| 114 | | def self::addTeardownBlock( &block ) |
| 115 | | self.methodCounter += 1 |
| 116 | | newMethodName = "teardown_#{self.methodCounter}".intern |
| 117 | | define_method( newMethodName, &block ) |
| 118 | | self.teardownBlocks.unshift newMethodName |
| 119 | | end |
| 120 | | |
| 121 | | |
| 122 | | ############################################################# |
| 123 | | ### I N S T A N C E M E T H O D S |
| 124 | | ############################################################# |
| 125 | | |
| 126 | | ### Forward-compatibility method for namechange in Test::Unit |
| 127 | | def setup( *args ) |
| 128 | | self.class.setupBlocks.each {|sblock| |
| 129 | | debugMsg "Calling setup block method #{sblock}" |
| 130 | | self.send( sblock ) |
| 131 | | } |
| 132 | | super( *args ) |
| 133 | | end |
| 134 | | alias_method :set_up, :setup |
| 135 | | |
| 136 | | |
| 137 | | ### Forward-compatibility method for namechange in Test::Unit |
| 138 | | def teardown( *args ) |
| 139 | | super( *args ) |
| 140 | | self.class.teardownBlocks.each {|tblock| |
| 141 | | debugMsg "Calling teardown block method #{tblock}" |
| 142 | | self.send( tblock ) |
| 143 | | } |
| 144 | | end |
| 145 | | alias_method :tear_down, :teardown |
| 146 | | |
| 147 | | |
| 148 | | ### Skip the current step (called from #setup) with the +reason+ given. |
| 149 | | def skip( reason=nil ) |
| 150 | | if reason |
| 151 | | msg = "Skipping %s: %s" % [ @method_name, reason ] |
| 152 | | else |
| 153 | | msg = "Skipping %s: No reason given." % @method_name |
| 154 | | end |
| 155 | | |
| 156 | | $stderr.puts( msg ) if $VERBOSE |
| 157 | | @method_name = :skipped_test |
| 158 | | end |
| 159 | | |
| 160 | | |
| 161 | | def skipped_test # :nodoc: |
| 162 | | end |
| 163 | | |
| 164 | | |
| 165 | | ### Add the specified +block+ to the code that gets executed by #setup. |
| 166 | | def addSetupBlock( &block ); self.class.addSetupBlock( &block ); end |
| 167 | | |
| 168 | | |
| 169 | | ### Add the specified +block+ to the code that gets executed by #teardown. |
| 170 | | def addTeardownBlock( &block ); self.class.addTeardownBlock( &block ); end |
| 171 | | |
| 172 | | |
| 173 | | ### Turn off the stupid 'No tests were specified' |
| 174 | | def default_test; end |
| 175 | | |
| 176 | | |
| 177 | | ### Instance alias for the like-named class method. |
| 178 | | def message( *msgs ) |
| 179 | | self.class.message( *msgs ) |
| 180 | | end |
| 181 | | |
| 182 | | |
| 183 | | ### Instance alias for the like-named class method |
| 184 | | def debugMsg( *msgs ) |
| 185 | | self.class.debugMsg( *msgs ) |
| 186 | | end |
| 187 | | |
| 188 | | |
| 189 | | ### Output a separator line made up of <tt>length</tt> of the specified |
| 190 | | ### <tt>char</tt>. |
| 191 | | def writeLine( length=75, char="-" ) |
| 192 | | $stderr.puts "\r" + (char * length ) |
| 193 | | end |
| 194 | | |
| 195 | | |
| 196 | | ### Output a header for delimiting tests |
| 197 | | def printTestHeader( desc ) |
| 198 | | return unless $VERBOSE || $DEBUG |
| 199 | | message ">>> %s <<<" % desc |
| 200 | | end |
| 201 | | |
| 202 | | |
| 203 | | ### Try to force garbage collection to start. |
| 204 | | def collectGarbage |
| 205 | | a = [] |
| 206 | | 1000.times { a << {} } |
| 207 | | a = nil |
| 208 | | GC.start |
| 209 | | end |
| 210 | | |
| 211 | | |
| 212 | | ### Output the name of the test as it's running if in verbose mode. |
| 213 | | def run( result ) |
| 214 | | $stderr.puts self.name if $VERBOSE || $DEBUG |
| 215 | | |
| 216 | | # Support debugging for individual tests |
| 217 | | olddb = nil |
| 218 | | if $DebugPattern && $DebugPattern =~ @method_name |
| 219 | | MUES::Logger::global.outputters << |
| 220 | | MUES::Logger::Outputter::create( 'file', $stderr, "STDERR" ) |
| 221 | | MUES::Logger::global.level = :debug |
| 222 | | |
| 223 | | olddb = $DEBUG |
| 224 | | $DEBUG = true |
| 225 | | end |
| 226 | | |
| 227 | | super |
| 228 | | |
| 229 | | unless olddb.nil? |
| 230 | | $DEBUG = olddb |
| 231 | | MUES::Logger::global.outputters.clear |
| 232 | | end |
| 233 | | end |
| 234 | | |
| 235 | | |
| 236 | | |
| 237 | | ############################################################# |
| 238 | | ### E X T R A A S S E R T I O N S |
| 239 | | ############################################################# |
| 240 | | |
| 241 | | ### Negative of assert_respond_to |
| 242 | | def assert_not_respond_to( obj, meth ) |
| 243 | | msg = "%s expected NOT to respond to '%s'" % |
| 244 | | [ obj.inspect, meth ] |
| 245 | | assert_block( msg ) { |
| 246 | | !obj.respond_to?( meth ) |
| 247 | | } |
| 248 | | rescue Test::Unit::AssertionFailedError => err |
| 249 | | cutframe = err.backtrace.reverse.find {|frame| |
| 250 | | /assert_not_respond_to/ =~ frame |
| 251 | | } |
| 252 | | firstIdx = (err.backtrace.rindex( cutframe )||0) + 1 |
| 253 | | Kernel::raise( err, err.message, err.backtrace[firstIdx..-1] ) |
| 254 | | end |
| 255 | | |
| 256 | | |
| 257 | | ### Assert that the instance variable specified by +sym+ of an +object+ |
| 258 | | ### is equal to the specified +value+. The '@' at the beginning of the |
| 259 | | ### +sym+ will be prepended if not present. |
| 260 | | def assert_ivar_equal( value, object, sym ) |
| 261 | | sym = "@#{sym}".intern unless /^@/ =~ sym.to_s |
| 262 | | msg = "Instance variable '%s'\n\tof <%s>\n\texpected to be <%s>\n" % |
| 263 | | [ sym, object.inspect, value.inspect ] |
| 264 | | msg += "\tbut was: <%s>" % object.instance_variable_get(sym) |
| 265 | | assert_block( msg ) { |
| 266 | | value == object.instance_variable_get(sym) |
| 267 | | } |
| 268 | | rescue Test::Unit::AssertionFailedError => err |
| 269 | | cutframe = err.backtrace.reverse.find {|frame| |
| 270 | | /assert_ivar_equal/ =~ frame |
| 271 | | } |
| 272 | | firstIdx = (err.backtrace.rindex( cutframe )||0) + 1 |
| 273 | | Kernel::raise( err, err.message, err.backtrace[firstIdx..-1] ) |
| 274 | | end |
| 275 | | |
| 276 | | |
| 277 | | ### Assert that the specified +object+ has an instance variable which |
| 278 | | ### matches the specified +sym+. The '@' at the beginning of the +sym+ |
| 279 | | ### will be prepended if not present. |
| 280 | | def assert_has_ivar( sym, object ) |
| 281 | | sym = "@#{sym}" unless /^@/ =~ sym.to_s |
| 282 | | msg = "Object <%s> expected to have an instance variable <%s>" % |
| 283 | | [ object.inspect, sym ] |
| 284 | | assert_block( msg ) { |
| 285 | | object.instance_variables.include?( sym.to_s ) |
| 286 | | } |
| 287 | | rescue Test::Unit::AssertionFailedError => err |
| 288 | | cutframe = err.backtrace.reverse.find {|frame| |
| 289 | | /assert_has_ivar/ =~ frame |
| 290 | | } |
| 291 | | firstIdx = (err.backtrace.rindex( cutframe )||0) + 1 |
| 292 | | Kernel::raise( err, err.message, err.backtrace[firstIdx..-1] ) |
| 293 | | end |
| 294 | | |
| 295 | | |
| 296 | | ### Override the stupid deprecated #assert_not_nil so when it |
| 297 | | ### disappears, code doesn't break. |
| 298 | | def assert_not_nil( obj, msg=nil ) |
| 299 | | msg ||= "<%p> expected to not be nil." % obj |
| 300 | | assert_block( msg ) { !obj.nil? } |
| 301 | | rescue Test::Unit::AssertionFailedError => err |
| 302 | | cutframe = err.backtrace.reverse.find {|frame| |
| 303 | | /assert_not_nil/ =~ frame |
| 304 | | } |
| 305 | | firstIdx = (err.backtrace.rindex( cutframe )||0) + 1 |
| 306 | | Kernel::raise( err, err.message, err.backtrace[firstIdx..-1] ) |
| 307 | | end |
| 308 | | |
| | 201 | end |
| | 202 | |
| | 203 | |
| | 204 | |
| | 205 | ############################################################# |
| | 206 | ### E X T R A A S S E R T I O N S |
| | 207 | ############################################################# |
| | 208 | |
| | 209 | ### Negative of assert_respond_to |
| | 210 | def assert_not_respond_to( obj, meth ) |
| | 211 | msg = "%s expected NOT to respond to '%s'" % |
| | 212 | [ obj.inspect, meth ] |
| | 213 | assert_block( msg ) { |
| | 214 | !obj.respond_to?( meth ) |
| | 215 | } |
| | 216 | rescue Test::Unit::AssertionFailedError => err |
| | 217 | cutframe = err.backtrace.reverse.find {|frame| |
| | 218 | /assert_not_respond_to/ =~ frame |
| | 219 | } |
| | 220 | firstIdx = (err.backtrace.rindex( cutframe )||0) + 1 |
| | 221 | Kernel::raise( err, err.message, err.backtrace[firstIdx..-1] ) |
| | 222 | end |
| | 223 | |
| | 224 | |
| | 225 | ### Assert that the instance variable specified by +sym+ of an +object+ |
| | 226 | ### is equal to the specified +value+. The '@' at the beginning of the |
| | 227 | ### +sym+ will be prepended if not present. |
| | 228 | def assert_ivar_equal( value, object, sym ) |
| | 229 | sym = "@#{sym}".intern unless /^@/ =~ sym.to_s |
| | 230 | msg = "Instance variable '%s'\n\tof <%s>\n\texpected to be <%s>\n" % |
| | 231 | [ sym, object.inspect, value.inspect ] |
| | 232 | msg += "\tbut was: <%s>" % object.instance_variable_get(sym) |
| | 233 | assert_block( msg ) { |
| | 234 | value == object.instance_variable_get(sym) |
| | 235 | } |
| | 236 | rescue Test::Unit::AssertionFailedError => err |
| | 237 | cutframe = err.backtrace.reverse.find {|frame| |
| | 238 | /assert_ivar_equal/ =~ frame |
| | 239 | } |
| | 240 | firstIdx = (err.backtrace.rindex( cutframe )||0) + 1 |
| | 241 | Kernel::raise( err, err.message, err.backtrace[firstIdx..-1] ) |
| | 242 | end |
| | 243 | |
| | 244 | |
| | 245 | ### Assert that the specified +object+ has an instance variable which |
| | 246 | ### matches the specified +sym+. The '@' at the beginning of the +sym+ |
| | 247 | ### will be prepended if not present. |
| | 248 | def assert_has_ivar( sym, object ) |
| | 249 | sym = "@#{sym}" unless /^@/ =~ sym.to_s |
| | 250 | msg = "Object <%s> expected to have an instance variable <%s>" % |
| | 251 | [ object.inspect, sym ] |
| | 252 | assert_block( msg ) { |
| | 253 | object.instance_variables.include?( sym.to_s ) |
| | 254 | } |
| | 255 | rescue Test::Unit::AssertionFailedError => err |
| | 256 | cutframe = err.backtrace.reverse.find {|frame| |
| | 257 | /assert_has_ivar/ =~ frame |
| | 258 | } |
| | 259 | firstIdx = (err.backtrace.rindex( cutframe )||0) + 1 |
| | 260 | Kernel::raise( err, err.message, err.backtrace[firstIdx..-1] ) |
| | 261 | end |
| | 262 | |
| | 263 | |
| | 264 | ### Override the stupid deprecated #assert_not_nil so when it |
| | 265 | ### disappears, code doesn't break. |
| | 266 | def assert_not_nil( obj, msg=nil ) |
| | 267 | msg ||= "<%p> expected to not be nil." % obj |
| | 268 | assert_block( msg ) { !obj.nil? } |
| | 269 | rescue Test::Unit::AssertionFailedError => err |
| | 270 | cutframe = err.backtrace.reverse.find {|frame| |
| | 271 | /assert_not_nil/ =~ frame |
| | 272 | } |
| | 273 | firstIdx = (err.backtrace.rindex( cutframe )||0) + 1 |
| | 274 | Kernel::raise( err, err.message, err.backtrace[firstIdx..-1] ) |
| | 275 | end |