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