<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Wolfmans Howlings: RSpec testing all actions of a controller</title>
    <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>A programmers Blog about Ruby, Rails and a few other issues</description>
    <item>
      <title>RSpec testing all actions of a controller</title>
      <description>&lt;p&gt;A pattern I find very helpful is to find all the actions in a
controller and apply a test to all those actions. &lt;/p&gt;

&lt;p&gt;For instance this is useful for automatically testing all actions are
protected from unauthorized access when using a login system.&lt;/p&gt;

&lt;p&gt;One nice feature of this pattern is that if you add an action to a
controller it will automatically be tested. This is less helpful if
you use&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;before_filter :login_required, :except =&amp;gt; {...}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;as it will automatically be protected, but there are other use cases
where this is not the situation. Just as in the except clause above
you need to explicitly add any action that does not need to be tested
to an exception list, which is supported by this pattern.&lt;/p&gt;

&lt;p&gt;Here are the methods I use to test for login accessibility.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;MySpecHelper&lt;/span&gt;

  &lt;span class="comment"&gt;# get all actions for specified controller&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;get_all_actions&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;cont&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;c&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Module&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;const_get&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;cont&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;pluralize&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;capitalize&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Controller&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="ident"&gt;c&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;public_instance_methods&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;reject&lt;/span&gt;&lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;action&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;rescue_action&lt;/span&gt;&lt;span class="punct"&gt;'].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;action&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# test actions fail if not logged in&lt;/span&gt;
  &lt;span class="comment"&gt;# opts[:exclude] contains an array of actions to skip&lt;/span&gt;
  &lt;span class="comment"&gt;# opts[:include] contains an array of actions to add to the test in addition&lt;/span&gt;
  &lt;span class="comment"&gt;# to any found by get_all_actions&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;controller_actions_should_fail_if_not_logged_in&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;cont&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;opts&lt;/span&gt;&lt;span class="punct"&gt;={})&lt;/span&gt;
    &lt;span class="ident"&gt;except&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;opts&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:except&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="punct"&gt;[]&lt;/span&gt;
    &lt;span class="ident"&gt;actions_to_test&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;get_all_actions&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;cont&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;reject&lt;/span&gt;&lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;except&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="ident"&gt;actions_to_test&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="ident"&gt;opts&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:include&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;opts&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:include&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
    &lt;span class="ident"&gt;actions_to_test&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="comment"&gt;#puts &amp;quot;... #{a}&amp;quot;&lt;/span&gt;
      &lt;span class="ident"&gt;get&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt;
      &lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_not&lt;/span&gt; &lt;span class="ident"&gt;be_success&lt;/span&gt;
      &lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;redirect_to&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;http://test.host/login&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
      &lt;span class="ident"&gt;flash&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:warning&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="attribute"&gt;@login_warning&lt;/span&gt;
   &lt;span class="keyword"&gt;end&lt;/span&gt;
 &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I put this in my spec_helper.rb and include it as shown here:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;When Logged out&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;MySpecHelper&lt;/span&gt;
  &lt;span class="ident"&gt;controller_name&lt;/span&gt; &lt;span class="symbol"&gt;:events&lt;/span&gt;

  &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:each&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;controller&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;stub!&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:current_user&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:false&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@login_warning&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;You need to be logged in to do that&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# test all actions require login except the ones specified&lt;/span&gt;
  &lt;span class="comment"&gt;# add new_comment as it is not seen by the automatic collector&lt;/span&gt;
  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;actions should fail&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;controller_actions_should_fail_if_not_logged_in&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:input&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; 
                              &lt;span class="symbol"&gt;:except&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;show&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;tagged&lt;/span&gt;&lt;span class="punct"&gt;'],&lt;/span&gt; 
                              &lt;span class="symbol"&gt;:include&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;new_comment&lt;/span&gt;&lt;span class="punct"&gt;'])&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;get_all_actions&lt;/code&gt; method collects all the public un-inherited
