Be072eb0e9f6f81c20541150cabce3ab

This piece of code specifies that years, months and days (y(), m() and d() respectively), when put in a range with Inf iterate [at least] 20 times. My concern is that this is a testing smell because my example no longer contains a should.

"with_infinity y(2008)" doesn't really say anything about the check that is going on. How could/should I refactor this in terms of should.

Thanks in advance.

def with_infinity(date_unit)
  limit = 20
  (date_unit..Inf).each do |x|
    limit -= 1
    break if limit <= 0
  end
  limit.should == 0
end

it "should work with infinity" do
  with_infinity y(2008)
  with_infinity m(2008, 10)
  with_infinity d(2008, 10, 1)
  # TODO: add weeks here
end

Refactorings

No refactoring yet !

A8d3f35baafdaea851914b17dae9e1fc

Adam

December 22, 2008, December 22, 2008 05:44, permalink

2 ratings. Login to rate!

Here is a thought on naming conventions. I will leave the implementation up to you.

it "should work with infinity" do
  y(2008).should have_infinite_range
  m(2008, 10).should have_infinite_range
end
D41d8cd98f00b204e9800998ecf8427e

reima

December 23, 2008, December 23, 2008 03:12, permalink

2 ratings. Login to rate!

You should write a custom expression matcher. See http://rspec.rubyforge.org/rspec/1.1.11/classes/Spec/Matchers.html for details.

Be072eb0e9f6f81c20541150cabce3ab

Ollie

December 23, 2008, December 23, 2008 05:22, permalink

No rating. Login to rate!

Thanks for your comments so far. I've written a customer matcher. It read much more cleanly now but I have two concerns with it. Firstly, it's a lot of extra code and secondly, don't I need to test that the matcher is working correctly? I did a quick smoke test by forcing it to break early (see commented line) that suggests it is doing it's job but I don't really know.

module CustomMatchers
  
  def enumerate_infinitely_with_inf
    EnumerateInfinitelyWithInf.new
  end

  class EnumerateInfinitelyWithInf
    
    attr_accessor :test_times
    
    def initialize
      @test_times = 50
    end
    
    def matches?(date_unit)
      @date_unit = date_unit
      (@date_unit..Inf).each do |x|
        @test_times -= 1
        #break # early to smoke test this matcher
        break if @test_times <= 0
      end
      @test_times == 0
    end
    
    def failure_message
      "#{@date_unit} should enumerate infinitely with Inf"
    end
    
    def negative_failure_message
      "#{@date_unit} should not enumerate infinitely with Inf"
    end
    
  end

end

describe 'range enumeration' do
  
  include CustomMatchers
  
  it "should work with infinity" do
    y(2008).should enumerate_infinitely_with_inf
    m(2008, 10).should enumerate_infinitely_with_inf
    d(2008, 10, 1).should enumerate_infinitely_with_inf
  end

end
Be072eb0e9f6f81c20541150cabce3ab

Ollie

December 23, 2008, December 23, 2008 07:13, permalink

No rating. Login to rate!

Whoops! I missed this feature of RSpec. Happy now. :-)

def enumerate_infinitely_with(expected)
    simple_matcher('enumerate infinitely with') do |given, matcher|
      matcher.failure_message = "expected #{given} to enumerate infinitely with #{expected}"
      matcher.negative_failure_message = "expected #{given} not to enumerate infinitely with #{expected}"
      test_times = 50
      (given..expected).each do |x|
        test_times -= 1
        break if test_times <= 0
      end
      test_times == 0
    end
  end
Bd6a347f200c1aae37075eb3968e7bf9

Mouna

July 7, 2009, July 07, 2009 14:03, permalink

No rating. Login to rate!

Hi all. The world tolerates conceit from those who are successful, but not from anybody else.
I am from Australia and bad know English, give please true I wrote the following sentence: "Civil partnership dissolution by andrew marshallcivil partnerships came into operation in the united kingdom in december."

THX :(, Mouna.

123456

Your refactoring





Format Copy from initial code

or Cancel