A major reason to have tests is to build your confidence in your code. Tested code can be proved to have a specific functionality because the tests say they do. Confidence grows from the proof. The question is, by looping through all the INEDIBLE_GOATS
, do you gain any more confidence in your code? Either way, with both positive and negative tests, you cover the relevant code. With the loop, though, you are basically exercising these lines over and over. Essentially, you are testing that List<Goat>#contains()
does what it says. Do you gain anything from that? If you trust that a List
works as it should, then no, you don't get anything additional. If, on the other hand, you are not confident that a List
works as it should, then you should have a separate test of List#contains()
to give you that confidence.
You also have to balance the number of tests with the performance of your test suite. Looping through all the INEDIBLE_GOATS
may give you a little more confidence, but if there are, say, 1.8 million of them, and running the tests takes 30 seconds longer, does that tiny additional confidence outweigh the lost time (and ensuing lost productivity).?
Finally, while INEDIBLE_GOATS
may only have a small number of elements now, theoretically, the number of inedible Goat
s may actually be infinite. It is impossible to test every potential Goat
. While in this simplified example, you may say that there won't really be infinite Goat
s, in general, we must account for infinite and near-infinite possible inputs and accept that we cannot practically test everything. We must also realize that this is a good thing. Not all inputs are equal, and trying to test everything wouldn't necessarily get us any more confidence. It is optimizing tests for confidence that makes them practical and profitable.