methods in the given controller, these will consist of all the
accessible actions in that controller. I explicitly exclude
&lt;code&gt;rescue_action&lt;/code&gt; as it is created by RSpec itself and should not be
tested. Note it will not see any actions that are in application.rb so
you need to add those to the list manually of you want them tested.
(See the :include option in the example).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;controller_actions_should_fail_if_not_logged_in&lt;/code&gt; could be put in
the spec itself rather than the spec_helper, but as I call this from
all my controller specs it is more DRY to put it here. This method
takes the controller name and an option array of actions names to
ignore. This method tests all the actions and makes sure I get the
expected result of the filter failing due to not being logged in.&lt;/p&gt;

&lt;p&gt;I show an example spec that uses this to test my events controller, it
mocks the login calls to say I am not logged in, and then tests them
with the exceptions of the actions in this controller that do not
require one to be logged in.&lt;/p&gt;

&lt;p&gt;This pattern can be extended to test all sorts of things, and is
especially useful for testing things where you can add an action and
forget to do something in a filter to protect it. Make sure the
default is on the side of caution though. IE you need to explicitly
except actions rather than include actions.&lt;/p&gt;

&lt;p&gt;Another example is something I recently stumbled upon in my RESTful
controllers. In many cases it is good to use a verify statement to
make sure that the RESTful actions actually can only be called with
PUT, POST or DELETE and fail if called with GET. I use this statement
in my controllers to enforce this...&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)&lt;/span&gt;
&lt;span class="ident"&gt;verify&lt;/span&gt; &lt;span class="symbol"&gt;:method&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:put&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:only&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt; &lt;span class="symbol"&gt;:update&lt;/span&gt; &lt;span class="punct"&gt;],&lt;/span&gt; &lt;span class="symbol"&gt;:add_flash&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:error&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Operation Failed&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;},&lt;/span&gt; &lt;span class="symbol"&gt;:redirect_to&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:index&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;verify&lt;/span&gt; &lt;span class="symbol"&gt;:method&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:post&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:only&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt; &lt;span class="symbol"&gt;:create&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:new_comment&lt;/span&gt; &lt;span class="punct"&gt;],&lt;/span&gt; &lt;span class="symbol"&gt;:add_flash&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:error&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Operation Failed&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;},&lt;/span&gt; &lt;span class="symbol"&gt;:redirect_to&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:index&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;verify&lt;/span&gt; &lt;span class="symbol"&gt;:method&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:delete&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:only&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt; &lt;span class="symbol"&gt;:destroy&lt;/span&gt; &lt;span class="punct"&gt;],&lt;/span&gt; &lt;span class="symbol"&gt;:add_flash&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:error&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Operation Failed&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;},&lt;/span&gt; &lt;span class="symbol"&gt;:redirect_to&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:index&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I test this in my specs using this in the MySpecHelper Module&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;controller_actions_should_fail_with_get&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;cont&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;except&lt;/span&gt;&lt;span class="punct"&gt;=[])&lt;/span&gt;
    &lt;span class="ident"&gt;actions_to_test&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;get_all_actions&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;cont&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;reject&lt;/span&gt;&lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;except&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="ident"&gt;actions_to_test&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="comment"&gt;#puts &amp;quot;... #{a}&amp;quot;&lt;/span&gt;
      &lt;span class="ident"&gt;get&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt;
      &lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;redirect_to&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;http://test.host/&lt;span class="expr"&gt;#{cont.to_s.pluralize}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
      &lt;span class="ident"&gt;flash&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:error&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Operation Failed&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and an example of its use in a spec...&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;actions should fail if not post or put&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;controller_actions_should_fail_with_get&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:event&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;show&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;edit&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;'])&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;                                                                                     &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now whenever I add an action, the default is that it will fail with a
GET, unless I add it to the exclude list in the spec, this will remind
me to check if the action required PUT, POST or DELETE instead and to
add it to the verify if so or add it to the specs exclude list if not.&lt;/p&gt;

&lt;p&gt;These automatic tests keep me honest, especially in the last case
where you really don't want a GET to be able to delete something.&lt;/p&gt;

