#157
Apr 13, 2009

RSpec Matchers & Macros

You can improve the readability and remove duplication in RSpec by adding matchers and macros. Learn how in this episode.
Tags: testing tools
Download (39.1 MB, 18:09)
alternative download for iPod & Apple TV (25.7 MB, 18:09)

Resources

Note: Unfortunately there are a couple problems with this episode. Special thanks to David Chelimsky for pointing them out.

  1. Since RSpec 1.2.0, the method names for failure messages are failure_message_for_should and failure_message_for_should_not. The old method names are still supported, but will be deprecating
    eventually. The code below has been updated to reflect the new method names.
  2. Newer versions of RSpec offers a 3rd method for creating a custom matcher. We can apply it to this example and it would have proper error messages. Please see the documentation for details on how this works.
# spec_helper.rb
require File.dirname(__FILE__) + "/custom_matchers"
require File.dirname(__FILE__) + "/controller_macros"
# ...
config.include(CustomMatchers)
config.include(ControllerMacros, :type => :controller)

# spec/custom_matcher.rb
module CustomMatchers
  class OneMoreThan
    def initialize(expected)
      @expected = expected
    end

    def matches?(actual)
      @actual = actual
      @actual == @expected+1
    end

    def failure_message_for_should
      "expected #{@actual.inspect} to be one more than #{@expected.inspect}"
    end

    def failure_message_for_should_not
      "expected #{@actual.inspect} not to be one more than #{@expected.inspect}"
    end
  end

  def be_one_more_than(expected)
    OneMoreThan.new(expected)
  end
end

# spec/controller_macros.rb
module ControllerMacros
  def self.included(base)
    base.extend(ClassMethods)
  end
  
  module ClassMethods
    def it_should_require_admin_for_actions(*actions)
      actions.each do |action|
        it "#{action} action should require admin" do
          get action, :id => 1
          response.should redirect_to(login_url)
          flash[:error].should == "Unauthorized Access"
        end
      end
    end
  end
  
  def login_as_admin
    user = User.new(:username => "admin", :email => "admin@example.com", :password => "secret")
    user.admin = true
    user.save!
    session[:user_id] = user.id
  end
end

# article_spec.rb
article2.position.should be_one_more_than(article1.position)

# articles_controller_spec.rb
it_should_require_admin_for_actions :new, :create, :edit, :update, :destroy

# simple matcher
def be_one_more_than(number)
  simple_matcher("one more than #{number}") { |actual| actual == number+1 }
end

RSS Feed for Episode Comments 32 comments

1. mike Apr 13, 2009 at 02:37

Do you do any testing with shoulda? after banging my head over rspec for the past few days i decided to give it a try but there is not much instruction out there. I bet this cast would have gotten me stick with rspec for a few more days if id seen it earlier. :-p


2. Clemens Kofler Apr 13, 2009 at 04:40

It should probably be noted that it's not ideal to just get every passed in action in the last macro. Instead, one might use something like the following:

http://gist.github.com/94405


3. Hongli Lai Apr 13, 2009 at 06:18

Good stuff. :) The RSpec RDoc on matchers is very confusing but your screencast is very easy to understand.


4. Jesse Newland Apr 13, 2009 at 08:54

Awesome, custom rspec matchers for Moonshine are in my backlog. You just saved me a lot of time :).


5. George Apr 13, 2009 at 09:19

Thank you very much.


6. erik Apr 13, 2009 at 10:00

Does your it_should_require_admin_for_actions test what you want it to?

In articles_controller_spec.rb, you wrote out 5 it blocks that test the actions using get, post, put, and delete, but it_should_require_admin_for_actions only runs get on each of the actions. Doesn't it need to run the correct verb on each action, or does it work the way it is?


7. Ryan Bates Apr 13, 2009 at 22:40

@Clemens, @erik, good eye, and thank you for pointing this out. I have not found any downside to using "get" at all times for testing this authentication before filter. However the solution Clements gave seems like a great way to handle this issue.


