PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/minitest/unit.rb

https://github.com/nazy/ruby
Ruby | 816 lines | 488 code | 172 blank | 156 comment | 37 complexity | f2d4765920dfe8e34d53816476c58682 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0, 0BSD, Unlicense
  1. ############################################################
  2. # This file is imported from a different project.
  3. # DO NOT make modifications in this repo.
  4. # File a patch instead and assign it to Ryan Davis
  5. ############################################################
  6. require 'optparse'
  7. ##
  8. # Minimal (mostly drop-in) replacement for test-unit.
  9. module MiniTest
  10. ##
  11. # Assertion base class
  12. class Assertion < Exception; end
  13. ##
  14. # Assertion raised when skipping a test
  15. class Skip < Assertion; end
  16. file = if RUBY_VERSION =~ /^1\.9/ then # bt's expanded, but __FILE__ isn't :(
  17. File.expand_path __FILE__
  18. elsif __FILE__ =~ /^[^\.]/ then # assume both relative
  19. require 'pathname'
  20. pwd = Pathname.new Dir.pwd
  21. pn = Pathname.new File.expand_path(__FILE__)
  22. pn = File.join(".", pn.relative_path_from(pwd)) unless pn.relative?
  23. pn.to_s
  24. else # assume both are expanded
  25. __FILE__
  26. end
  27. # './lib' in project dir, or '/usr/local/blahblah' if installed
  28. MINI_DIR = File.dirname(File.dirname(file)) # :nodoc:
  29. def self.filter_backtrace bt # :nodoc:
  30. return ["No backtrace"] unless bt
  31. new_bt = []
  32. bt.each do |line|
  33. break if line.rindex(MINI_DIR, 0)
  34. new_bt << line
  35. end
  36. new_bt = bt.reject { |line| line.rindex(MINI_DIR, 0) } if new_bt.empty?
  37. new_bt = bt.dup if new_bt.empty?
  38. new_bt
  39. end
  40. ##
  41. # MiniTest Assertions. All assertion methods accept a +msg+ which is
  42. # printed if the assertion fails.
  43. module Assertions
  44. ##
  45. # mu_pp gives a human-readable version of +obj+. By default #inspect is
  46. # called. You can override this to use #pretty_print if you want.
  47. def mu_pp obj
  48. s = obj.inspect
  49. s = s.force_encoding(Encoding.default_external) if defined? Encoding
  50. s
  51. end
  52. def _assertions= n # :nodoc:
  53. @_assertions = n
  54. end
  55. def _assertions # :nodoc:
  56. @_assertions ||= 0
  57. end
  58. ##
  59. # Fails unless +test+ is a true value.
  60. def assert test, msg = nil
  61. msg ||= "Failed assertion, no message given."
  62. self._assertions += 1
  63. unless test then
  64. msg = msg.call if Proc === msg
  65. raise MiniTest::Assertion, msg
  66. end
  67. true
  68. end
  69. ##
  70. # Fails unless the block returns a true value.
  71. def assert_block msg = nil
  72. msg = message(msg) { "Expected block to return true value" }
  73. assert yield, msg
  74. end
  75. ##
  76. # Fails unless +obj+ is empty.
  77. def assert_empty obj, msg = nil
  78. msg = message(msg) { "Expected #{obj.inspect} to be empty" }
  79. assert_respond_to obj, :empty?
  80. assert obj.empty?, msg
  81. end
  82. ##
  83. # Fails unless <tt>exp == act</tt>.
  84. #
  85. # For floats use assert_in_delta
  86. def assert_equal exp, act, msg = nil
  87. msg = message(msg) { "Expected #{mu_pp(exp)}, not #{mu_pp(act)}" }
  88. assert(exp == act, msg)
  89. end
  90. ##
  91. # For comparing Floats. Fails unless +exp+ and +act+ are within +delta+
  92. # of each other.
  93. #
  94. # assert_in_delta Math::PI, (22.0 / 7.0), 0.01
  95. def assert_in_delta exp, act, delta = 0.001, msg = nil
  96. n = (exp - act).abs
  97. msg = message(msg) { "Expected #{exp} - #{act} (#{n}) to be < #{delta}" }
  98. assert delta >= n, msg
  99. end
  100. ##
  101. # For comparing Floats. Fails unless +exp+ and +act+ have a relative
  102. # error less than +epsilon+.
  103. def assert_in_epsilon a, b, epsilon = 0.001, msg = nil
  104. assert_in_delta a, b, [a, b].min * epsilon, msg
  105. end
  106. ##
  107. # Fails unless +collection+ includes +obj+.
  108. def assert_includes collection, obj, msg = nil
  109. msg = message(msg) {
  110. "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}"
  111. }
  112. assert_respond_to collection, :include?
  113. assert collection.include?(obj), msg
  114. end
  115. ##
  116. # Fails unless +obj+ is an instace of +cls+.
  117. def assert_instance_of cls, obj, msg = nil
  118. msg = message(msg) {
  119. "Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}"
  120. }
  121. assert obj.instance_of?(cls), msg
  122. end
  123. ##
  124. # Fails unless +obj+ is a kind of +cls+.
  125. def assert_kind_of cls, obj, msg = nil # TODO: merge with instance_of
  126. msg = message(msg) {
  127. "Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" }
  128. assert obj.kind_of?(cls), msg
  129. end
  130. ##
  131. # Fails unless +exp+ is <tt>=~</tt> +act+.
  132. def assert_match exp, act, msg = nil
  133. msg = message(msg) { "Expected #{mu_pp(exp)} to match #{mu_pp(act)}" }
  134. assert_respond_to act, :"=~"
  135. exp = /#{Regexp.escape exp}/ if String === exp && String === act
  136. assert exp =~ act, msg
  137. end
  138. ##
  139. # Fails unless +obj+ is nil
  140. def assert_nil obj, msg = nil
  141. msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" }
  142. assert obj.nil?, msg
  143. end
  144. ##
  145. # For testing equality operators and so-forth.
  146. #
  147. # assert_operator 5, :<=, 4
  148. def assert_operator o1, op, o2, msg = nil
  149. msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" }
  150. assert o1.__send__(op, o2), msg
  151. end
  152. ##
  153. # Fails if stdout or stderr do not output the expected results.
  154. # Pass in nil if you don't care about that streams output. Pass in
  155. # "" if you require it to be silent.
  156. #
  157. # See also: #assert_silent
  158. def assert_output stdout = nil, stderr = nil
  159. out, err = capture_io do
  160. yield
  161. end
  162. x = assert_equal stdout, out, "In stdout" if stdout
  163. y = assert_equal stderr, err, "In stderr" if stderr
  164. (!stdout || x) && (!stderr || y)
  165. end
  166. ##
  167. # Fails unless the block raises one of +exp+
  168. def assert_raises *exp
  169. msg = String === exp.last ? exp.pop : nil
  170. msg = msg.to_s + "\n" if msg
  171. should_raise = false
  172. begin
  173. yield
  174. should_raise = true
  175. rescue MiniTest::Skip => e
  176. details = "#{msg}#{mu_pp(exp)} exception expected, not"
  177. if exp.include? MiniTest::Skip then
  178. return e
  179. else
  180. raise e
  181. end
  182. rescue Exception => e
  183. details = "#{msg}#{mu_pp(exp)} exception expected, not"
  184. assert(exp.any? { |ex|
  185. ex.instance_of?(Module) ? e.kind_of?(ex) : ex == e.class
  186. }, exception_details(e, details))
  187. return e
  188. end
  189. exp = exp.first if exp.size == 1
  190. flunk "#{msg}#{mu_pp(exp)} expected but nothing was raised." if
  191. should_raise
  192. end
  193. ##
  194. # Fails unless +obj+ responds to +meth+.
  195. def assert_respond_to obj, meth, msg = nil
  196. msg = message(msg) {
  197. "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}"
  198. }
  199. assert obj.respond_to?(meth), msg
  200. end
  201. ##
  202. # Fails unless +exp+ and +act+ are #equal?
  203. def assert_same exp, act, msg = nil
  204. msg = message(msg) {
  205. data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
  206. "Expected %s (oid=%d) to be the same as %s (oid=%d)" % data
  207. }
  208. assert exp.equal?(act), msg
  209. end
  210. ##
  211. # +send_ary+ is a receiver, message and arguments.
  212. #
  213. # Fails unless the call returns a true value
  214. # TODO: I should prolly remove this from specs
  215. def assert_send send_ary, m = nil
  216. recv, msg, *args = send_ary
  217. m = message(m) {
  218. "Expected #{mu_pp(recv)}.#{msg}(*#{mu_pp(args)}) to return true" }
  219. assert recv.__send__(msg, *args), m
  220. end
  221. ##
  222. # Fails if the block outputs anything to stderr or stdout.
  223. #
  224. # See also: #assert_output
  225. def assert_silent
  226. assert_output "", "" do
  227. yield
  228. end
  229. end
  230. ##
  231. # Fails unless the block throws +sym+
  232. def assert_throws sym, msg = nil
  233. default = "Expected #{mu_pp(sym)} to have been thrown"
  234. caught = true
  235. catch(sym) do
  236. begin
  237. yield
  238. rescue ArgumentError => e # 1.9 exception
  239. default += ", not #{e.message.split(/ /).last}"
  240. rescue NameError => e # 1.8 exception
  241. default += ", not #{e.name.inspect}"
  242. end
  243. caught = false
  244. end
  245. assert caught, message(msg) { default }
  246. end
  247. ##
  248. # Captures $stdout and $stderr into strings:
  249. #
  250. # out, err = capture_io do
  251. # warn "You did a bad thing"
  252. # end
  253. #
  254. # assert_match %r%bad%, err
  255. def capture_io
  256. require 'stringio'
  257. orig_stdout, orig_stderr = $stdout, $stderr
  258. captured_stdout, captured_stderr = StringIO.new, StringIO.new
  259. $stdout, $stderr = captured_stdout, captured_stderr
  260. yield
  261. return captured_stdout.string, captured_stderr.string
  262. ensure
  263. $stdout = orig_stdout
  264. $stderr = orig_stderr
  265. end
  266. ##
  267. # Returns details for exception +e+
  268. def exception_details e, msg
  269. "#{msg}\nClass: <#{e.class}>\nMessage: <#{e.message.inspect}>\n---Backtrace---\n#{MiniTest::filter_backtrace(e.backtrace).join("\n")}\n---------------"
  270. end
  271. ##
  272. # Fails with +msg+
  273. def flunk msg = nil
  274. msg ||= "Epic Fail!"
  275. assert false, msg
  276. end
  277. ##
  278. # Returns a proc that will output +msg+ along with the default message.
  279. def message msg = nil, &default
  280. proc {
  281. if msg then
  282. msg = msg.to_s unless String === msg
  283. msg += '.' unless msg.empty?
  284. msg += "\n#{default.call}."
  285. msg.strip
  286. else
  287. "#{default.call}."
  288. end
  289. }
  290. end
  291. ##
  292. # used for counting assertions
  293. def pass msg = nil
  294. assert true
  295. end
  296. ##
  297. # Fails if +test+ is a true value
  298. def refute test, msg = nil
  299. msg ||= "Failed refutation, no message given"
  300. not assert(! test, msg)
  301. end
  302. ##
  303. # Fails if +obj+ is empty.
  304. def refute_empty obj, msg = nil
  305. msg = message(msg) { "Expected #{obj.inspect} to not be empty" }
  306. assert_respond_to obj, :empty?
  307. refute obj.empty?, msg
  308. end
  309. ##
  310. # Fails if <tt>exp == act</tt>.
  311. #
  312. # For floats use refute_in_delta.
  313. def refute_equal exp, act, msg = nil
  314. msg = message(msg) {
  315. "Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}"
  316. }
  317. refute exp == act, msg
  318. end
  319. ##
  320. # For comparing Floats. Fails if +exp+ is within +delta+ of +act+
  321. #
  322. # refute_in_delta Math::PI, (22.0 / 7.0)
  323. def refute_in_delta exp, act, delta = 0.001, msg = nil
  324. n = (exp - act).abs
  325. msg = message(msg) {
  326. "Expected #{exp} - #{act} (#{n}) to not be < #{delta}"
  327. }
  328. refute delta > n, msg
  329. end
  330. ##
  331. # For comparing Floats. Fails if +exp+ and +act+ have a relative error
  332. # less than +epsilon+.
  333. def refute_in_epsilon a, b, epsilon = 0.001, msg = nil
  334. refute_in_delta a, b, a * epsilon, msg
  335. end
  336. ##
  337. # Fails if +collection+ includes +obj+
  338. def refute_includes collection, obj, msg = nil
  339. msg = message(msg) {
  340. "Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}"
  341. }
  342. assert_respond_to collection, :include?
  343. refute collection.include?(obj), msg
  344. end
  345. ##
  346. # Fails if +obj+ is an instance of +cls+
  347. def refute_instance_of cls, obj, msg = nil
  348. msg = message(msg) {
  349. "Expected #{mu_pp(obj)} to not be an instance of #{cls}"
  350. }
  351. refute obj.instance_of?(cls), msg
  352. end
  353. ##
  354. # Fails if +obj+ is a kind of +cls+
  355. def refute_kind_of cls, obj, msg = nil # TODO: merge with instance_of
  356. msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" }
  357. refute obj.kind_of?(cls), msg
  358. end
  359. ##
  360. # Fails if +exp+ <tt>=~</tt> +act+
  361. def refute_match exp, act, msg = nil
  362. msg = message(msg) { "Expected #{mu_pp(exp)} to not match #{mu_pp(act)}" }
  363. assert_respond_to act, :"=~"
  364. exp = (/#{Regexp.escape exp}/) if String === exp and String === act
  365. refute exp =~ act, msg
  366. end
  367. ##
  368. # Fails if +obj+ is nil.
  369. def refute_nil obj, msg = nil
  370. msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" }
  371. refute obj.nil?, msg
  372. end
  373. ##
  374. # Fails if +o1+ is not +op+ +o2+ nil. eg:
  375. #
  376. # refute_operator 1, :>, 2 #=> pass
  377. # refute_operator 1, :<, 2 #=> fail
  378. def refute_operator o1, op, o2, msg = nil
  379. msg = message(msg) {
  380. "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}"
  381. }
  382. refute o1.__send__(op, o2), msg
  383. end
  384. ##
  385. # Fails if +obj+ responds to the message +meth+.
  386. def refute_respond_to obj, meth, msg = nil
  387. msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" }
  388. refute obj.respond_to?(meth), msg
  389. end
  390. ##
  391. # Fails if +exp+ is the same (by object identity) as +act+.
  392. def refute_same exp, act, msg = nil
  393. msg = message(msg) {
  394. data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
  395. "Expected %s (oid=%d) to not be the same as %s (oid=%d)" % data
  396. }
  397. refute exp.equal?(act), msg
  398. end
  399. ##
  400. # Skips the current test. Gets listed at the end of the run but
  401. # doesn't cause a failure exit code.
  402. def skip msg = nil, bt = caller
  403. msg ||= "Skipped, no message given"
  404. raise MiniTest::Skip, msg, bt
  405. end
  406. end
  407. class Unit
  408. VERSION = "1.7.2" # :nodoc:
  409. attr_accessor :report, :failures, :errors, :skips # :nodoc:
  410. attr_accessor :test_count, :assertion_count # :nodoc:
  411. attr_accessor :start_time # :nodoc:
  412. @@installed_at_exit ||= false
  413. @@out = $stdout
  414. ##
  415. # Registers MiniTest::Unit to run tests at process exit
  416. def self.autorun
  417. at_exit {
  418. next if $! # don't run if there was an exception
  419. exit_code = MiniTest::Unit.new.run(ARGV)
  420. exit false if exit_code && exit_code != 0
  421. } unless @@installed_at_exit
  422. @@installed_at_exit = true
  423. end
  424. ##
  425. # Sets MiniTest::Unit to write output to +stream+. $stdout is the default
  426. # output
  427. def self.output= stream
  428. @@out = stream
  429. end
  430. def location e # :nodoc:
  431. last_before_assertion = ""
  432. e.backtrace.reverse_each do |s|
  433. break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
  434. last_before_assertion = s
  435. end
  436. last_before_assertion.sub(/:in .*$/, '')
  437. end
  438. ##
  439. # Writes status for failed test +meth+ in +klass+ which finished with
  440. # exception +e+
  441. def puke klass, meth, e
  442. e = case e
  443. when MiniTest::Skip then
  444. @skips += 1
  445. "Skipped:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
  446. when MiniTest::Assertion then
  447. @failures += 1
  448. "Failure:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
  449. else
  450. @errors += 1
  451. bt = MiniTest::filter_backtrace(e.backtrace).join("\n ")
  452. "Error:\n#{meth}(#{klass}):\n#{e.class}: #{e.message}\n #{bt}\n"
  453. end
  454. @report << e
  455. e[0, 1]
  456. end
  457. def initialize # :nodoc:
  458. @report = []
  459. @errors = @failures = @skips = 0
  460. @verbose = false
  461. end
  462. def process_args args = []
  463. options = {}
  464. OptionParser.new do |opts|
  465. opts.banner = 'minitest options:'
  466. opts.version = MiniTest::Unit::VERSION
  467. opts.on '-h', '--help', 'Display this help.' do
  468. puts opts
  469. exit
  470. end
  471. opts.on '-s', '--seed SEED', Integer, "Sets random seed" do |m|
  472. options[:seed] = m.to_i
  473. end
  474. opts.on '-v', '--verbose', "Verbose. Show progress processing files." do
  475. options[:verbose] = true
  476. end
  477. opts.on '-n', '--name PATTERN', "Filter test names on pattern." do |a|
  478. options[:filter] = a
  479. end
  480. opts.parse args
  481. end
  482. options
  483. end
  484. ##
  485. # Top level driver, controls all output and filtering.
  486. def run args = []
  487. options = process_args args
  488. @verbose = options[:verbose]
  489. filter = options[:filter] || '/./'
  490. filter = Regexp.new $1 if filter and filter =~ /\/(.*)\//
  491. seed = options[:seed]
  492. unless seed then
  493. srand
  494. seed = srand % 0xFFFF
  495. end
  496. srand seed
  497. help = ["--seed", seed]
  498. help.push "--verbose" if @verbose
  499. help.push("--name", options[:filter].inspect) if options[:filter]
  500. @@out.puts "Test run options: #{help.join(" ")}"
  501. @@out.puts
  502. @@out.puts "Loaded suite #{$0.sub(/\.rb$/, '')}\nStarted"
  503. start = Time.now
  504. run_test_suites filter
  505. @@out.puts
  506. @@out.puts "Finished in #{'%.6f' % (Time.now - start)} seconds."
  507. @report.each_with_index do |msg, i|
  508. @@out.puts "\n%3d) %s" % [i + 1, msg]
  509. end
  510. @@out.puts
  511. status
  512. @@out.puts
  513. @@out.puts "Test run options: #{help.join(" ")}"
  514. return failures + errors if @test_count > 0 # or return nil...
  515. rescue Interrupt
  516. abort 'Interrupted'
  517. end
  518. ##
  519. # Writes status to +io+
  520. def status io = @@out
  521. format = "%d tests, %d assertions, %d failures, %d errors, %d skips"
  522. io.puts format % [test_count, assertion_count, failures, errors, skips]
  523. end
  524. ##
  525. # Runs test suites matching +filter+
  526. def run_test_suites filter = /./
  527. @test_count, @assertion_count = 0, 0
  528. old_sync, @@out.sync = @@out.sync, true if @@out.respond_to? :sync=
  529. TestCase.test_suites.each do |suite|
  530. suite.test_methods.grep(filter).each do |test|
  531. inst = suite.new test
  532. inst._assertions = 0
  533. @@out.print "#{suite}##{test}: " if @verbose
  534. @start_time = Time.now
  535. result = inst.run(self)
  536. @@out.print "%.2f s: " % (Time.now - @start_time) if @verbose
  537. @@out.print result
  538. @@out.puts if @verbose
  539. @test_count += 1
  540. @assertion_count += inst._assertions
  541. end
  542. end
  543. @@out.sync = old_sync if @@out.respond_to? :sync=
  544. [@test_count, @assertion_count]
  545. end
  546. ##
  547. # Subclass TestCase to create your own tests. Typically you'll want a
  548. # TestCase subclass per implementation class.
  549. class TestCase
  550. attr_reader :__name__ # :nodoc:
  551. PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException,
  552. Interrupt, SystemExit] # :nodoc:
  553. SUPPORTS_INFO_SIGNAL = Signal.list['INFO'] # :nodoc:
  554. ##
  555. # Runs the tests reporting the status to +runner+
  556. def run runner
  557. trap 'INFO' do
  558. warn '%s#%s %.2fs' % [self.class, self.__name__,
  559. (Time.now - runner.start_time)]
  560. runner.status $stderr
  561. end if SUPPORTS_INFO_SIGNAL
  562. result = '.'
  563. begin
  564. @passed = nil
  565. self.setup
  566. self.__send__ self.__name__
  567. @passed = true
  568. rescue *PASSTHROUGH_EXCEPTIONS
  569. raise
  570. rescue Exception => e
  571. @passed = false
  572. result = runner.puke(self.class, self.__name__, e)
  573. ensure
  574. begin
  575. self.teardown
  576. rescue *PASSTHROUGH_EXCEPTIONS
  577. raise
  578. rescue Exception => e
  579. result = runner.puke(self.class, self.__name__, e)
  580. end
  581. trap 'INFO', 'DEFAULT' if SUPPORTS_INFO_SIGNAL
  582. end
  583. result
  584. end
  585. def initialize name # :nodoc:
  586. @__name__ = name
  587. @passed = nil
  588. end
  589. def self.reset # :nodoc:
  590. @@test_suites = {}
  591. end
  592. reset
  593. def self.inherited klass # :nodoc:
  594. @@test_suites[klass] = true
  595. end
  596. ##
  597. # Defines test order and is subclassable. Defaults to :random
  598. # but can be overridden to return :alpha if your tests are order
  599. # dependent (read: weak).
  600. def self.test_order
  601. :random
  602. end
  603. def self.test_suites # :nodoc:
  604. @@test_suites.keys.sort_by { |ts| ts.name }
  605. end
  606. def self.test_methods # :nodoc:
  607. methods = public_instance_methods(true).grep(/^test/).map { |m| m.to_s }
  608. case self.test_order
  609. when :random then
  610. max = methods.size
  611. methods.sort.sort_by { rand(max) }
  612. when :alpha, :sorted then
  613. methods.sort
  614. else
  615. raise "Unknown test_order: #{self.test_order.inspect}"
  616. end
  617. end
  618. ##
  619. # Returns true if the test passed.
  620. def passed?
  621. @passed
  622. end
  623. ##
  624. # Runs before every test. Use this to refactor test initialization.
  625. def setup; end
  626. ##
  627. # Runs after every test. Use this to refactor test cleanup.
  628. def teardown; end
  629. include MiniTest::Assertions
  630. end # class TestCase
  631. end # class Unit
  632. end # module MiniTest
  633. if $DEBUG then
  634. module Test # :nodoc:
  635. module Unit # :nodoc:
  636. class TestCase # :nodoc:
  637. def self.inherited x # :nodoc:
  638. # this helps me ferret out porting issues
  639. raise "Using minitest and test/unit in the same process: #{x}"
  640. end
  641. end
  642. end
  643. end
  644. end