This should have an easy answer but I'm struggling to find it (have checked RSpec documentation, EverydayRails Testing with RSpec, Google results). In my model specs I like to include basic attribute specs as follows:
describe Foo do
describe "basic attributes" do
before { @foo = create(:foo) }
subject { @foo }
it { should be_valid }
it { should respond_to(:color) }
it { should respond_to(:height) }
it { should respond_to(:some_other_attribute) }
it { should respond_to(:you_get_the_idea) }
...
I like these specs because if there is some kind of error within my factory and/or model these specs help me pinpoint it quickly.
I've incorporated the expect
syntax into all other specs and I like how it reads, but how to use it here? One option might be
expect(@foo).to respond_to(:color)
And another might be
expect(it).to respond_to(:color)
The former involves duplication that is avoided with the should
syntax, but the latter looks strange to me (which could just be me).
I realize this question is more about style than functionality*, but we Ruby developers are conscientious about style, and I want to adhere to standard practices and have readable, idiomatic code. Any help is appreciated. Thanks.
UPDATE: Neither of my proposed options actually work, by the way. They both throw undefined method 'expect'
errors. Now I'm really confused!
Having thought about the error, I realize it's because the should
specs above are within one-line block. The confusion, then, is how can I write a single-line block with the expect syntax? In light of this update, the question is very much about functionality and I'll be excited to hear others' thoughts.
4/2015 UPDATE
rspec > 3.0
has added yet another way of handling these, and it sounds like rspec ~> 4.0
will do away with the should
syntax. Per Myron Masters:
Some users have expressed confusion about how this should relates to the expect syntax and if you can continue using it. It will continue to be available in RSpec 3 (again, regardless of your syntax configuration), but we've also added an alternate API that is a bit more consistent with the expect syntax:
describe Post do
it { is_expected.to allow_mass_assignment_of(:title) }
end
is_expected is defined very simply as expect(subject) and also supports negative expectations via is_expected.not_to matcher. [...]
In RSpec 3, we've kept the should syntax, and it is available by default, but you will get a deprecation warning if you use it without explicitly enabling it. This will pave the way for it being disabled by default (or potentially extracted into a seperate gem) in RSpec 4, while minimizing confusion for newcomers coming to RSpec via an old tutorial.
Myron Marston, one of the core RSpec committers, explains here that you should still use
it { should be_cool }
If you've disabled the should
syntax, he offers a solution to alias expect_it
to it
:
RSpec.configure do |c| c.alias_example_to :expect_it end RSpec::Core::MemoizedHelpers.module_eval do alias to should alias to_not should_not end
With this in place, you could write this as:
describe User do expect_it { to be_valid } end
I don't think there's a correct answer to this question, but I've been recently rewriting my test suites to move away from should
and use the expect
syntax exclusively, so I'll throw my two cents in. I decided to re-write pretty much because Myron Marston, the RSpec lead maintainer, wrote:
In the future, we plan to change the defaults so that only expect is available unless you explicitly enable should. We may do this as soon as RSpec 3.0, but we want to give users plenty of time to get acquianted with it.
He also commented:
We have no plans to ever remove "should"...but expect has fewer gotchas, and is the syntax I would recommend for new projects.
I do agree with Mark Rushakoff's answer as well, but personally I don't want to have to create those aliases just to keep a single it
-block style syntax. So, using your example, where originally I wrote a model spec like your example in this form:
describe Foo do
let(:foo) { create(:foo) }
subject { foo }
describe "model attributes" do
it { should be_valid }
it { should respond_to(:color) }
it { should respond_to(:height) }
it { should respond_to(:some_other_attribute) }
it { should respond_to(:you_get_the_idea) }
end
# ...
end
I now would tend to write it like:
describe Foo do
let(:foo) { create(:foo) }
specify "model attributes" do
expect(foo).to be_valid
expect(foo).to respond_to(:color)
expect(foo).to respond_to(:height)
expect(foo).to respond_to(:some_other_attribute)
expect(foo).to respond_to(:you_get_the_idea)
end
# ...
end
My opinion is that referencing foo
directly in expect(foo).to respond_to(:color)
is as much "duplication" as referencing a subject
indirectly using it
, so I'm not too phased about it, and I'm warming to the way that expect
specs generally read. But, ultimately I think this comes down to just being an issue of preferred writing style.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With