Module | Shoulda::ClassMethods |
In: |
lib/shoulda/context.rb
|
Before statements are should statements that run before the current context‘s setup. These are especially useful when setting expectations.
class UserControllerTest < Test::Unit::TestCase context "the index action" do setup do @users = [Factory(:user)] User.stubs(:find).returns(@users) end context "on GET" do setup { get :index } should_respond_with :success # runs before "get :index" before_should "find all users" do User.expects(:find).with(:all).returns(@users) end end end end
# File lib/shoulda/context.rb, line 98 98: def before_should(name, &blk) 99: should(name, :before => blk) { assert true } 100: end
A context block groups should statements under a common set of setup/teardown methods. Context blocks can be arbitrarily nested, and can do wonders for improving the maintainability and readability of your test code.
A context block can contain setup, should, should_eventually, and teardown blocks.
class UserTest < Test::Unit::TestCase context "A User instance" do setup do @user = User.find(:first) end should "return its full name" assert_equal 'John Doe', @user.full_name end end end
This code will produce the method "test: A User instance should return its full name. ".
Contexts may be nested. Nested contexts run their setup blocks from out to in before each should statement. They then run their teardown blocks from in to out after each should statement.
class UserTest < Test::Unit::TestCase context "A User instance" do setup do @user = User.find(:first) end should "return its full name" assert_equal 'John Doe', @user.full_name end context "with a profile" do setup do @user.profile = Profile.find(:first) end should "return true when sent :has_profile?" assert @user.has_profile? end end end end
This code will produce the following methods
Just like should statements, a context block can exist next to normal def test_the_old_way; end tests. This means you do not have to fully commit to the context/should syntax in a test file.
# File lib/shoulda/context.rb, line 165 165: def context(name, &blk) 166: if Shoulda.current_context 167: Shoulda.current_context.context(name, &blk) 168: else 169: context = Shoulda::Context.new(name, self, &blk) 170: context.build 171: end 172: end
Returns the class being tested, as determined by the test class name.
class UserTest; described_type; end # => User
# File lib/shoulda/context.rb, line 178 178: def described_type 179: self.name.gsub(/Test$/, '').constantize 180: end
Should statements are just syntactic sugar over normal Test::Unit test methods. A should block contains all the normal code and assertions you‘re used to seeing, with the added benefit that they can be wrapped inside context blocks (see below).
class UserTest < Test::Unit::TestCase def setup @user = User.new("John", "Doe") end should "return its full name" assert_equal 'John Doe', @user.full_name end end
…will produce the following test:
Note: The part before should in the test name is gleamed from the name of the Test::Unit class.
Should statements can also take a Proc as a :before option. This proc runs after any parent context‘s setups but before the current context‘s setup.
context "Some context" do setup { puts("I run after the :before proc") } should "run a :before proc", :before => lambda { puts("I run before the setup") } do assert true end end
# File lib/shoulda/context.rb, line 60 60: def should(name, options = {}, &blk) 61: if Shoulda.current_context 62: block_given? ? Shoulda.current_context.should(name, options, &blk) : Shoulda.current_context.should_eventually(name) 63: else 64: context_name = self.name.gsub(/Test/, "") 65: context = Shoulda::Context.new(context_name, self) do 66: block_given? ? should(name, options, &blk) : should_eventually(name) 67: end 68: context.build 69: end 70: end
Just like should, but never runs, and instead prints an ‘X’ in the Test::Unit output.
# File lib/shoulda/context.rb, line 103 103: def should_eventually(name, options = {}, &blk) 104: context_name = self.name.gsub(/Test/, "") 105: context = Shoulda::Context.new(context_name, self) do 106: should_eventually(name, &blk) 107: end 108: context.build 109: end