&lt;p&gt;I hope this pattern is useful to you.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://technorati.com/tag/rspec+controllers" rel="tag"&gt;&lt;/a&gt;
&lt;a href="http://technorati.com/tag/rspec+rails" rel="tag"&gt;&lt;/a&gt;
&lt;a href="http://technorati.com/tag/rspec" rel="tag"&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 28 Jul 2007 14:23:07 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:d49575f0-142f-4311-b52f-380bcedf63e9</guid>
      <author>Jim Morris</author>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller</link>
      <category>RSpec</category>
      <category>Rails</category>
      <category>rails</category>
      <category>rspec</category>
      <category>controllers</category>
      <trackback:ping>http://blog.wolfman.com/articles/trackback/336</trackback:ping>
    </item>
    <item>
      <title>"RSpec testing all actions of a controller" by eknok(maiklilangangemailaddressko@yahoo.com)</title>
      <description>&lt;p&gt;how could i test these codes?  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;before_filter :login_required, :only =&amp;gt; [:show, :edit, :update]
 skip_before_filter :store_location_filter
 after_filter(:create_referral_point, :only =&amp;gt; :activate)&lt;/code&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 19 May 2008 01:20:45 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:16a74b2b-16cf-4fe4-8931-6a72b06136c0</guid>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller#comment-215</link>
    </item>
    <item>
      <title>"RSpec testing all actions of a controller" by brian</title>
      <description>&lt;p&gt;Does anyone have a example put that works on their controller?  I can't get any updates to work using put.  Get, and Post work fine.   I also can't find any examples online that actually have the code that does it.  This example uses puts ....  and assumes that it works... 
I get a nil.downcase with no idea where/how to find it.  The actually code manually tests fine and the services works from XML or the screens using html.  Any put examples out there?&lt;/p&gt;</description>
      <pubDate>Mon, 04 Feb 2008 14:16:53 -0800</pubDate>
      <guid isPermaLink="false">urn:uuid:79f17bbb-d373-46d9-8159-543c027a2ae2</guid>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller#comment-197</link>
    </item>
    <item>
      <title>"RSpec testing all actions of a controller" by Chris O'Sullivan</title>
      <description>&lt;p&gt;This is pretty fantastically sweet&lt;/p&gt;

&lt;p&gt;I did however have to change the &lt;code&gt;get_all_actions&lt;/code&gt; method to use camelize rather than capitalize so that my multiword controllers would work.&lt;br /&gt;
i.e:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;c= Module.const_get(cont.to_s.pluralize.capitalize + "Controller")&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;becomes&lt;/p&gt;

&lt;p&gt;&lt;code&gt;c= Module.const_get(cont.to_s.pluralize.pluralize + "Controller")&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So I can call the method with 'user_account' and it finds the appropriate UserAccountController&lt;/p&gt;</description>
      <pubDate>Tue, 11 Dec 2007 06:38:18 -0800</pubDate>
      <guid isPermaLink="false">urn:uuid:cae8fa30-6527-4796-bc95-b8f6b6c6ee06</guid>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller#comment-183</link>
    </item>
    <item>
      <title>"RSpec testing all actions of a controller" by Dibi store</title>
      <description>&lt;p&gt;i use this for having all the actions of my controller:
  &lt;code&gt;(Admin::UsersController.public_instance_methods -   ApplicationController.public_instance_methods).each do |action|....&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I think is very simple, anyway your solution is cool&lt;/p&gt;</description>
      <pubDate>Sun, 21 Oct 2007 06:13:24 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:30c9c838-0e64-436c-8460-010df821b981</guid>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller#comment-155</link>
    </item>
    <item>
      <title>"RSpec testing all actions of a controller" by wolfmanjm</title>
      <description>&lt;p&gt;To see examples of normal RSpec usage for a controller goto their web page, they have plenty of examples under the Rails section. This Blog is about testing all actions in a given controller,which is an advanced topic, and not everyone will need to do this.&lt;/p&gt;</description>
      <pubDate>Sat, 01 Sep 2007 15:24:11 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:164ab68f-38e2-472c-838b-93629389616d</guid>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller#comment-138</link>
    </item>
    <item>
      <title>"RSpec testing all actions of a controller" by shaikriyaz@hexaware.com</title>
      <description>&lt;p&gt;Hi can i have a sample rspec examples  which depicts how to test one controller file.
