Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test class methods in RSPEC

I wrote a simple class method Buy.get_days(string), and is trying to test it with different text string inputs. However I feel it is very verbose.

  • Is there any more concise way to test the following?
  • Is there a equivalent of subject for methods which I can just keep passing different parameters in and check the results?
  • Is there a way to avoid the unnecessary description at each it?

thanks

 describe Buy do
   describe '.get_days' do
    it 'should get days' do
      Buy.get_days('Includes a 1-weeknight stay for up to 4 people')
      .should == 1
      end
    it 'should get days' do
      Buy.get_days('Includes a 1-night stay in a King Studio Room with stone fireplace')
      .should == 1
    end
    it 'should get days' do
      Buy.get_days('Includes 4 nights/5 days at the Finisterra Hotel for up to two adults and two children (staying in the same room)')
      .should == 4
    end
  end
end
like image 245
lulalala Avatar asked Nov 04 '11 03:11

lulalala


People also ask

How do I run a test in RSpec?

To run a single Rspec test file, you can do: rspec spec/models/your_spec. rb to run the tests in the your_spec. rb file.

Is RSpec TDD or BDD?

RSpec is a Behavior-Driven Development tool for Ruby programmers. BDD is an approach to software development that combines Test-Driven Development, Domain Driven Design and Acceptance Test-Driven Planning. RSpec helps you do the TDD part of that equation, focusing on the documentation and design aspects of TDD.

What RSpec method is used to create an example?

The describe Keyword The word describe is an RSpec keyword. It is used to define an “Example Group”. You can think of an “Example Group” as a collection of tests. The describe keyword can take a class name and/or string argument.


4 Answers

Apparently there is a described_class method.

https://www.relishapp.com/rspec/rspec-core/docs/metadata/described-class

I suppose it's cleaner than subject.class, since it doesn't introduce another . method call, which reduces readability.

Using either described_class or subject.class may be more DRY than mentioning the class explicitly in every example. But personally I think not getting the syntax highlighting that comes with mentioning the class name explicitly is kind of a bummer, and I think it reduces readability, despite it totally winning in the maintainability department.

A question arises regarding best practice:

Should you use described_class whenever possible inside and outside the .expect() method, or only within the expect() method?

like image 63
ahnbizcad Avatar answered Oct 23 '22 19:10

ahnbizcad


There isn't a subject equivalent for calling a method, so using it is the way to go here. The issue I see with your code as presented is that it doesn't actually explain what you are testing for. I would write something more like:

describe Buy do
  describe '.get_days' do
    it 'should detect hyphenated weeknights' do
      Buy.get_days('Includes a 1-weeknight stay for up to 4 people').should == 1
    end
    it 'should detect hyphenated nights' do
      Buy.get_days('Includes a 1-night stay in a King Studio Room with stone fireplace').should == 1
    end
    it 'should detect first number' do
      Buy.get_days('Includes 4 nights/5 days at the Finisterra Hotel for up to two adults and two children (staying in the same room)').should == 4
    end
  end
end

I'm making assumptions about what you're after here, but hopefully the idea is clear. This will also lead to much more helpful error output when a test fails. Hope this helps!

like image 41
Matt Sanders Avatar answered Oct 23 '22 20:10

Matt Sanders


This might be an old question but you can always use subject.class to get by:

describe Buy do
  describe '.get_days' do
    it { expect(subject.class.get_days('Includes a 1-weeknight stay for up to 4 people')).to eq 1 }
  end
end
like image 23
Omar Ali Avatar answered Oct 23 '22 20:10

Omar Ali


This is an interesting though perhaps more obtuse way to use the 'subject' block with Class methods.

Edit: The broken link as reported by the Wayback Archive which I suppose is susceptible to the same problem.

like image 32
TCopple Avatar answered Oct 23 '22 20:10

TCopple