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.

On 23 Aug 2008, at 19:11, Rodrigo Rosenfeld R. wrote:

" ActionController::Integration::Session
Note that nothing is said about the “path” parameter. And that is

post the login and follow through to the home page

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

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 C. wrote:

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?

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.

On 25 Aug 2008, at 13:52, Rodrigo Rosenfeld R. 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

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 C. wrote:

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

get for parameters description.

Or something like that…

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

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 R. 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(“

Welcome testuser!

”)

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 

testuser!

")
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

On Sat, Sep 6, 2008 at 10:39 AM, Paolo M. <