PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/External.LCA_RESTRICTED/Languages/Ruby/ruby19/lib/ruby/gems/1.9.1/gems/shoulda-2.11.3/lib/shoulda/context.rb

http://github.com/IronLanguages/main
Ruby | 433 lines | 218 code | 49 blank | 166 comment | 16 complexity | 2d632616fc31c722000ffec8272367bf MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. module Shoulda
  2. class << self
  3. attr_accessor :contexts
  4. def contexts # :nodoc:
  5. @contexts ||= []
  6. end
  7. def current_context # :nodoc:
  8. self.contexts.last
  9. end
  10. def add_context(context) # :nodoc:
  11. self.contexts.push(context)
  12. end
  13. def remove_context # :nodoc:
  14. self.contexts.pop
  15. end
  16. end
  17. module ClassMethods
  18. # == Should statements
  19. #
  20. # Should statements are just syntactic sugar over normal Test::Unit test
  21. # methods. A should block contains all the normal code and assertions
  22. # you're used to seeing, with the added benefit that they can be wrapped
  23. # inside context blocks (see below).
  24. #
  25. # === Example:
  26. #
  27. # class UserTest < Test::Unit::TestCase
  28. #
  29. # def setup
  30. # @user = User.new("John", "Doe")
  31. # end
  32. #
  33. # should "return its full name"
  34. # assert_equal 'John Doe', @user.full_name
  35. # end
  36. #
  37. # end
  38. #
  39. # ...will produce the following test:
  40. # * <tt>"test: User should return its full name. "</tt>
  41. #
  42. # Note: The part before <tt>should</tt> in the test name is gleamed from the name of the Test::Unit class.
  43. #
  44. # Should statements can also take a Proc as a <tt>:before </tt>option. This proc runs after any
  45. # parent context's setups but before the current context's setup.
  46. #
  47. # === Example:
  48. #
  49. # context "Some context" do
  50. # setup { puts("I run after the :before proc") }
  51. #
  52. # should "run a :before proc", :before => lambda { puts("I run before the setup") } do
  53. # assert true
  54. # end
  55. # end
  56. #
  57. # Should statements can also wrap matchers, making virtually any matcher
  58. # usable in a macro style. The matcher's description is used to generate a
  59. # test name and failure message, and the test will pass if the matcher
  60. # matches the subject.
  61. #
  62. # === Example:
  63. #
  64. # should validate_presence_of(:first_name).with_message(/gotta be there/)
  65. #
  66. def should(name_or_matcher, options = {}, &blk)
  67. if Shoulda.current_context
  68. Shoulda.current_context.should(name_or_matcher, options, &blk)
  69. else
  70. context_name = self.name.gsub(/Test/, "")
  71. context = Shoulda::Context.new(context_name, self) do
  72. should(name_or_matcher, options, &blk)
  73. end
  74. context.build
  75. end
  76. end
  77. # Allows negative tests using matchers. The matcher's description is used
  78. # to generate a test name and negative failure message, and the test will
  79. # pass unless the matcher matches the subject.
  80. #
  81. # === Example:
  82. #
  83. # should_not set_the_flash
  84. def should_not(matcher)
  85. if Shoulda.current_context
  86. Shoulda.current_context.should_not(matcher)
  87. else
  88. context_name = self.name.gsub(/Test/, "")
  89. context = Shoulda::Context.new(context_name, self) do
  90. should_not(matcher)
  91. end
  92. context.build
  93. end
  94. end
  95. # == Before statements
  96. #
  97. # Before statements are should statements that run before the current
  98. # context's setup. These are especially useful when setting expectations.
  99. #
  100. # === Example:
  101. #
  102. # class UserControllerTest < Test::Unit::TestCase
  103. # context "the index action" do
  104. # setup do
  105. # @users = [Factory(:user)]
  106. # User.stubs(:find).returns(@users)
  107. # end
  108. #
  109. # context "on GET" do
  110. # setup { get :index }
  111. #
  112. # should respond_with(:success)
  113. #
  114. # # runs before "get :index"
  115. # before_should "find all users" do
  116. # User.expects(:find).with(:all).returns(@users)
  117. # end
  118. # end
  119. # end
  120. # end
  121. def before_should(name, &blk)
  122. should(name, :before => blk) { assert true }
  123. end
  124. # Just like should, but never runs, and instead prints an 'X' in the Test::Unit output.
  125. def should_eventually(name, options = {}, &blk)
  126. context_name = self.name.gsub(/Test/, "")
  127. context = Shoulda::Context.new(context_name, self) do
  128. should_eventually(name, &blk)
  129. end
  130. context.build
  131. end
  132. # == Contexts
  133. #
  134. # A context block groups should statements under a common set of setup/teardown methods.
  135. # Context blocks can be arbitrarily nested, and can do wonders for improving the maintainability
  136. # and readability of your test code.
  137. #
  138. # A context block can contain setup, should, should_eventually, and teardown blocks.
  139. #
  140. # class UserTest < Test::Unit::TestCase
  141. # context "A User instance" do
  142. # setup do
  143. # @user = User.find(:first)
  144. # end
  145. #
  146. # should "return its full name"
  147. # assert_equal 'John Doe', @user.full_name
  148. # end
  149. # end
  150. # end
  151. #
  152. # This code will produce the method <tt>"test: A User instance should return its full name. "</tt>.
  153. #
  154. # Contexts may be nested. Nested contexts run their setup blocks from out to in before each
  155. # should statement. They then run their teardown blocks from in to out after each should statement.
  156. #
  157. # class UserTest < Test::Unit::TestCase
  158. # context "A User instance" do
  159. # setup do
  160. # @user = User.find(:first)
  161. # end
  162. #
  163. # should "return its full name"
  164. # assert_equal 'John Doe', @user.full_name
  165. # end
  166. #
  167. # context "with a profile" do
  168. # setup do
  169. # @user.profile = Profile.find(:first)
  170. # end
  171. #
  172. # should "return true when sent :has_profile?"
  173. # assert @user.has_profile?
  174. # end
  175. # end
  176. # end
  177. # end
  178. #
  179. # This code will produce the following methods
  180. # * <tt>"test: A User instance should return its full name. "</tt>
  181. # * <tt>"test: A User instance with a profile should return true when sent :has_profile?. "</tt>
  182. #
  183. # <b>Just like should statements, a context block can exist next to normal <tt>def test_the_old_way; end</tt>
  184. # tests</b>. This means you do not have to fully commit to the context/should syntax in a test file.
  185. def context(name, &blk)
  186. if Shoulda.current_context
  187. Shoulda.current_context.context(name, &blk)
  188. else
  189. context = Shoulda::Context.new(name, self, &blk)
  190. context.build
  191. end
  192. end
  193. # Returns the class being tested, as determined by the test class name.
  194. #
  195. # class UserTest; described_type; end
  196. # # => User
  197. def described_type
  198. self.name.gsub(/Test$/, '').constantize
  199. end
  200. # Sets the return value of the subject instance method:
  201. #
  202. # class UserTest < Test::Unit::TestCase
  203. # subject { User.first }
  204. #
  205. # # uses the existing user
  206. # should validate_uniqueness_of(:email)
  207. # end
  208. def subject(&block)
  209. @subject_block = block
  210. end
  211. def subject_block # :nodoc:
  212. @subject_block
  213. end
  214. end
  215. module InstanceMethods
  216. # Returns an instance of the class under test.
  217. #
  218. # class UserTest
  219. # should "be a user" do
  220. # assert_kind_of User, subject # passes
  221. # end
  222. # end
  223. #
  224. # The subject can be explicitly set using the subject class method:
  225. #
  226. # class UserTest
  227. # subject { User.first }
  228. # should "be an existing user" do
  229. # assert !subject.new_record? # uses the first user
  230. # end
  231. # end
  232. #
  233. # The subject is used by all macros that require an instance of the class
  234. # being tested.
  235. def subject
  236. @shoulda_subject ||= construct_subject
  237. end
  238. def subject_block # :nodoc:
  239. (@shoulda_context && @shoulda_context.subject_block) || self.class.subject_block
  240. end
  241. def get_instance_of(object_or_klass) # :nodoc:
  242. if object_or_klass.is_a?(Class)
  243. object_or_klass.new
  244. else
  245. object_or_klass
  246. end
  247. end
  248. def instance_variable_name_for(klass) # :nodoc:
  249. klass.to_s.split('::').last.underscore
  250. end
  251. private
  252. def construct_subject
  253. if subject_block
  254. instance_eval(&subject_block)
  255. else
  256. get_instance_of(self.class.described_type)
  257. end
  258. end
  259. end
  260. class Context # :nodoc:
  261. attr_accessor :name # my name
  262. attr_accessor :parent # may be another context, or the original test::unit class.
  263. attr_accessor :subcontexts # array of contexts nested under myself
  264. attr_accessor :setup_blocks # blocks given via setup methods
  265. attr_accessor :teardown_blocks # blocks given via teardown methods
  266. attr_accessor :shoulds # array of hashes representing the should statements
  267. attr_accessor :should_eventuallys # array of hashes representing the should eventually statements
  268. attr_accessor :subject_block
  269. def initialize(name, parent, &blk)
  270. Shoulda.add_context(self)
  271. self.name = name
  272. self.parent = parent
  273. self.setup_blocks = []
  274. self.teardown_blocks = []
  275. self.shoulds = []
  276. self.should_eventuallys = []
  277. self.subcontexts = []
  278. merge_block(&blk)
  279. Shoulda.remove_context
  280. end
  281. def merge_block(&blk)
  282. blk.bind(self).call
  283. end
  284. def context(name, &blk)
  285. self.subcontexts << Context.new(name, self, &blk)
  286. end
  287. def setup(&blk)
  288. self.setup_blocks << blk
  289. end
  290. def teardown(&blk)
  291. self.teardown_blocks << blk
  292. end
  293. def should(name_or_matcher, options = {}, &blk)
  294. if name_or_matcher.respond_to?(:description) && name_or_matcher.respond_to?(:matches?)
  295. name = name_or_matcher.description
  296. blk = lambda { assert_accepts name_or_matcher, subject }
  297. else
  298. name = name_or_matcher
  299. end
  300. if blk
  301. self.shoulds << { :name => name, :before => options[:before], :block => blk }
  302. else
  303. self.should_eventuallys << { :name => name }
  304. end
  305. end
  306. def should_not(matcher)
  307. name = matcher.description
  308. blk = lambda { assert_rejects matcher, subject }
  309. self.shoulds << { :name => "not #{name}", :block => blk }
  310. end
  311. def should_eventually(name, &blk)
  312. self.should_eventuallys << { :name => name, :block => blk }
  313. end
  314. def subject(&block)
  315. self.subject_block = block
  316. end
  317. def subject_block
  318. return @subject_block if @subject_block
  319. parent.subject_block
  320. end
  321. def full_name
  322. parent_name = parent.full_name if am_subcontext?
  323. return [parent_name, name].join(" ").strip
  324. end
  325. def am_subcontext?
  326. parent.is_a?(self.class) # my parent is the same class as myself.
  327. end
  328. def test_unit_class
  329. am_subcontext? ? parent.test_unit_class : parent
  330. end
  331. def create_test_from_should_hash(should)
  332. test_name = ["test:", full_name, "should", "#{should[:name]}. "].flatten.join(' ').to_sym
  333. if test_unit_class.instance_methods.include?(test_name.to_s)
  334. warn " * WARNING: '#{test_name}' is already defined"
  335. end
  336. context = self
  337. test_unit_class.send(:define_method, test_name) do
  338. @shoulda_context = context
  339. begin
  340. context.run_parent_setup_blocks(self)
  341. should[:before].bind(self).call if should[:before]
  342. context.run_current_setup_blocks(self)
  343. should[:block].bind(self).call
  344. ensure
  345. context.run_all_teardown_blocks(self)
  346. end
  347. end
  348. end
  349. def run_all_setup_blocks(binding)
  350. run_parent_setup_blocks(binding)
  351. run_current_setup_blocks(binding)
  352. end
  353. def run_parent_setup_blocks(binding)
  354. self.parent.run_all_setup_blocks(binding) if am_subcontext?
  355. end
  356. def run_current_setup_blocks(binding)
  357. setup_blocks.each do |setup_block|
  358. setup_block.bind(binding).call
  359. end
  360. end
  361. def run_all_teardown_blocks(binding)
  362. teardown_blocks.reverse.each do |teardown_block|
  363. teardown_block.bind(binding).call
  364. end
  365. self.parent.run_all_teardown_blocks(binding) if am_subcontext?
  366. end
  367. def print_should_eventuallys
  368. should_eventuallys.each do |should|
  369. test_name = [full_name, "should", "#{should[:name]}. "].flatten.join(' ')
  370. puts " * DEFERRED: " + test_name
  371. end
  372. end
  373. def build
  374. shoulds.each do |should|
  375. create_test_from_should_hash(should)
  376. end
  377. subcontexts.each { |context| context.build }
  378. print_should_eventuallys
  379. end
  380. def method_missing(method, *args, &blk)
  381. test_unit_class.send(method, *args, &blk)
  382. end
  383. end
  384. end