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).