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

/Languages/Ruby/Tests/Libraries/test-spec-0.10.0/lib/test/spec.rb

http://github.com/IronLanguages/main
Ruby | 662 lines | 615 code | 38 blank | 9 comment | 7 complexity | fb3a794e9c4afcbc591c77008de4cf02 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. #
  2. # test/spec -- a BDD interface for Test::Unit
  3. #
  4. # Copyright (C) 2006, 2007, 2008, 2009 Christian Neukirchen <mailto:chneukirchen@gmail.com>
  5. #
  6. # This work is licensed under the same terms as Ruby itself.
  7. #
  8. require 'test/unit'
  9. class Test::Unit::AutoRunner # :nodoc:
  10. RUNNERS[:specdox] = lambda { |*args|
  11. require 'test/spec/dox'
  12. Test::Unit::UI::SpecDox::TestRunner
  13. }
  14. RUNNERS[:rdox] = lambda { |*args|
  15. require 'test/spec/rdox'
  16. Test::Unit::UI::RDox::TestRunner
  17. }
  18. end
  19. module Test # :nodoc:
  20. end
  21. module Test::Spec
  22. require 'test/spec/version'
  23. CONTEXTS = {} # :nodoc:
  24. SHARED_CONTEXTS = Hash.new { |h,k| h[k] = [] } # :nodoc:
  25. class DefinitionError < StandardError
  26. end
  27. class Should
  28. include Test::Unit::Assertions
  29. def self.deprecated_alias(to, from) # :nodoc:
  30. define_method(to) { |*args|
  31. warn "Test::Spec::Should##{to} is deprecated and will be removed in future versions."
  32. __send__ from, *args
  33. }
  34. end
  35. def initialize(object, message=nil)
  36. @object = object
  37. @message = message
  38. end
  39. $TEST_SPEC_TESTCASE = nil
  40. def add_assertion
  41. $TEST_SPEC_TESTCASE && $TEST_SPEC_TESTCASE.__send__(:add_assertion)
  42. end
  43. def an
  44. self
  45. end
  46. def a
  47. self
  48. end
  49. def not(*args)
  50. case args.size
  51. when 0
  52. ShouldNot.new(@object, @message)
  53. when 1
  54. ShouldNot.new(@object, @message).pass(args.first)
  55. else
  56. raise ArgumentError, "#not takes zero or one argument(s)."
  57. end
  58. end
  59. def messaging(message)
  60. @message = message.to_s
  61. self
  62. end
  63. alias blaming messaging
  64. def satisfy(&block)
  65. assert_block(@message || "satisfy block failed.") {
  66. yield @object
  67. }
  68. end
  69. def equal(value)
  70. assert_equal value, @object, @message
  71. end
  72. alias == equal
  73. def close(value, delta)
  74. assert_in_delta value, @object, delta, @message
  75. end
  76. deprecated_alias :be_close, :close
  77. def be(*value)
  78. case value.size
  79. when 0
  80. self
  81. when 1
  82. if CustomShould === value.first
  83. pass value.first
  84. else
  85. assert_same value.first, @object, @message
  86. end
  87. else
  88. raise ArgumentError, "should.be needs zero or one argument"
  89. end
  90. end
  91. def match(value)
  92. assert_match value, @object, @message
  93. end
  94. alias =~ match
  95. def instance_of(klass)
  96. assert_instance_of klass, @object, @message
  97. end
  98. deprecated_alias :be_an_instance_of, :instance_of
  99. def kind_of(klass)
  100. assert_kind_of klass, @object, @message
  101. end
  102. deprecated_alias :be_a_kind_of, :kind_of
  103. def respond_to(method)
  104. assert_respond_to @object, method, @message
  105. end
  106. def _raise(*args, &block)
  107. args = [RuntimeError] if args.empty?
  108. block ||= @object
  109. args << @message if @message
  110. assert_raise(*args, &block)
  111. end
  112. def throw(sym)
  113. assert_throws(sym, @message, &@object)
  114. end
  115. def nil
  116. assert_nil @object, @message
  117. end
  118. deprecated_alias :be_nil, :nil
  119. def include(value)
  120. msg = build_message(@message, "<?> expected to include ?, but it didn't.",
  121. @object, value)
  122. assert_block(msg) { @object.include?(value) }
  123. end
  124. def >(value)
  125. assert_operator @object, :>, value, @message
  126. end
  127. def >=(value)
  128. assert_operator @object, :>=, value, @message
  129. end
  130. def <(value)
  131. assert_operator @object, :<, value, @message
  132. end
  133. def <=(value)
  134. assert_operator @object, :<=, value, @message
  135. end
  136. def ===(value)
  137. assert_operator @object, :===, value, @message
  138. end
  139. def pass(custom)
  140. _wrap_assertion {
  141. assert_nothing_raised(Test::Unit::AssertionFailedError,
  142. @message || custom.failure_message) {
  143. assert custom.matches?(@object), @message || custom.failure_message
  144. }
  145. }
  146. end
  147. def method_missing(name, *args, &block)
  148. # This will make raise call Kernel.raise, and self.raise call _raise.
  149. return _raise(*args, &block) if name == :raise
  150. if @object.respond_to?("#{name}?")
  151. assert @object.__send__("#{name}?", *args),
  152. "#{name}? expected to be true. #{@message}"
  153. else
  154. if @object.respond_to?(name)
  155. assert @object.__send__(name, *args),
  156. "#{name} expected to be true. #{@message}"
  157. else
  158. super
  159. end
  160. end
  161. end
  162. end
  163. class ShouldNot
  164. include Test::Unit::Assertions
  165. def initialize(object, message=nil)
  166. @object = object
  167. @message = message
  168. end
  169. def add_assertion
  170. $TEST_SPEC_TESTCASE && $TEST_SPEC_TESTCASE.__send__(:add_assertion)
  171. end
  172. def satisfy(&block)
  173. assert_block(@message || "not.satisfy block succeded.") {
  174. not yield @object
  175. }
  176. end
  177. def equal(value)
  178. assert_not_equal value, @object, @message
  179. end
  180. alias == equal
  181. def be(*value)
  182. case value.size
  183. when 0
  184. self
  185. when 1
  186. if CustomShould === value.first
  187. pass value.first
  188. else
  189. assert_not_same value.first, @object, @message
  190. end
  191. else
  192. Kernel.raise ArgumentError, "should.be needs zero or one argument"
  193. end
  194. end
  195. def match(value)
  196. # Icky Regexp check
  197. assert_no_match value, @object, @message
  198. end
  199. alias =~ match
  200. def _raise(*args, &block)
  201. block ||= @object
  202. args << @message if @message
  203. assert_nothing_raised(*args, &block)
  204. end
  205. def throw
  206. assert_nothing_thrown(@message, &@object)
  207. end
  208. def nil
  209. assert_not_nil @object, @message
  210. end
  211. def be_nil
  212. warn "Test::Spec::ShouldNot#be_nil is deprecated and will be removed in future versions."
  213. self.nil
  214. end
  215. def not(*args)
  216. case args.size
  217. when 0
  218. Should.new(@object, @message)
  219. when 1
  220. Should.new(@object, @message).pass(args.first)
  221. else
  222. raise ArgumentError, "#not takes zero or one argument(s)."
  223. end
  224. end
  225. def pass(custom)
  226. _wrap_assertion {
  227. begin
  228. assert !custom.matches?(@object), @message || custom.failure_message
  229. end
  230. }
  231. end
  232. def method_missing(name, *args, &block)
  233. # This will make raise call Kernel.raise, and self.raise call _raise.
  234. return _raise(*args, &block) if name == :raise
  235. if @object.respond_to?("#{name}?")
  236. assert_block("#{name}? expected to be false. #{@message}") {
  237. not @object.__send__("#{name}?", *args)
  238. }
  239. else
  240. if @object.respond_to?(name)
  241. assert_block("#{name} expected to be false. #{@message}") {
  242. not @object.__send__("#{name}", *args)
  243. }
  244. else
  245. super
  246. end
  247. end
  248. end
  249. end
  250. class CustomShould
  251. attr_accessor :object
  252. def initialize(obj)
  253. self.object = obj
  254. end
  255. def failure_message
  256. "#{self.class.name} failed"
  257. end
  258. def matches?(*args, &block)
  259. assumptions(*args, &block)
  260. true
  261. end
  262. def assumptions(*args, &block)
  263. raise NotImplementedError, "you need to supply a #{self.class}#matches? method"
  264. end
  265. end
  266. end
  267. class Test::Spec::TestCase
  268. attr_reader :testcase
  269. attr_reader :name
  270. attr_reader :position
  271. module InstanceMethods
  272. def setup # :nodoc:
  273. $TEST_SPEC_TESTCASE = self
  274. super
  275. call_methods_including_parents(:setups)
  276. end
  277. def teardown # :nodoc:
  278. super
  279. call_methods_including_parents(:teardowns, :reverse)
  280. end
  281. def before_all
  282. call_methods_including_parents(:before_all)
  283. end
  284. def after_all
  285. call_methods_including_parents(:after_all, :reverse)
  286. end
  287. def initialize(name)
  288. super name
  289. # Don't let the default_test clutter up the results and don't
  290. # flunk if no tests given, either.
  291. throw :invalid_test if name.to_s == "default_test"
  292. end
  293. def position
  294. self.class.position
  295. end
  296. def context(*args)
  297. raise Test::Spec::DefinitionError,
  298. "context definition is not allowed inside a specify-block"
  299. end
  300. alias :describe :context
  301. private
  302. def call_methods_including_parents(method, reverse=false, klass=self.class)
  303. return unless klass
  304. if reverse
  305. klass.send(method).each { |s| instance_eval(&s) }
  306. call_methods_including_parents(method, reverse, klass.parent)
  307. else
  308. call_methods_including_parents(method, reverse, klass.parent)
  309. klass.send(method).each { |s| instance_eval(&s) }
  310. end
  311. end
  312. end
  313. module ClassMethods
  314. attr_accessor :count
  315. attr_accessor :name
  316. attr_accessor :position
  317. attr_accessor :parent
  318. attr_accessor :setups
  319. attr_accessor :teardowns
  320. attr_accessor :before_all
  321. attr_accessor :after_all
  322. # old-style (RSpec <1.0):
  323. def context(name, superclass=Test::Unit::TestCase, klass=Test::Spec::TestCase, &block)
  324. (Test::Spec::CONTEXTS[self.name + "\t" + name] ||= klass.new(name, self, superclass)).add(&block)
  325. end
  326. def xcontext(name, superclass=Test::Unit::TestCase, &block)
  327. context(name, superclass, Test::Spec::DisabledTestCase, &block)
  328. end
  329. def specify(specname, &block)
  330. raise ArgumentError, "specify needs a block" if block.nil?
  331. self.count += 1 # Let them run in order of definition
  332. define_method("test_spec {%s} %03d [%s]" % [name, count, specname], &block)
  333. end
  334. def xspecify(specname, &block)
  335. specify specname do
  336. @_result.add_disabled(specname)
  337. end
  338. end
  339. def setup(&block)
  340. setups << block
  341. end
  342. def teardown(&block)
  343. teardowns << block
  344. end
  345. def shared_context(name, &block)
  346. Test::Spec::SHARED_CONTEXTS[self.name + "\t" + name] << block
  347. end
  348. def behaves_like(shared_context)
  349. if Test::Spec::SHARED_CONTEXTS.include?(shared_context)
  350. Test::Spec::SHARED_CONTEXTS[shared_context].each { |block|
  351. instance_eval(&block)
  352. }
  353. elsif Test::Spec::SHARED_CONTEXTS.include?(self.name + "\t" + shared_context)
  354. Test::Spec::SHARED_CONTEXTS[self.name + "\t" + shared_context].each { |block|
  355. instance_eval(&block)
  356. }
  357. else
  358. raise NameError, "Shared context #{shared_context} not found."
  359. end
  360. end
  361. alias :it_should_behave_like :behaves_like
  362. # new-style (RSpec 1.0+):
  363. alias :describe :context
  364. alias :describe_shared :shared_context
  365. alias :it :specify
  366. alias :xit :xspecify
  367. def before(kind=:each, &block)
  368. case kind
  369. when :each
  370. setup(&block)
  371. when :all
  372. before_all << block
  373. else
  374. raise ArgumentError, "invalid argument: before(#{kind.inspect})"
  375. end
  376. end
  377. def after(kind=:each, &block)
  378. case kind
  379. when :each
  380. teardown(&block)
  381. when :all
  382. after_all << block
  383. else
  384. raise ArgumentError, "invalid argument: after(#{kind.inspect})"
  385. end
  386. end
  387. def init(name, position, parent)
  388. self.position = position
  389. self.parent = parent
  390. if parent
  391. self.name = parent.name + "\t" + name
  392. else
  393. self.name = name
  394. end
  395. self.count = 0
  396. self.setups = []
  397. self.teardowns = []
  398. self.before_all = []
  399. self.after_all = []
  400. end
  401. end
  402. @@POSITION = 0
  403. def initialize(name, parent=nil, superclass=Test::Unit::TestCase)
  404. @testcase = Class.new(superclass) {
  405. include InstanceMethods
  406. extend ClassMethods
  407. }
  408. @@POSITION = @@POSITION + 1
  409. @testcase.init(name, @@POSITION, parent)
  410. end
  411. def add(&block)
  412. raise ArgumentError, "context needs a block" if block.nil?
  413. @testcase.class_eval(&block)
  414. self
  415. end
  416. end
  417. (Test::Spec::DisabledTestCase = Test::Spec::TestCase.dup).class_eval do
  418. alias :test_case_initialize :initialize
  419. def initialize(*args, &block)
  420. test_case_initialize(*args, &block)
  421. @testcase.instance_eval do
  422. alias :test_case_specify :specify
  423. def specify(specname, &block)
  424. test_case_specify(specname) { @_result.add_disabled(specname) }
  425. end
  426. alias :it :specify
  427. end
  428. end
  429. end
  430. class Test::Spec::Disabled < Test::Unit::Failure # :nodoc:
  431. def initialize(name)
  432. @name = name
  433. end
  434. def single_character_display
  435. "D"
  436. end
  437. def short_display
  438. @name
  439. end
  440. def long_display
  441. @name + " is disabled"
  442. end
  443. end
  444. class Test::Spec::Empty < Test::Unit::Failure # :nodoc:
  445. def initialize(name)
  446. @name = name
  447. end
  448. def single_character_display
  449. ""
  450. end
  451. def short_display
  452. @name
  453. end
  454. def long_display
  455. @name + " is empty"
  456. end
  457. end
  458. # Monkey-patch test/unit to run tests in an optionally specified order.
  459. module Test::Unit # :nodoc:
  460. class TestSuite # :nodoc:
  461. undef run
  462. def run(result, &progress_block)
  463. sort!
  464. yield(STARTED, name)
  465. @tests.first.before_all if @tests.first.respond_to? :before_all
  466. @tests.each do |test|
  467. test.run(result, &progress_block)
  468. end
  469. @tests.last.after_all if @tests.last.respond_to? :after_all
  470. yield(FINISHED, name)
  471. end
  472. def sort!
  473. @tests = @tests.sort_by { |test|
  474. test.respond_to?(:position) ? test.position : 0
  475. }
  476. end
  477. def position
  478. @tests.first.respond_to?(:position) ? @tests.first.position : 0
  479. end
  480. end
  481. class TestResult # :nodoc:
  482. # Records a disabled test.
  483. def add_disabled(name)
  484. notify_listeners(FAULT, Test::Spec::Disabled.new(name))
  485. notify_listeners(CHANGED, self)
  486. end
  487. end
  488. end
  489. # Hide Test::Spec interna in backtraces.
  490. module Test::Unit::Util::BacktraceFilter # :nodoc:
  491. TESTSPEC_PREFIX = __FILE__.gsub(/spec\.rb\Z/, '')
  492. # Vendor plugins like to be loaded several times, don't recurse
  493. # infinitely then.
  494. unless method_defined? "testspec_filter_backtrace"
  495. alias :testspec_filter_backtrace :filter_backtrace
  496. end
  497. def filter_backtrace(backtrace, prefix=nil)
  498. if prefix.nil?
  499. testspec_filter_backtrace(testspec_filter_backtrace(backtrace),
  500. TESTSPEC_PREFIX)
  501. else
  502. testspec_filter_backtrace(backtrace, prefix)
  503. end
  504. end
  505. end
  506. #-- Global helpers
  507. class Object
  508. def should(*args)
  509. case args.size
  510. when 0
  511. Test::Spec::Should.new(self)
  512. when 1
  513. Test::Spec::Should.new(self).pass(args.first)
  514. else
  515. raise ArgumentError, "Object#should takes zero or one argument(s)."
  516. end
  517. end
  518. end
  519. module Kernel
  520. def context(name, superclass=Test::Unit::TestCase, klass=Test::Spec::TestCase, &block) # :doc:
  521. (Test::Spec::CONTEXTS[name] ||= klass.new(name, nil, superclass)).add(&block)
  522. end
  523. def xcontext(name, superclass=Test::Unit::TestCase, &block) # :doc:
  524. context(name, superclass, Test::Spec::DisabledTestCase, &block)
  525. end
  526. def shared_context(name, &block)
  527. Test::Spec::SHARED_CONTEXTS[name] << block
  528. end
  529. alias :describe :context
  530. alias :xdescribe :xcontext
  531. alias :describe_shared :shared_context
  532. private :context, :xcontext, :shared_context
  533. private :describe, :xdescribe, :describe_shared
  534. end