Rails Testing Framework lacking documentation

It's said that Rails promotes testing. But it lacks in properly
documentation.

I'm trying to learn how to write test units in Rails 2.1, but the
documentation is unusable.

Take for instance, this case:

In API, it is stated that:
" ActionController::Integration::Session
get(path, parameters = nil, headers = nil)

Performs a GET request with the given parameters. The parameters may be nil,
a Hash, or a string that is appropriately encoded
(application/x-www-form-urlencoded or multipart/form-data). The headers
should be a hash. The keys will automatically be upcased, with the
prefix ?HTTP_? added if needed."

Note that nothing is said about the "path" parameter. And that is exactly my
doubt!

continuing reading the API:

"ActionController::IntegrationTest
...
# get the login page
      get "/login"
...
# post the login and follow through to the home page
      post "/login", ...
"

Note that all examples use a string as the "path". Ok, that works...

The problem is that the scaffolded integration tests generated and a lot of
tutorial on the Net point to another usage: "get :index", using a symbol,
instead.
Here is an extract from scaffold:
"script/generate scaffold sample field1:string field2:integer"
test/functional/samples_controller_test.rb:

"class SamplesControllerTest < ActionController::TestCase
def test_should_get_index
    get :index
    assert_response :success
    assert_not_nil assigns(:samples)
  end"

That also works... but wait! Not always! This works for the scaffold
generated controller, but doesn't work on my actual application. I guess
the cause is that the scaffold generates RESTfull controllers and routes
and my own controllers aren't RESTful. Besides that, these tests inherits
ActionController::TestCase, instead of IntegrationTest. But it is just a
guest from my experience. Nor even the source code helped in this case.
Ruby is a too powerful language, which has also some drawbacks. It's too
powerful that it is difficult to find the implementation for some methods
if you don't know the implementation overall. Methods can be overridden in
any file and modules can be included in any file either.

First, note that SamplesControllerTest inherits ActionController::TestCase,
which has no documentation at all.

Thankfully to ruby_debug "step" method, I could realize that these are the
relevant codes:
actionpack/lib/action_controller/test_process.rb:359:
" module TestProcess
    def self.included(base)
      # execute the request simulating a specific HTTP method and set/volley
the response
      %w( get post put delete head ).each do |method|
        base.class_eval <<-EOV, __FILE__, __LINE__
          def #{method}(action, parameters = nil, session = nil, flash =
nil)
            @request.env['REQUEST_METHOD'] = "#{method.upcase}" if defined
(@request)
            process(action, parameters, session, flash)
          end
        EOV
      end
    end
    # execute the request and set/volley the response
    def process(action, parameters = nil, session = nil, flash = nil)
      # Sanity check for required instance variables so we can give an
      # understandable error message.
      %w(@controller @request @response).each do |iv_name|
        if !(instance_variable_names.include?(iv_name) ||
instance_variable_name
s.include?(iv_name.to_sym)) || instance_variable_get(iv_name).nil?
          raise "#{iv_name} is nil: make sure you set it in your test's
setup me
thod."
        end
      end

      @request.recycle!

      @html_document = nil
      @request.env['REQUEST_METHOD'] ||= "GET"
      debugger
      @request.action = action.to_s

      parameters ||= {}
      @request.assign_parameters(@controller.class.controller_path,
action.to_s,
parameters)
      @request.session = ActionController::TestSession.new(session) unless
session.nil?
      @request.session["flash"] =
ActionController::Flash::FlashHash.new.update(flash) if flash
      build_request_uri(action, parameters)
      @controller.process(@request, @response)
    end
...
"

Very clean, don't you agree? That's what I am talking about. The
ActionController::TestCase is just an example of the lack of documentation
in Rails, as a whole. There are a lot of methods and classes that lack
documentation in Rails.

I think Rails is one of the greatest frameworks I've known, but the lack of
good documentation and good internationalization support still sets me
down...

Finally, I would like to know, how am I supposed to learn about Testing in
Rails, without citing non-free books? I think there should be, at least, a
good API on the subject. Am I missing something?

Thanks in advance...

