5 ms·
OP asked how any state change would be tested with a single 'assertion' and I provided an answer. Absolute rules are stupid, but our codebase has just short of
by mollerhoj 4y ago
OP asked how any state change would be tested with a single 'assertion' and I provided an answer. Absolute rules are stupid, but our codebase has just short of 10k tests, and very few have more than one assertion.
The only reason I can really see to have more than one assertion would be to avoid having to run the setup/teardown multiple times. However, its usually a desirable goal to write code that require little setup/teardown to test anyways because that comes with other benefits. Again, it might not be practical or even possible, but that goes of almost all programming "rules"..
- dd82 4y agoone assert per test seems... as you said, indicative of zealotry. if you already have your object there, why not test for the changes you expect? So you have one test that indicates that a log error is outut. then another that tests that the property X in the return from the error is what you expect. then another test to determine that propery Y in return is what you expect? that to me is wasteful, unclear, bloated. About the only useful result I can see that is it allows bragging about how many tests a project has.
- mannykannot 4y agoFurthermore, if you have a one-assertion rule, some bright spark will realize he can write a single assertion that checks for the conjunction of all the individual postconditions. That's one way to get dogma-driven assertion roulette, as you will not know which particular error occurred.
- seadan83 4y agoIf all assertions are at the end of the test, then yes. Sometimes this can be made nice with custom matchers, eg: assertThat(fooReturningOptional(), isPresentAndIs(4)) Or assertThat(shape, hasAreaEqualTo(10)) Or AssertThat(polygonList, hasNoIntersections()) Custom matchers can go off the deep end really easily. One of those cases of learn the principle, then learn when it does not apply
- jeremyjh 4y agoIf two tests call the same method with the same setup and arguments just to assert two different outcomes I would suggest that is the code smell.
- dd82 4y agoYep, but that seems to be the prevailing convention being asserted (pun intended) by many commenters.
- philliphaydon 4y agoIf there’s 2 tests which are identical but assert 2 different things. It should be a single test with 2 assertions. Can always refactor to 2 tests if the test setup changes and the assertions begin to differ or become too complex.
- mannykannot 4y agoThe amount of setup and teardown necessary to test something is a property of the system under test. It is not susceptible to one's opinion as to how things should be.
- mollerhoj 4y agoThere are usually different ways to design a system. Its often the case that designing the system such that it is easy to test (with little setup/teardown) has other benefits too. E.g. It often indicates low coupling and a more simple design. That being said, there can of course me other tradeoffs e.g. performance and even cases where simple test setups are downright impossible.
- scruple 4y agoInteresting. Our (Rails) codebase is around 25,000 tests and less than half have a single assertion. Personally, there's some calculus in my head when I'm writing a test that determines if/when the scenario I'm testing needs multiple assertions.
- mollerhoj 4y agorspec or minitest? ;-) Could rspecs 'expect change' idiom be the difference? I find that reducing assertions per spec where I can a good guideline. E.g. combining expect(foo['a']).to eq(1) and expect(foo['b']).to eq(2) into expect(foo).to include('a' => 1, 'b' => 2) yields better error messages.