1require 'minitest/unit' 2require 'pp' 3 4module Test 5 module Unit 6 module Assertions 7 include MiniTest::Assertions 8 9 def mu_pp(obj) #:nodoc: 10 obj.pretty_inspect.chomp 11 end 12 13 MINI_DIR = File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), "minitest") #:nodoc: 14 15 UNASSIGNED = Object.new # :nodoc: 16 17 # :call-seq: 18 # assert( test, failure_message = UNASSIGNED ) 19 # 20 #Tests if +test+ is true. 21 # 22 #+msg+ may be a String or a Proc. If +msg+ is a String, it will be used 23 #as the failure message. Otherwise, the result of calling +msg+ will be 24 #used as the message if the assertion fails. 25 # 26 #If no +msg+ is given, a default message will be used. 27 # 28 # assert(false, "This was expected to be true") 29 def assert(test, msg = UNASSIGNED) 30 case msg 31 when UNASSIGNED 32 msg = nil 33 when String, Proc 34 else 35 bt = caller.reject { |s| s.rindex(MINI_DIR, 0) } 36 raise ArgumentError, "assertion message must be String or Proc, but #{msg.class} was given.", bt 37 end 38 super 39 end 40 41 # :call-seq: 42 # assert_block( failure_message = nil ) 43 # 44 #Tests the result of the given block. If the block does not return true, 45 #the assertion will fail. The optional +failure_message+ argument is the same as in 46 #Assertions#assert. 47 # 48 # assert_block do 49 # [1, 2, 3].any? { |num| num < 1 } 50 # end 51 def assert_block(*msgs) 52 assert yield, *msgs 53 end 54 55 # :call-seq: 56 # assert_raise( *args, &block ) 57 # 58 #Tests if the given block raises an exception. Acceptable exception 59 #types maye be given as optional arguments. If the last argument is a 60 #String, it will be used as the error message. 61 # 62 # assert_raise do #Fails, no Exceptions are raised 63 # end 64 # 65 # assert_raise NameError do 66 # puts x #Raises NameError, so assertion succeeds 67 # end 68 def assert_raise(*args, &b) 69 assert_raises(*args, &b) 70 end 71 72 # :call-seq: 73 # assert_nothing_raised( *args, &block ) 74 # 75 #If any exceptions are given as arguments, the assertion will 76 #fail if one of those exceptions are raised. Otherwise, the test fails 77 #if any exceptions are raised. 78 # 79 #The final argument may be a failure message. 80 # 81 # assert_nothing_raised RuntimeError do 82 # raise Exception #Assertion passes, Exception is not a RuntimeError 83 # end 84 # 85 # assert_nothing_raised do 86 # raise Exception #Assertion fails 87 # end 88 def assert_nothing_raised(*args) 89 self._assertions += 1 90 if Module === args.last 91 msg = nil 92 else 93 msg = args.pop 94 end 95 begin 96 line = __LINE__; yield 97 rescue MiniTest::Skip 98 raise 99 rescue Exception => e 100 bt = e.backtrace 101 as = e.instance_of?(MiniTest::Assertion) 102 if as 103 ans = /\A#{Regexp.quote(__FILE__)}:#{line}:in /o 104 bt.reject! {|ln| ans =~ ln} 105 end 106 if ((args.empty? && !as) || 107 args.any? {|a| a.instance_of?(Module) ? e.is_a?(a) : e.class == a }) 108 msg = message(msg) { "Exception raised:\n<#{mu_pp(e)}>" } 109 raise MiniTest::Assertion, msg.call, bt 110 else 111 raise 112 end 113 end 114 nil 115 end 116 117 # :call-seq: 118 # assert_nothing_thrown( failure_message = nil, &block ) 119 # 120 #Fails if the given block uses a call to Kernel#throw. 121 # 122 #An optional failure message may be provided as the final argument. 123 # 124 # assert_nothing_thrown "Something was thrown!" do 125 # throw :problem? 126 # end 127 def assert_nothing_thrown(msg=nil) 128 begin 129 yield 130 rescue ArgumentError => error 131 raise error if /\Auncaught throw (.+)\z/m !~ error.message 132 msg = message(msg) { "<#{$1}> was thrown when nothing was expected" } 133 flunk(msg) 134 end 135 assert(true, "Expected nothing to be thrown") 136 end 137 138 # :call-seq: 139 # assert_equal( expected, actual, failure_message = nil ) 140 # 141 #Tests if +expected+ is equal to +actual+. 142 # 143 #An optional failure message may be provided as the final argument. 144 def assert_equal(exp, act, msg = nil) 145 msg = message(msg) { 146 exp_str = mu_pp(exp) 147 act_str = mu_pp(act) 148 exp_comment = '' 149 act_comment = '' 150 if exp_str == act_str 151 if (exp.is_a?(String) && act.is_a?(String)) || 152 (exp.is_a?(Regexp) && act.is_a?(Regexp)) 153 exp_comment = " (#{exp.encoding})" 154 act_comment = " (#{act.encoding})" 155 elsif exp.is_a?(Float) && act.is_a?(Float) 156 exp_str = "%\#.#{Float::DIG+2}g" % exp 157 act_str = "%\#.#{Float::DIG+2}g" % act 158 elsif exp.is_a?(Time) && act.is_a?(Time) 159 if exp.subsec * 1000_000_000 == exp.nsec 160 exp_comment = " (#{exp.nsec}[ns])" 161 else 162 exp_comment = " (subsec=#{exp.subsec})" 163 end 164 if act.subsec * 1000_000_000 == act.nsec 165 act_comment = " (#{act.nsec}[ns])" 166 else 167 act_comment = " (subsec=#{act.subsec})" 168 end 169 elsif exp.class != act.class 170 # a subclass of Range, for example. 171 exp_comment = " (#{exp.class})" 172 act_comment = " (#{act.class})" 173 end 174 elsif !Encoding.compatible?(exp_str, act_str) 175 if exp.is_a?(String) && act.is_a?(String) 176 exp_str = exp.dump 177 act_str = act.dump 178 exp_comment = " (#{exp.encoding})" 179 act_comment = " (#{act.encoding})" 180 else 181 exp_str = exp_str.dump 182 act_str = act_str.dump 183 end 184 end 185 "<#{exp_str}>#{exp_comment} expected but was\n<#{act_str}>#{act_comment}" 186 } 187 assert(exp == act, msg) 188 end 189 190 # :call-seq: 191 # assert_not_nil( expression, failure_message = nil ) 192 # 193 #Tests if +expression+ is not nil. 194 # 195 #An optional failure message may be provided as the final argument. 196 def assert_not_nil(exp, msg=nil) 197 msg = message(msg) { "<#{mu_pp(exp)}> expected to not be nil" } 198 assert(!exp.nil?, msg) 199 end 200 201 # :call-seq: 202 # assert_not_equal( expected, actual, failure_message = nil ) 203 # 204 #Tests if +expected+ is not equal to +actual+. 205 # 206 #An optional failure message may be provided as the final argument. 207 def assert_not_equal(exp, act, msg=nil) 208 msg = message(msg) { "<#{mu_pp(exp)}> expected to be != to\n<#{mu_pp(act)}>" } 209 assert(exp != act, msg) 210 end 211 212 # :call-seq: 213 # assert_no_match( regexp, string, failure_message = nil ) 214 # 215 #Tests if the given Regexp does not match a given String. 216 # 217 #An optional failure message may be provided as the final argument. 218 def assert_no_match(regexp, string, msg=nil) 219 assert_instance_of(Regexp, regexp, "The first argument to assert_no_match should be a Regexp.") 220 self._assertions -= 1 221 msg = message(msg) { "<#{mu_pp(regexp)}> expected to not match\n<#{mu_pp(string)}>" } 222 assert(regexp !~ string, msg) 223 end 224 225 # :call-seq: 226 # assert_not_same( expected, actual, failure_message = nil ) 227 # 228 #Tests if +expected+ is not the same object as +actual+. 229 #This test uses Object#equal? to test equality. 230 # 231 #An optional failure message may be provided as the final argument. 232 # 233 # assert_not_same("x", "x") #Succeeds 234 def assert_not_same(expected, actual, message="") 235 msg = message(msg) { build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__) } 236<?> 237with id <?> expected to not be equal\\? to 238<?> 239with id <?>. 240EOT 241 assert(!actual.equal?(expected), msg) 242 end 243 244 # :call-seq: 245 # assert_respond_to( object, method, failure_message = nil ) 246 # 247 #Tests if the given Object responds to +method+. 248 # 249 #An optional failure message may be provided as the final argument. 250 # 251 # assert_respond_to("hello", :reverse) #Succeeds 252 # assert_respond_to("hello", :does_not_exist) #Fails 253 def assert_respond_to obj, (meth, priv), msg = nil 254 if priv 255 msg = message(msg) { 256 "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}#{" privately" if priv}" 257 } 258 return assert obj.respond_to?(meth, priv), msg 259 end 260 #get rid of overcounting 261 super if !caller[0].rindex(MINI_DIR, 0) || !obj.respond_to?(meth) 262 end 263 264 # :call-seq: 265 # assert_send( +send_array+, failure_message = nil ) 266 # 267 # Passes if the method send returns a true value. 268 # 269 # +send_array+ is composed of: 270 # * A receiver 271 # * A method 272 # * Arguments to the method 273 # 274 # Example: 275 # assert_send([[1, 2], :member?, 1]) # -> pass 276 # assert_send([[1, 2], :member?, 4]) # -> fail 277 def assert_send send_ary, m = nil 278 recv, msg, *args = send_ary 279 m = message(m) { 280 if args.empty? 281 argsstr = "" 282 else 283 (argsstr = mu_pp(args)).sub!(/\A\[(.*)\]\z/m, '(\1)') 284 end 285 "Expected #{mu_pp(recv)}.#{msg}#{argsstr} to return true" 286 } 287 assert recv.__send__(msg, *args), m 288 end 289 290 # :call-seq: 291 # assert_not_send( +send_array+, failure_message = nil ) 292 # 293 # Passes if the method send doesn't return a true value. 294 # 295 # +send_array+ is composed of: 296 # * A receiver 297 # * A method 298 # * Arguments to the method 299 # 300 # Example: 301 # assert_not_send([[1, 2], :member?, 1]) # -> fail 302 # assert_not_send([[1, 2], :member?, 4]) # -> pass 303 def assert_not_send send_ary, m = nil 304 recv, msg, *args = send_ary 305 m = message(m) { 306 if args.empty? 307 argsstr = "" 308 else 309 (argsstr = mu_pp(args)).sub!(/\A\[(.*)\]\z/m, '(\1)') 310 end 311 "Expected #{mu_pp(recv)}.#{msg}#{argsstr} to return false" 312 } 313 assert !recv.__send__(msg, *args), m 314 end 315 316 ms = instance_methods(true).map {|sym| sym.to_s } 317 ms.grep(/\Arefute_/) do |m| 318 mname = ('assert_not_' << m.to_s[/.*?_(.*)/, 1]) 319 alias_method(mname, m) unless ms.include? mname 320 end 321 alias assert_include assert_includes 322 alias assert_not_include assert_not_includes 323 324 def build_message(head, template=nil, *arguments) #:nodoc: 325 template &&= template.chomp 326 template.gsub(/\G((?:[^\\]|\\.)*?)(\\)?\?/) { $1 + ($2 ? "?" : mu_pp(arguments.shift)) } 327 end 328 end 329 end 330end 331