Sorry for boring you, but I'm pretty upset after 2 days digging on the
subject, trying to search for documentation in the API and finally, trying
to understand the source-code...

Rodrigo.

It's said that Rails promotes testing. But it lacks in properly
documentation.

I'm trying to learn how to write test units in Rails 2.1, but the
documentation is unusable.

Take for instance, this case:

In API, it is stated that:
" ActionController::Integration::Session
get(path, parameters = nil, headers = nil)

Performs a GET request with the given parameters. The parameters may
be nil,
a Hash, or a string that is appropriately encoded
(application/x-www-form-urlencoded or multipart/form-data). The
headers
should be a hash. The keys will automatically be upcased, with the
prefix ?HTTP_? added if needed."

Note that nothing is said about the "path" parameter. And that is
exactly my
doubt!

continuing reading the API:

"ActionController::IntegrationTest
...
# get the login page
     get "/login"
...
# post the login and follow through to the home page
     post "/login", ...
"

Note that all examples use a string as the "path". Ok, that works...

The problem is that the scaffolded integration tests generated and a
lot of
tutorial on the Net point to another usage: "get :index", using a
symbol,
instead.
Here is an extract from scaffold:
"script/generate scaffold sample field1:string field2:integer"
test/functional/samples_controller_test.rb:

"class SamplesControllerTest < ActionController::TestCase
def test_should_get_index
   get :index
   assert_response :success
   assert_not_nil assigns(:samples)
end"

The key thing here is that the documentation you have read is for
integration testing where the first parameter to get is a path whereas
what you have got there is a functional test (ie one which only
touches one particular controller). In this case the first parameter
is an action from the controller. You cannot invoke actions from other
controllers.

First, note that SamplesControllerTest inherits
ActionController::TestCase,
which has no documentation at all.

ActionController::TestCase isn't really an enduser facing class. It
automatically sets up a test request and response for you etc... but
that's about it

Very clean, don't you agree? That's what I am talking about. The
ActionController::TestCase is just an example of the lack of
documentation
in Rails, as a whole. There are a lot of methods and classes that lack
documentation in Rails.

Test process is an internal class. Unless you are hacking rails itself
you really don't need to know about this

I think Rails is one of the greatest frameworks I've known, but the
lack of
good documentation and good internationalization support still sets me
down...

Finally, I would like to know, how am I supposed to learn about
Testing in
Rails, without citing non-free books? I think there should be, at
least, a
good API on the subject. Am I missing something?

There are bits in the api about specific assertions (assert_select
etc..)
For a more conceptual type document, checkout http://izumi.plan99.net/manuals/testing_rails_applications.html

Fred

Frederick Cheung wrote:

It's said that Rails promotes testing. But it lacks in properly
documentation.

I'm trying to learn how to write test units in Rails 2.1, but the
documentation is unusable.
...

The key thing here is that the documentation you have read is for
integration testing where the first parameter to get is a path whereas
what you have got there is a functional test (ie one which only
touches one particular controller).

This is the documentation I've read because it is the only one I could find.

In this case the first parameter
is an action from the controller. You cannot invoke actions from other
controllers.

Right, but where is it stated on API documentation?

First, note that SamplesControllerTest inherits
ActionController::TestCase,
which has no documentation at all.

ActionController::TestCase isn't really an enduser facing class. It
automatically sets up a test request and response for you etc... but
that's about it

But why does Scaffold uses its class if it is not intended to be used by the
enduser?

...

Finally, I would like to know, how am I supposed to learn about
Testing in
Rails, without citing non-free books? I think there should be, at
least, a
good API on the subject. Am I missing something?

There are bits in the api about specific assertions (assert_select
etc..)
For a more conceptual type document, checkout
http://izumi.plan99.net/manuals/testing_rails_applications.html

I've read this documentation already before posting to the list. But, please
note that it doesn't mention Integration Tests.

I appreciate your help, though!

Thanks,

Rodrigo.

In this case the first parameter
is an action from the controller. You cannot invoke actions from
other
controllers.

Right, but where is it stated on API documentation?

