TL;DR; It’s not one
assertper test, rather one logical path per test.
I find this to be a classical example of how an inappropriate choice of terminology leads to huge confusion. In trying to find the original source of the “one assertion per test” quote, google came back only with a bunch of confused blog entries :(
Without much ranting, lets see a code example to start with:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
By saying one logical path per test, I mean I’d write a total of 4 tests for this method, each covering a logical path. But I really don’t care about how many assert calls you need in each logical path to express the desired behavior. For example, this is totally fine:
1 2 3 4 5 6 7 8 9 10 11
Of course, this can indeed be converted into a single assertion, if you already had
equals method overriden for the credit cards. But, I’d probably skip adding that code if its just for the sake of writing tests.
Image taken from mchenrybowl
The mechnical thought of “one assertion per test” is lame.
- If for nothing else, these silly assertions would multipy the running time of your test suite by a factor of digits.
- Doesn’t provide you any additional coverage or safety.
- As long as each of your tests cover a unique logical path, there’s only one logical reason why it’d fail, irrespective of how many assertions you put in there.
But, there’s a but! If you need many asserts per test, the code is probably asking for some refactoring. It indicates that one logical path in your code is touching too many things. Worse, when it calls too many methods that belong to other objects. Testing such a logical path is hard, usually requires a big setup and a bigger assertion. In such cases, breaking down the test into multiple tests may yield some superficial readability of the test, but certainly works around the actual problem in the code without fixing it. Almost always, this indicates long procedural methods and I’d suggest taking a second look at it to refactor into a more OO code.