With the inputs, outputs, and boundaries properly dissected, we can generate concrete test cases. Ideally, we would combine all the partitions we’ve devised for each of the inputs. The example has four categories, each with four or five partitions: the str
category with four partitions (null string, empty string, string of length 1, and string of length > 1), the open
category with four partitions (the same as str
), the close
category with four partitions (also the same as str
), and the (str
, open
, close
) category with five partitions (string does not contain either the open
or close
tags, string contains the open
tag but does not contain the close
tag, string contains the close
tag but does not contain the open
tag, string contains both the open
and close
tags, string contains both the open
and close
tags multiple times). This means you would start with the str
null partition and combine it with the partitions of the open
, close
, and (str
, open
, close
) categories. You would end up with 4 × 4 × 4 × 5 = 320 tests. Writing 320 tests may be an effort that will not pay off.
In such situations, we pragmatically decide which partitions should be combined with others and which should not. A first idea to reduce the number of tests is to test exceptional cases only once and not combine them. For example, the null string partition may be tested only once and not more than that. What would we gain from combining null string with open
being null, empty, length = 1, and length > 1 as well as with close
being null, empty, length = 1, length > 1, and so on? It would not be worth the effort. The same goes for empty string: one test may be good enough. If we apply the same logic to the other two parameters and test them as null and empty just once, we already drastically reduce the number of test cases.
There may be other partitions that do not need to be combined fully. In this problem, I see two:
- For the string of length 1 case, given that the string has length 1, two tests may be enough: one where the single character in the string matches
open
andclose
, and one where it does not. - Unless we have a good reason to believe that the program handles
open
andclose
tags of different lengths in different ways, we do not need the four combinations of (open length = 1, close length = 1), (open length > 1, close length = 1), (open length = 1, close length > 1), and (open length > 1, close length > 1). Just (open length = 1, close length = 1) and (open length > 1, close length > 1) are enough.
In other words, do not blindly combine partitions, as doing so may lead to less relevant test cases. Looking at the implementation can also help you reduce the number of combinations. We discuss using the source code to design test cases.
In the following list, I’ve marked with an [x] partitions we will not test multiple times:
str
—Null string [x], empty string [x], length = 1 [x], length > 1open
—Null string [x], empty string [x], length = 1, length > 1close
—Null string [x], empty string [x], length = 1, length > 1str
—Null string [x], empty string [x], length = 1, length > 1- (
str
,open
,close
)—String does not contain either theopen
or theclose
tag, string contains theopen
tag but does not contain theclose
tag, string contains theclose
tag but does not contain theopen
tag, string contains both theopen
andclose
tags, string contains both theopen
andclose
tags multiple times
With a clear understanding of which partitions need to be extensively tested and which ones do not, we can derive the test cases by performing the combination. First, the exceptional cases:
- T1:
str
is null. - T2:
str
is empty. - T3:
open
is null. - T4:
open
is empty. - T5:
close
is null. - T6:
close
is empty.
- T7: The single character in
str
matches theopen
tag. - T8: The single character in
str
matches theclose
tag. - T9: The single character in
str
does not match either theopen
or theclose
tag. - T10: The single character in
str
matches both theopen
andclose
tags.
Now, str length > 1, open
length = 1, close
= 1 :
- T11:
str
does not contain either theopen
or theclose
tag. - T12:
str
contains theopen
tag but does not contain theclose
tag. - T13:
str
contains theclose
tag but does not contain theopen
tag. - T14:
str
contains both theopen
andclose
tags. - T15:
str
contains both theopen
andclose
tags multiple times.
Next, str length > 1, open
length > 1, close
> 1 :
- T16:
str
does not contain either theopen
or theclose
tag. - T17:
str
contains theopen
tag but does not contain theclose
tag. - T18:
str
contains theclose
tag but does not contain theopen
tag. - T19:
str
contains both theopen
andclose
tags. - T20:
str
contains both theopen
andclose
tags multiple times.
Finally, here is the test for the boundary:
We end up with 21 tests. Note that deriving them did not require much creativity: the process we followed was systematic. This is the idea!
Leave a Reply