probably nowhere because this is a conceptual thing (ie what is a
functional test?) rather than an api thing. it would be nice if the
rails manual thingy went over that

First, note that SamplesControllerTest inherits
ActionController::TestCase,
which has no documentation at all.

ActionController::TestCase isn't really an enduser facing class. It
automatically sets up a test request and response for you etc... but
that's about it

But why does Scaffold uses its class if it is not intended to be
used by the
enduser?

I mean that you don't need to know about it. It does some setup for
you that's all. the intricacies of test_process.rb don't matter

Fred

Frederick Cheung wrote:

In this case the first parameter
is an action from the controller. You cannot invoke actions from
other
controllers.

Right, but where is it stated on API documentation?

probably nowhere because this is a conceptual thing (ie what is a
functional test?) rather than an api thing. it would be nice if the
rails manual thingy went over that

I agree with you but that's not the point. I mean there should be at least
something like:

ActionController::TestCase::get(action, parameters = nil, session = nil,
flash = nil)
Invokes an action in the controller using the GET HTTP method.

Input parameters:
"action": a string or symbol that means which action should be called by the
controller.
"parameters": ...
"session": ...
"flash": ...

ActionController::TestCase::post(action, parameters = nil, session = nil,
flash = nil)
Invokes an action in the controller using the POST HTTP method. See
<link>get</link> for parameters description.

Or something like that...

Actually, these methods (get, post, put, delete and head) are not even
mentioned in the API documentation.

First, note that SamplesControllerTest inherits
ActionController::TestCase,
which has no documentation at all.

ActionController::TestCase isn't really an enduser facing class. It
automatically sets up a test request and response for you etc... but
that's about it

But why does Scaffold uses its class if it is not intended to be
used by the
enduser?

I mean that you don't need to know about it. It does some setup for
you that's all. the intricacies of test_process.rb don't matter

As far as I know, scaffold generates a skeleton. I mean, I would use the
skeleton as a basis and would write further test methods for newer actions,
for instance. How am I supposed to write these further tests without an API
documentation?

Rodrigo.

Rodrigo Rosenfeld Rosas wrote:

Actually, these methods (get, post, put, delete and head) are not even
mentioned in the API documentation.

I agree with you and I'd also like to be able to call methods of other
controllers at the beginning. However I understood that functional tests
are
limited to just one controller and found another and better way to test
multiple controllers. Let's look at an example (I'm using rspec):

  # This is testing UserController
  post :signin, "user" => { "login" => "testuser", "password" =>
"password" }
  response.should redirect_to(:controller => "welcome", :action =>
"index")

This leaves me at the same point where a signin failure would be, i.e. a
redirection to the home page. I'd like to check the destination page
with

  get :controller => "welcome", :action => "index"
  response.should have_text("<p>Welcome <strong>testuser</strong>!</p>")

but that's not possible because the home page is served by another
controller.

The solution is testing the authentication in integration tests. This is
what they are for. Just for reference, this is an rspec story for that
(there isn't much documentation on this subject, so let's spread it a
little)

  Story "Signing in", %{ A user wants to sign in }, :type => RailsStory
do

    Scenario "A user signs in" do
      Given "An existing user" do
        create_test_user
      end
      When "signing in with the right login and password" do
        post signin_users_url,
          :user => { :login => "testuser", :password => "password" }
      end
      Then "gets redirected to the home page" do
        response.should redirect_to(:controller => "welcome",
                                    :action => "index")
      end
      And "gets welcomed by login" do
        get "/"
        response.should include_text("<p>Welcome
<strong>testuser</strong>!</p>")
      end
    end
  end

By the way, the get/post methods are autogenerated. They are called by
http://api.rubyonrails.com/classes/ActionController/TestProcess.html#M000588
You can look at it inside
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/test_process.rb
or the equivalent file in your installation. The method generation is a
few lines before the "def process".

Paolo

paulo, what you’re looking for in test::unit is under integration testing. in rspec, it’s usually done with stories. controller tests/specs are specifically for one controller. integration testing is designed to test your app as a system rather than in units. hope that helps.

RSL