New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Single expectation test #5
Comments
This can, however, be the bane of performant testing. |
I'm fairly new and inexperienced with Rspec and especially where there is some significant set up it can make it very slow. I have sometimes written as separate tests during TDD, got it working and then written a combined test to leave running in CI process/automatic testing and commented out the separate tests. If the combined test fails I can quickly activate the separate tests to find the exact issue. |
I sometimes use an assertion to verify that the conditions are right for the test to be valid. For instance, on one project, we had a very complicated set of fixtures, in several related models. There were about a dozen devs, so we were often stepping on each other's fixtures. When I tested a scope, I would usually do "it finds only those that fit" and "it omits only those that don't fit", by looping through the found or omitted records, and verifying that they fit or not. However, this tactic depends on there being ANY records that do or don't fit. So, I preceded the loop with a test that the set contained at least one record. One of our pull-request-approvers regularly made the perfect the enemy of the good, strictly enforcing "one assert per test", and rejected that style, so I made the existence-check a separate test, much slower. (To those who say putting the assertion in a loop was already a violation, yes I could have set a flag upon error and checked it at the end of the loop, but that cuts out a lot of clue about which record violated it. Yes, I could have initted something to nil and set it to the offending record's id on error, but still....) |
I think this best practice, as written, is misleading and not helpful. Here's what I'd say instead:
As in all things, software engineering is about tradeoffs, and this is no exception. It's bad to encourage cargo-cult thinking here. |
+1 to @myronmarston |
1 similar comment
+1 to @myronmarston |
One of the primary reasons for the "single assertion per test" is to provide easy and understandable traceability for what caused the failure, and keep multiple errors from mingling together and confusing this feedback. |
👍 to @myronmarston |
Later you make the point that you should have custom matchers. That is actually a very pragmatic suggestion that accomplishes a similar goal to this suggestion. |
+1 to @myronmarston |
Updated using the @myronmarston description. |
GOOD (NOT ISOLATED) should say BAD (NOT ISOLATED) |
+1 to @myronmarston (I was going to say exactly that :D) |
Please consider updating this spec as |
Why so? The text states that it should say 'GOOD', so why do you think it isn't? You could be right of course, but why? |
+1 @coreyhaines |
Guys, if you think of any change, please send us a pull request with the update. |
Where,and in which versions, is the |
@dcorking -- |
@andreareginato according to Myron's reply, the message is |
Yep. It was a typo. Sorry for that. Now it's up and running with the needed corrections. |
In this example, I just want to test that some action gives me the color blue. But the only way I have to test that it's blue is by its RBG components. If I don't break the single expectation test pattern, I loose the "why" I have this test. It is important for me that the reason I want this is that I want to make sure the color is some kind of blue. What is wrong with this reasoning? |
Absolutely nothing. Your example is specifying one behavior, and that's what's important. The fact that it takes 3 expectations to do isn't particularly important. That said, in RSpec 3.1+, you could use a single expectation: expect(subject.RGB).to have_attributes(
R: a_value < 0.2,
G: a_value < 0.2,
B: a_value > 0.8
) |
FYI the example method |
@coreyhaines would you agree that The "not isolated" example could be updated to include it: it 'creates a resource', :aggregate_failures do
expect(response).to respond_with_content_type(:json)
expect(response).to assign_to(:resource)
end Relevant docs: https://www.relishapp.com/rspec/rspec-expectations/v/3-3/docs/aggregating-failures |
See also post about single-expecation-fetish:
|
Hi, i have a question. |
@zameo94
|
@akz92 thank you |
Write your thoughts about the "single expectation test" best practice.
The text was updated successfully, but these errors were encountered: