Question

Here's a nice technique I use with RSpec that I would also like to use in projects that use Shoulda and Shoulda-context. But I don't know if it's possible. Is there a way to do this?

What I want: define a setup (before) block in an outer context that references a let clause in a nested context. That way, inner contexts can configure values that are referenced in the outer setup And the setup can still be DRY across inner contexts.

RSpec example (this example is simple--please assume my real-life examples have a lot more code in the before block that I don't want to duplicate):

describe Thing do
  before do
    # Notice that `user` isn't defined here--it's defined in `let` blocks
    # in nested contexts below.
    login_as user

    # Assume there's lots more code here that I would like to keep
    # DRY across contexts.
  end

  context "when logged in as an admin" do
    # THIS IS THE MAGIC RIGHT HERE:
    let(:user) { Factory(:user, role: "admin") }

    it "should ..." ...
  end

  context "when logged in as a normal user" do
    # THIS IS THE MAGIC RIGHT HERE:
    let(:user) { Factory(:user) }

    it "should ..." ...
  end
end

To summarize: how can I do this with shoulda-context and Test::Unit?

Some things I have already tried that didn't work:

  • def to redefine a method in each subcontext.
  • before_should in each subcontext.
Was it helpful?

Solution

I've found helper methods inside the test class useful for pulling out code repeated between tests. Like this:

class MyTest < TestCase
  context "when logged in as an admin" do
    setup do
      do_login Factory(:user, role: "admin")
    end

    should "..." do
      ...@user...
    end
  end

  context "when logged in as an admin" do
    setup do
      do_login Factory(:user)
    end

    should "..." do
      ...@user...
    end
  end

  def do_login(user)
    login_as user
    @user = user

    # lots more setup code here...
  end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top