Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6845687
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 27, 20262026-05-27T00:31:52+00:00 2026-05-27T00:31:52+00:00

I often find that in writing tests for a method I want to throw

  • 0

I often find that in writing tests for a method I want to throw a bunch of different inputs at the method and simply check whether the output is what I expected.

As a trivial example, suppose I’m testing my_square_function which squares numbers and intelligently handles nil.

The following code seems to do the job, but I’m wondering whether there’s a best practice that I should be using (e.g. using subject, context):

describe "my_square_function" do
  @tests = [{:input => 1, :result => 1},
            {:input => -1, :result => 1},
            {:input => 2, :result => 4},
            {:input => nil, :result => nil}]
  @tests.each do |test|
    it "squares #{test[:input].inspect} and gets #{test[:result].inspect}" do
      my_square_function(test[:input]).should == test[:result]
    end
  end
end

Suggestions?

Thanks!

(Related: rspec refactoring?)

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-27T00:31:53+00:00Added an answer on May 27, 2026 at 12:31 am

    Sorry for such a long answer, but I thought my thought process would be more coherent if I went through it all.

    Since this question is tagged with TDD, I’ll assume you are writing the method TDD style. If that it the case, you may want to start with:

     describe "my_square_function" do
       it "Squares a positive number" do
         my_square_function(1).should == 1
       end
     end
    

    Having a failing test, you may implement my_square_function as follows:

     def my_square_function(number)
       1
     end
    

    Now that the test is passing you want to refactor out duplication. In this case, the duplication is between the code and the test, that is the literal 1. Since argument carries the value of the test, we can remove the duplication by using the argument instead.

     def my_square_function(number)
       number
     end
    

    Now that duplication has been removed and the tests still pass, we can move to the next test:

     describe "my_square_function" do
       it "Squares a positive number" do
         my_square_function(1).should == 1
       end
    
       it "Squares a negative number" do
         my_square_function(-1).should == 1
       end
     end
    

    Running the tests you are again greeted with a failing test, so we make it pass:

     def my_square_function(number)
       number.abs   # of course I probably wouldn't really do this but
                    # hey, it's an example. :-)
     end
    

    Now this test passes and it’s time to move on to another test:

     describe "my_square_function" do
       it "Squares a positive number" do
         my_square_function(1).should == 1
       end
    
       it "Squares a negative number" do
         my_square_function(-1).should == 1
       end
    
       it "Squares other positive numbers" do
         my_square_function(2).should == 4
       end
     end
    

    At this point, your newest test will no longer pass, so now to make it pass:

     def my_square_function(number)
       number.abs * number
     end
    

    Oops. That didn’t quite work, it caused our negative number test to fail. Fortunately the failure pointed us back to the exact test that didn’t work, we know it failed due to the “negative” test. Back to the code:

     def my_square_function(number)
       number.abs * number.abs
     end
    

    That’s better, all of our tests pass now. It’s time to refactor again. Here we see some other uneccessary code in those calls to abs. We can get rid of them:

     def my_square_function(number)
       number * number
     end
    

    The tests still pass and we see some more duplication with that pesky argument. Let’s see if we can get rid of it:

     def my_square_function(number)
       number ** 2
     end
    

    The test pass and we don’t have that duplication any longer. Now that we have a clean implementation, let’s handle the nil case next:

     describe "my_square_function" do
       it "Squares a positive number" do
         my_square_function(1).should == 1
       end
    
       it "Squares a negative number" do
         my_square_function(-1).should == 1
       end
    
       it "Squares other positive numbers" do
         my_square_function(2).should == 4
       end
    
       it "Doesn't try to process 'nil' arguments" do
         my_square_function(nil).should == nil
       end
     end
    

    Ok, we’re back to failing again and we can go ahead and implement the nil check:

     def my_square_function(number)
       number ** 2 unless number == nil
     end
    

    This test passes and it’s pretty clean, so we’ll leave it as is. Now we go back to the spec and see what we’ve got and verify we like what we see:

     describe "my_square_function" do
       it "Squares a positive number" do
         my_square_function(1).should == 1
       end
    
       it "Squares a negative number" do
         my_square_function(-1).should == 1
       end
    
       it "Squares other positive numbers" do
         my_square_function(2).should == 4
       end
    
       it "Doesn't try to process 'nil' arguments" do
         my_square_function(nil).should == nil
       end
     end
    

    My first inclination is that we’re really describing the behavior of “squaring” a number, not the function itself, so we’ll change that:

     describe "How to square a number" do
       it "Squares a positive number" do
         my_square_function(1).should == 1
       end
    
       it "Squares a negative number" do
         my_square_function(-1).should == 1
       end
    
       it "Squares other positive numbers" do
         my_square_function(2).should == 4
       end
    
       it "Doesn't try to process 'nil' arguments" do
         my_square_function(nil).should == nil
       end
     end
    

    Now, the three example names are a little squishy when put into that context. I’m going to start with the first example, it seem’s a little cheesy to square 1. This is a choice I’m going to make to reduce the number of examples in the code. I really want the examples to be interesting in some fashion or I won’t test them. The difference between squaring 1 and 2 is uninteresting so I’ll remove the first example. It was useful at first, but not any longer. That leaves us with:

     describe "How to square a number" do
       it "Squares a negative number" do
         my_square_function(-1).should == 1
       end
    
       it "Squares other positive numbers" do
         my_square_function(2).should == 4
       end
    
       it "Doesn't try to process 'nil' arguments" do
         my_square_function(nil).should == nil
       end
     end
    

    The next thing I’m going to look at is the negative example as it relates to the context in the describe block. I’m going to give it and the rest of the examples new descriptions:

     describe "How to square a number" do
       it "Squaring a number is simply the number multiplied by itself" do
         my_square_function(2).should == 4
       end
    
       it "The square of a negative number is positive" do
         my_square_function(-1).should == 1
       end
    
       it "It is not possible to square a 'nil' value" do
         my_square_function(nil).should == nil
       end
     end
    

    Now that we’ve limited the number of test cases to the most interesting ones, we don’t really have too many to deal with. As we saw above, it was nice knowing exactly which line the failures occurred on in case it was another test case that we didn’t expect to fail. By building a list of scenarios to run through we lose that feature making it harder to debug failures. Now, we could replace the examples with dynamically generated it blocks as was mentioned in another solution, however we start to lose the behavior we’re trying to describe.

    So, in summary, by limiting your tested scenarios to only those that describe interesting characteristics of the system, your need for too many scenarios will be reduced. On a more complex system having that many scenarios likely highlights that the object model probably needs another look.

    Hope that helps!

    Brandon

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I often find myself writing R scripts that generate a lot of output. I
I often find myself writing a property that is evaluated lazily. Something like: if
When I load data in my code-behind, I find that often I want to
The more I get into writing unit tests the more often I find myself
When I'm writing a method or using a member variable, I often find I
When I'm programming, I often find myself writing functions that -should- (to be proper
I often find when I'm writing a service class (within an ASP.NET app) that
Every so often I find that I have accidentally broken data binding in my
I find that quite often Visual Studio memory usage will average ~150-300 MB of
I find that the .NET event model is such that I'll often be raising

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.