How to test class methods in RSPEC
Solution 1
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.
Solution 2
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?
Solution 3
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!
Solution 4
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
Related videos on Youtube
lulalala
Ruby and Rails developer. https://github.com/lulalala/ I also worked on XSLT, and have a hobby project written in C#.
Updated on March 19, 2020Comments
-
lulalala about 4 years
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
-
Dave Newton over 12 yearsHow is the
it
description unnecessary? Just because you wrote the same text for specs that test different things doesn't mean the description shouldn't be there--maybe re-word them so they're useful? -
lulalala over 12 yearsthe input/output combination is descriptive enough (for me at least).
-
ahnbizcad about 9 yearscan you give an example of rewording to make it more useful, @DaveNewton ?
-
Dave Newton about 9 years@ahnbizcad Hopefully three different blocks, each of which
'should get days'
(e.g., they say the same thing), is an obvious smell. Why are the expectations different? There's something about them that makes the result be1
,1
, and4
. The purpose of the string arg toit
is to describe in human-readable terms what the block is actually testing. I can't reword the OP's descriptions because I don't know why the blocks should return the blocks that they do.
-
lulalala over 12 yearsI guess the answer at the end is: there is no more concise way of writing it.
-
Jared Beck almost 11 yearsbroken link says "Posterous Spaces is no longer available"
-
ahnbizcad about 9 yearsGood catch! facepalm. I should have known this. This is the correct answer!
-
B Seven about 9 years
subject.class
? Wouldn't it be clearer to useBuy
? -
Dave Newton about 9 years@ahnbizcad Not really, because this shows only a single test. Think about the spec output and what it's supposed to be showing. Adding the other tests with no descriptive tests makes for essentially useless spec output because you don't know (a) what the spec is testing, and (b) what differentiates the different specs.
-
Dave Newton about 9 years@lulalala You don't want it to be concise, you want it to be accurate and descriptive in the context of the specs.
-
IAmNaN over 7 yearsFast-forward three years and the gist is here: gist.github.com/knzconnor/816049
-
DBrown over 6 yearsThis is what I prefer to use in my tests, leaving subject for the data tested through said methods.
-
Dave Newton over 4 yearsThis is one reason why link-only answers are bad.