8. Jose Apr 14, 2009 at 08:57

As a new person to tests and RSpec I have a problem getting my head around one thing:

How do the tests you write get integrated back into the code of the application? And how do methods like login_as_admin get used in the application?

If I'm writing code to make tests easier, shouldn't that code also make coding the application easier?


9. Sig Apr 14, 2009 at 13:36

As always awesome reailscast.
I'm going into Rspec+Cucumber and so on right now and those last episodes are really useful.
Hope you are going to make some more on the topic.

Have a good 1 buddy.


10. Andrea Apr 14, 2009 at 15:10

As usual another great screencast, thanks Ryan.
I am especially enjoying all your recent screencasts dedicated to testing as I felt I needed some extra help on this often underestimated aspect of programming.


11. Mazembo Apr 18, 2009 at 07:00

I really appreciate your work. It helps me to improve my skills in Rails. Thanks a lot.


12. dani Apr 20, 2009 at 11:56

thanks! thanks! thanks!


13. Paul Groves Apr 28, 2009 at 06:10

At 3:07 on line 5 in the block 'action' changes to 'actual' - don't really see this as a problem, was just weird - thought I was seeing things till I wound it back.


14. Scott Apr 28, 2009 at 12:48

Great episode as usual.

I'm a little foggy on why it_should_require_admin_for_actions needs to be a class method. Is it because you're using it to generate it-blocks?


15. Марианна May 23, 2009 at 01:01

hey, what's that? i can't understand


16. mdm Jun 13, 2009 at 14:41

Very cool stuff, thanks Ryan.


17. dolly Jun 19, 2009 at 15:52

Thank you very much.Great stuff.


18. Pavlik Jun 27, 2009 at 00:34

As a new person to tests and RSpec I have a problem getting my head around one thing:

How do the tests you write get integrated back into the code of the application? And how do methods like login_as_admin get used in the application?


19. Ionka Jun 30, 2009 at 22:24

Very nice, senk


20. Romasha Jul 02, 2009 at 02:53

As always awesome reailscast.
I'm going into Rspec+Cucumber and so on right now and those last episodes are really useful.
Hope you are going to make some more on the topic.

Have a good 1 buddy.


21. Nadegdushka Jul 16, 2009 at 23:43

