Q. Definition? A. E.g. for an int, test its "categorical" variants (negative, zero, positive). | Cue | Type | Boundary | | -------------- | ------------------- | -------------------------------------------------- | | `func(str)` | String | Domain relevant, empty, whitespace, unicode chars | | `func(int)` | Number | Negative, zero, positive | | | **––Collections––** | | | `func(enum.M)` | Enum | Each value | | `func(iter)` | Iterator | Empty, single element, multiple elements, mutation | | `func(list)` | List | Those of an [[Iterator]] + ordered/shuffled | | `func(dict)` | Map | Those of an [[Iterator]] + key-collisions. | Rowwise // Which boundary cases do you want to test for |Type|s? // |Boundary| Rowwise // |Cue|; which boundaries to test? // |Boundary| Rowwise // Which boundary cases do you want to handle for |Type|s? // |Boundary| --- Q. How you find out which [[Boundary test|Boundary case]]s to unit test? A. Look primarily at the input, and use domain knowledge to know which boundaries to test. Q. Why should the [[Boundary test|Boundary case]]s you test in units ideally be without looking at the implementation? A. It nudges you to test functionality, instead of implementation; makes it more stable. Q. Why do we want to avoid strings as arguments to functions? A. It makes [[Boundary test]] incredibly hard, and allows for many more errors (e.g. typos).