4 ms·
> The specification goes in the test title and if necessary, a comment. Then the programmer writes code to test the spec. I've never understood what is suboptim
by judofyr 5y ago
> The specification goes in the test title and if necessary, a comment. Then the programmer writes code to test the spec. I've never understood what is suboptimal about this. Why do developers need to be tricked?
I think there's a combination of things in play here which caused RSpec to take off:
- RSpec's matchers were a bit more expressive than the built-in assertions. This meant not only that you could write "should_be_greater" and when an error occurs it would present it in a much nicer way ("expected result to be greater than X, got Y") than the simple "assert".
- For many people when getting started with TDD/BDD it does help to start from a library/toolkit which has the concepts built-in. A good example is being able to actually write full sentences for the test name instead of being forced to summarize in snake_case.
That said, I do find the current RSpec expectation syntax to be annoying and over complicated. And that's not because I don't like DSL, but because I think that this DSL is focused on making it readable as an English sentence instead of trying to build its own language with its own primitives.
Example:
expect(result).to eq(3)
- `eq(3)` I can understand: This creates an assertion. This knows how to validate the value and how to format the error message. Having these as standalone objects seem to allow some pretty cool usages.
- However, what is expect()? What does it return? What does that object represent? Why is there a to() method? What other methods are on `to`? It seems to me that this could have been solved by a single method: expect_match(result, eq(3)). Yes, it doesn't read as an English sentence, but it's easy to understand the components: You have the assertion which is a standalone object, and then you have the `expect_match` which checks a result against that assertion. `expect_match` belongs to the test runner because we want it to fail the test if the assertion fails.
And when you look at comparisons it's even worse:
expect(actual).to be > expected
I've been writing Ruby for over 10 years and immediately I struggle to parse this line. I guess `be` is a local method (coming from what module?) which returns an object whose only purpose is to convert operators into an assertion? To make things even more confusing, you can also write `expect(actual).to be`, but that is something completely different (it passes when the result is truthy).
And here's the problem: The be() method doesn't actually serve any useful purpose in the "language" of matchers. It doesn't provide anything that couldn't have been accomplished within the existing framework. It's only there as a placeholder to make the whole expression read as an English sentence instead of `expect_match(result, gt(3))`.
- masklinn 5y ago> It seems to me that this could have been solved by a single method: expect_match(result, eq(3)). Except now you've circled back to the issue rspec originally tried to solve: getting the result and the reference in the correct order. While I care very little about rspec, that is definitely one thing to be said for it: the matcher system makes it extremely obvious and regular: you `expect` a (result) to (match) a (reference).