Don`t understand what do this code

it "#{action} action should require admin" do
          get action, :id => 1


22. Boba Jul 25, 2009 at 07:37

Very senk!


23. شات Nov 14, 2009 at 13:22

<a title="شات" href="http://www.y222y.com">شات</a>
<a title="منتديات عذاري" href="http://vb.y222y.com">منتديات عذاري</a>
<a title="دردشة الشلة" href="http://dlil.y222y.com/y222y-14065.html">دردشة الشلة</a>
<a title="دردشة دلع نجد" href="http://dlil.y222y.com/y222y-14066.html">دردشة دلع نجد</a>
<a title="دردشة البحرين" href="http://dlil.y222y.com/y222y-14072.html">دردشة البحرين</a>
<a title="دردشة روحي تحبك" href="http://dlil.y222y.com/y222y-14062.html">دردشة روحي تحبك</a>
<a title="دردشة المميزة" href="http://dlil.y222y.com/y222y-14059.html">دردشة المميزة</a>
<a title="دردشة الغلا" href="http://dlil.y222y.com/y222y-14063.html">دردشة الغلا</a>
<a title="شات تعب قلبي" href="http://dlil.y222y.com/y222y-14068.html">شات تعب قلبي</a>
<a title="شات روحي تحبك" href="http://dlil.y222y.com/y222y-14061.html">شات روحي تحبك</a>
<a title="دردشة بنت الاردن" href="http://dlil.y222y.com/y222y-14055.html">دردشة بنت الاردن</a>
<a title="شات تحب" href="http://dlil.y222y.com/y222y-14024.html">شات تحب</a>
<a title="دردشة اللوبي السعودي" href="http://dlil.y222y.com/y222y-14041.html">دردشة اللوبي السعودي</a>
<a title="شات المميزة" href="http://dlil.y222y.com/y222y-14060.html">شات المميزة</a>
<a title="دردشة شلة بنات" href="http://dlil.y222y.com/y222y-13477.html">دردشة شلة بنات</a>
<a title="دردشة الشرقية" href="http://dlil.y222y.com/y222y-13476.html">دردشة الشرقية</a>
<a title="دردشة بنات القطيف" href="http://dlil.y222y.com/y222y-13364.html">دردشة بنات القطيف</a>
<a title="دردشة قلبي" href="http://dlil.y222y.com/y222y-13687.html">دردشة قلبي</a>
<a title="دردشة احساس" href="http://dlil.y222y.com/y222y-12824.html">دردشة احساس</a>
<a title="دردشة القصيم" href="http://dlil.y222y.com/y222y-12806.html">دردشة القصيم</a>
<a title="دردشة علي بابا" href="http://dlil.y222y.com/y222y-12717.html">دردشة علي بابا</a>
<a title="دردشة دلع الكويت" href="http://dlil.y222y.com/y222y-14067.html">دردشة دلع الكويت</a>
<a title="دردشة تعب قلبي" href="http://dlil.y222y.com/y222y-5354.html">دردشة تعب قلبي</a>
<a title="دردشة كازنوفا" href="http://dlil.y222y.com/y222y-14069.html">دردشة كازنوفا</a>
<a title="دليل دردشات" href="http://dlil.y222y.com">دليل دردشات</a>
<a title="رقص بنت السعوديه" href="http://dlil.y222y.com/y222y-14129.html">رقص بنت السعوديه</a>
<a title="رقص فضيحة" href="http://dlil.y222y.com/y222y-14138.html">رقص فضيحة</a>
<a title="رقص بنات" href="http://dlil.y222y.com/y222y-14136.html">رقص بنات</a>
<a title="رقص مصري" href="http://dlil.y222y.com/y222y-14130.html">رقص مصري</a>
<a title="دردشة كويتية" href="http://dlil.y222y.com/cat-y222y-73.html">دردشة كويتية</a>
<a title="دردشة عربية" href="http://dlil.y222y.com/cat-y222y-72.html">دردشة عربية</a>
<a title="دردشة سعودية" href="http://dlil.y222y.com/cat-y222y-71.html">دردشة سعودية</a>
<a title="دردشة خليجية" href="http://dlil.y222y.com/cat-y222y-70.html">دردشة خليجية</a>
<a title="بلوتوث" href="http://dlil.y222y.com/cat-y222y-60.html">بلوتوث</a>
<a title="دردشة كتابية" href="http://dlil.y222y.com/cat-y222y-13.html">دردشة كتابية</a>
<a title="ازياء" href="http://vb.y222y.com/f2.html">ازياء</a>


24. Daniel Nov 27, 2009 at 05:38

Thanks! Recently I've been reading the RSpec beta book from Pragmatic Programmers, and it was not too much clear for me. Now I think I've finally understood how this works.


25. 上海汇菱商务咨询有限公司 Dec 08, 2009 at 23:22

消费品等行业的大型跨国公司及国内大型企


26. calc-x Dec 19, 2009 at 08:59

Thank you very much


27. brand clothing Jan 07, 2010 at 21:25

Thank you very much.


28. freerealmscoins Jan 12, 2010 at 16:41

It is very good.I like to see it.I will try it.Thank you .Have a good time.


29. wholesale nike shoes Jan 13, 2010 at 23:10

A very good article, I will always come in.


30. wholesale nike shoes Jan 13, 2010 at 23:10

A very good article, I will always come in.


31. wholesale scarves Jan 13, 2010 at 23:10

Such a good article, caught my sympathy!
-


32. low puma shoes Feb 05, 2010 at 00:32

thank you very much!!

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player
Give Back to Open Source