Showing posts with label testspec. Show all posts
Showing posts with label testspec. Show all posts

01 July, 2007

and the test_spec_on_rails journey continues

Test/Spec has a wonderful - if largely unnoticed - feature: you can specify the superclass of contexts. The default is the ole' Test::Unit::TestCase, but that won't always do.

Let's say, hypothetically, you wanted to write some integration tests for your not-quite-shiny Rails app. You'd use ApplicationController::IntegrationTest, right? That way you can do things like get "/posts/34.html" and it would look up the routings and just do the right thing. Awesome.

Except... things aren't quite so simple when using test/spec. Therefore, I bring you an illustrious, illustrative example:

require File.dirname(__FILE__) + '/../test_helper'

class UserStoriesTest < ActionController::IntegrationTest
 fixtures :people, :openid_authentications, :password_authentications
 context "User Stories", ActionController::IntegrationTest do
   context "a person coming to the site to log in", ActionController::IntegrationTest do
     specify "should see the welcome page" do
       get '/'
       template.should.be 'welcome/index'
       status.should.be 200
     end
     specify "should be able to successfully log in with email and password..." do
       post_via_redirect '/login.html', {:email => 'pete.thomas@xahoo.com', :password => 'test'}
       template.should.be 'people/home'
       status.should.be 200
     end
   end
 end

end

test_spec_on_rails continued...

Yesterday, I was very happy because all my controller tests (using test/spec, of course) were passing individually.

Today I decided to run rake test:functionals just to make sure they played well together. CRASH! BOOM! OTHER LOUD NOISES!

The problem, after two hours of debugging, is that I was creating the same context in different controllers. DocumentationControllerTest had a "A guest" context, and so did "AccountControllerTest" and "WelcomeControllerTest"

Test/spec is perfectly happy to merge these . . . I just didn't realize it merged them. I assumed that it would scope the context to its parent TestClass. No such luck.

The solution is quite easy, and really not all that bad practice anyway: scope your contexts manually. For example:

class WelcomeControllerTest < Test::Unit::TestCase
 context "The Welcome Controller" do
   context "A guest" do
     ...
   end
   context "A logged-in user" do
     ...
   end
 end
end

30 June, 2007

ActsAsAuthenticated in test_spec_on_rails

I was having trouble getting "login_as" from the ActsAsAuthenticated plugin to work with test/spec on Rails.

TechnoWeenie suggested doing a def login_as... within each context. (It no longer does; I've put the code from this post into that page now.) That didn't seem very DRY, so I tried including ActsAsAuthenticated all over the place. Nothing worked...

Until I realized the problem: each "context" block creates a new instance of Test::Unit::TestCase. I had assumed it created a new instance of XxxControllerTest. Alas. Easy to fix. Just putTest::Unit::TestCase.send(:include, AuthenticatedTestHelper) before the opening of your XxxControllerTest.

For example:

require File.dirname(__FILE__) + '/../test_helper'
require 'welcome_controller'

Test::Unit::TestCase.send(:include, AuthenticatedTestHelper)

# Re-raise errors caught by the controller.
class WelcomeController; def rescue_action(e) raise e end; end

class WelcomeControllerTest < Test::Unit::TestCase
  fixtures :people
  def setup
    @controller = WelcomeController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
  end
  context "A logged-in person" do
    setup do
      use_controller WelcomeController
      login_as :yvette_moore
    end
     ...
  end
end