Let's say I'm trying to test a simple Set class
public IntSet : IEnumerable<int> { Add(int i) {...}
And suppose I'm trying to verify that there are no duplicate values ​​in the set. My first option is to insert some sample data into the set and check for duplicates using my knowledge of the data that I used, for example:
//OPTION 1 void InsertDuplicateValues_OnlyOneInstancePerValueShouldBeInTheSet() { var set = new IntSet(); //3 will be added 3 times var values = new List<int> {1, 2, 3, 3, 3, 4, 5}; foreach (int i in values) set.Add(i); //I know 3 is the only candidate to appear multiple times int counter = 0; foreach (int i in set) if (i == 3) counter++; Assert.AreEqual(1, counter); }
My second option is to check my condition as a whole:
//OPTION 2 void InsertDuplicateValues_OnlyOneInstancePerValueShouldBeInTheSet() { var set = new IntSet(); //The following could even be a list of random numbers with a duplicate var values = new List<int> { 1, 2, 3, 3, 3, 4, 5}; foreach (int i in values) set.Add(i); //I am not using my prior knowledge of the sample data //the following line would work for any data CollectionAssert.AreEquivalent(new HashSet<int>(values), set); }
Of course, in this example, it’s convenient for me to have an implementation for checking, as well as code for comparing collections (CollectionAssert). But what if I hadn’t? This code will definitely be more complicated than the previous version! And this is a situation when you test your business logic in real life.
Of course, testing the expected conditions in the general case covers more cases - but it is very similar to repeating the logic (which is tedious and useless - you cannot use the same code to test yourself!). Basically I ask if my tests should look like "insert 1, 2, 3 and then check something around 3" or "insert 1, 2, 3 and check something at all"
EDIT. To help me understand, please indicate in your answer if you prefer OPTION 1 or OPTION 2 (or neither one nor the other, it depends on the case, etc.). Just to clarify, it’s pretty clear that in this case ( IntSet ) option 2 is better in all aspects. However, my question relates to cases where you do not have an alternative implementation for verification, so the code in option 2 will definitely be more complicated than option 1.