$ rspec ~/insane-magic.spec
F
Failures:
1) Rspec should not allow you to make shit up
Failure/Error: [1, 2, 3].should have(4).potatoes
expected 4 potatoes, got 3
# /Users/graham/insane-magic.spec:5
Finished in 0.00042 seconds
1 example, 1 failure
Do you see the potatoes
method call? Why isn't Ruby complaining that
it doesn't exist? Where the hell did it come from? Is it part of rspec?
It must be, surely. That's the only library I've required!
[Goes off to grep the rspec gems for "potatoes"... doesn't find it]
What's happening here? RSpec is purposefully ignoring .potatoes
, which
is a method call on the object returned by #have
. And what is that
object, exactly?
So RSpec (and this "BDD" business) is good for people new to testing you say? Really?
The "call any method you like and we'll silently ignore it" behaviour is not syntactic sugar, it's pain and confusion for people who are new to programming. It's a bloody daft idea to put it forward as good practice in a widely popular library.
Some bad ideas catch on just as easily as good ideas, and this approach is its own special breed of footgun.
To be clear, I like describe
and it
. But you can stop there; I feel
RSpec's features have a negative impact on productivity from there on
in.
And for comparison, the Contest gem adds support for these blocks to test/unit in 100 lines of code.
I suspect many more libraries are susceptible to the reductio ad absurdum attack, though :)
RSpec makes it easier to do stupid stuff, for sure. I also think that when used well, the resulting code makes far more immediate sense with less cognitive overhead at 17.30 on a Friday afternoon when you're sleepy after a nice lunchtime pie. It might be the case that it's just what I got used to, having skipped Test::Unit and coming to it straight from C#/MSpec.
[1, 2, 3].should have(3).numbers
makes sense to me - it requires zero parsing beyond what I already do for English, whereasassert_equal(3, [1,2,3].length)
always leaves me having to expend at least a small amount of energy to get to a mental model of "[1,2,3] should have 3 numbers". I'd prefer not to have the parsing overhead, especially if I'm taking in a dozen failures at a time.Of course, this is all rationalisation from me having a blind spot remembering the sequence of
actual, expected
in anassert_equal
and finding remembering thathave(n)
returns a matcher andshould
is mixed into everything is much easier than forcing myself to internalise a different and unnatural order for subject -> predicate -> object. Just wired that way, I suppose.But I also like stuff like
and too often I see an equivalent Test::Unit suite of
In a CI environment, when that test fails, do you know which assertion failed? Do you care? Does it help to know? Maybe not in this contrived example, but how about if there were a dozen asserts? Does Test::Unit have an equivalent of the RSpec version where the code under test is called once and multiple identifiable assertions are made (is it Contest)? If so, why doesn't it get used more? If it exists, I'll try Test::Unit on my next project and report back.
Wow. Sorry that was so long. I probably could just have said "it's a matter of taste" ;)
EDIT: please allow me to admit that a lot of this response didn't have anything to with the
have(n)
matcher and was mostly for @techbelly