The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Increasing your testing vocabulary

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Bryan Liles

Posts: 228
Nickname: bryanl
Registered: May, 2008

Bryan Liles is the Principal Web Developer for Sourcefire, Inc.
Increasing your testing vocabulary Posted: Sep 16, 2008 7:43 PM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Bryan Liles.
Original Post: Increasing your testing vocabulary
Feed Title: Smarticus
Feed URL: http://smartic.us/feed/atom.xml
Feed Description: Ramblings of a ruby hacker
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Bryan Liles
Latest Posts From Smarticus

Advertisement

On your journey to writing better tests, there are a quite a few hurdles to overcome. One of those hurdles is improving your your vocabulary. One day I noticed I was writing better tests. I also noticed that I was actually enjoying the testing piece. What turned it around for me was getting the vocabulary right.

Let’s start at the beginning:

1
2
3

def test_new_assigns_car
end

This is where I started. As you can most likely infer from the method signature, I was attempting to test that new assigns car. What? This doesn’t really make any sense, but there are plenty of tests floating around right now named in this fashion. We can make this example better, so let’s give it another try:

1
2
3

def test_get_on_new_should_assign_to_car
end

This is better. We can now pretty accurately determine that we are testing ‘get’ on something called ‘new’ and it should assign something. If I mentioned that is was a functional test for a Ruby on Rails controller, you most likely would guess what I’m aiming for here. One lesson that you might pick up here is that is OK to give your tests extremely long method names. When it comes down to it, the more verbose the better, right? It might sound good at first, but extremely long test method names make it difficult to read your test files, and do nothing for helping your test class organization.

So why don’t we take another stab at it? This time, we’ll incorporate Shoulda, as I use this on a daily basis:

1
2
3
4
5

context "get on new" do
  setup { get :new }
  should_assign_to :car
end

Now, we are getting to a good place. Our test code is becoming easier to read since we have introduced contexts. Contexts are one of the great points of Shoulda and RSpec alike. We can read it like, “after doing a get on action new, an instance variable car should have something assigned”. At first glance, this reads pretty easily, and for quite some while, I was stuck in this place. It isn’t a bad place, but there is still room for improvement. So, now I’m progressed my tests a bit further:

1
2
3
4
5

context "requesting the new car form" do
  setup { get :new } 
  should_assign_to :car
end

Notice the simple language change from what we are physically doing to what we are trying to accomplish. These types of changes don’t make your tests run any faster or better, but they do make them more readable and are great for increasing your testing vocabulary. We should all strive for great readability, but don’t let the quest for English like tests take you to far from what you are actually doing: writing tests.

We can now work on improving our vocabulary even further with another example. Testing ‘create’ actions for Rails controllers seems to be a straight forward set of tasks generally.

1
2
3
4
5

context "creating a new car" do
  setup { post :create, :car => {:name => "My new Car"}}
  should_redirect_to "car_url(@car)"
end

Finished? Well not quite. What happens if the car isn’t created correctly? We need some more test code:

1
2
3
4
5
6
7
8
9
10
11
12
13

context "creating a new car" do
  context "successful creation" do
    setup { post :create, :car => {:name => "My new Car"}}
    should_redirect_to "car_url(@car)"
  end
  context "failed creation" do
    setup { post :create, :car => {:name => ""}}
    should_assign_to :car
    should_respond_with :success
    should_render_template "new"
  end
end

Now, we have a more complicated example. Using nested contexts, we can group tests that are related together. If you text editor or IDE has code folding capabilities, you only have to focus on what you are doing, and you still won’t lose site of your goal.

In most cases, we might stop here, but there are still other things to think about. With Ruby on Rails, it is fairly simple to create resources that can be retrieved and manipulated in a REST like manor. We can also state the format of the reply we want just by manipulating the URL. So, in a nutshell, this means if you exposing HTML along with JSON or XML or some other data format, you’ll need to test those as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

context "creating a new car" do
  context "successful creation" do
    context "expecting HTML" do
      setup { post :create, :car => {:name => "My new Car"}}
      should_redirect_to "car_url(@car)"
    end
    context "expecting XML" do
      setup { post :create, :car => {:name => "My new Car"}, :format => "xml"}
      should_respond_with :201
      should "respond with properly formatted xml" do
        assert_xml_is_good_and_stuff
      end
    end    
  end
  context "failed creation" do
    context "expecting HTML" do
      setup { post :create, :car => {:name => ""}}
      should_assign_to :car
      should_respond_with :success
      should_render_template "new"      
    end
    context "expecting XML" do
      setup { post :create, :car => {:name => ""}}
      should_respond_with :400
    end
  end
end

We have lots of tests here. Testing positive and negative conditions with multiple formats. And notice that is no implementation here… so we did some TDB (test driven blogging) as well. From here, only your imagination or impending deadlines can limit you.

So, what can we learn from all of this? I’m sure there are multiple lessons buried somewhere in here, so I’ll let you pick the good parts from the not so good parts. I only have one goal, and that is get everyone to start expressing intent rather than the intended action when testing. If get at least that, my job is done for the day. Just remember to go after many small wins instead of swinging from the fence every time.

Thanks and TATFT

Read: Increasing your testing vocabulary

Topic: The Sapphire Programming Language - Latest News Previous Topic   Next Topic Topic: Django turns 1.0

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use