The rspec given above is a bit complex i felt as a beginner.&lt;/p&gt;

&lt;p&gt;Thanks in advance&lt;/p&gt;</description>
      <pubDate>Sat, 01 Sep 2007 07:59:51 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:25236bae-8070-49bd-96ac-6b57b79fa16e</guid>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller#comment-137</link>
    </item>
    <item>
      <title>"RSpec testing all actions of a controller" by Matti Kotsalainen</title>
      <description>&lt;p&gt;I tried your second approach, ie checking the routes maps but I ran into trouble with actions that route like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;POST   /users/:id/add_friend/                   {:controller=&amp;gt;"users", :action=&amp;gt;"add_friend"}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The routing greps for the id and if it isn't supplied, it won't route the request. I guess I'll have to go with your first approach.&lt;/p&gt;</description>
      <pubDate>Tue, 14 Aug 2007 07:07:46 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:543076ea-e069-40e5-9e8d-e2d1d69222f2</guid>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller#comment-128</link>
    </item>
    <item>
      <title>"RSpec testing all actions of a controller" by wolfmanjm</title>
      <description>&lt;p&gt;That shouldn't be too hard to fix, just create a map of actions to method, and call post, put or delete where appropriate with a default of get, which should throw an error if you add a new action.&lt;/p&gt;

&lt;p&gt;Another approach would be to test whatever is in your routes maps with the appropriate method.&lt;/p&gt;</description>
      <pubDate>Mon, 13 Aug 2007 15:09:25 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:e3d2ff28-0356-4e6a-b230-8b4178bb6fb0</guid>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller#comment-127</link>
    </item>
    <item>
      <title>"RSpec testing all actions of a controller" by Matti Kotsalainen</title>
      <description>&lt;p&gt;Thanks for this, it's really useful!
I've got one problem with it though. I run into a bunch of 'No route match exceptions' since it tries to call my restful contollers with GET when they are only accessible through the other operations (because of the way the routes are setup in routes.rb).&lt;/p&gt;</description>
      <pubDate>Mon, 13 Aug 2007 14:54:17 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:482b8d76-5cb8-4c55-8937-1a5920ed9445</guid>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller#comment-126</link>
    </item>
    <item>
      <title>"RSpec testing all actions of a controller" by wolfmanjm</title>
      <description>&lt;p&gt;I use the :include option because I have an action in application.rb which can only be called when logged in so needs to be tested, but it will not be found by &lt;code&gt;get_all_actions&lt;/code&gt; because that does not find inherited methods from the base class. So include is there to add those actions.&lt;/p&gt;</description>
      <pubDate>Sat, 28 Jul 2007 21:43:20 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:03421e68-78ea-4f66-a0f0-097e2f2448b3</guid>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller#comment-116</link>
    </item>
    <item>
      <title>"RSpec testing all actions of a controller" by Matt Aimonetti</title>
      <description>&lt;p&gt;Interesting, that's a very smart way of quickly writing specs to verify that you setup your authentication properly. I'm just wondering when you would use the :include method?  It seems to me that you might want to test all the actions except few. When do you need to include an action?&lt;/p&gt;

&lt;p&gt;Matt &lt;/p&gt;</description>
      <pubDate>Sat, 28 Jul 2007 17:36:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:16a14432-c6a3-4909-af78-d268715e9353</guid>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller#comment-115</link>
    </item>
    <item>
      <title>"RSpec testing all actions of a controller" by wolfmanjm</title>
      <description>&lt;p&gt;Of course this pattern can also be applied to regular rails tests as well as RSpec, and is particularly nice when used in integration tests.&lt;/p&gt;</description>
      <pubDate>Sat, 28 Jul 2007 14:31:43 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:dd3e8b55-6e34-4d03-97de-42c68a04c567</guid>
      <link>http://blog.wolfman.com/articles/2007/07/28/rspec-testing-all-actions-of-a-controller#comment-114</link>
    </item>
  </channel>
</rss>
