Skip to content

Commit c66f86f

Browse files
committed
rewrite edgecase as extensive input testing
1 parent 6a27607 commit c66f86f

File tree

1 file changed

+61
-12
lines changed

1 file changed

+61
-12
lines changed

docs/pages/principles/testing.md

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -482,21 +482,70 @@ def test_pytest(mocker):
482482
dangerous_sideffects()
483483
```
484484

485-
## Testing Edgecases
485+
## Extensive Input Testing
486486

487-
While writing unit tests, you may be tempted to test edgecases. You may have a
488-
critical private function or algorithm, which is not part of the public API (so
489-
not a good candidate for External testing) and you are concerned about many
490-
edgecases that you want to defend against using tests.
487+
The range of inputs that test cases validate is an important decision.
491488

492-
It is perfectly valid to write extensive edgecase testing for private code, but
493-
these tests should be kept separate from the unit test suite. Extensive edgecase
494-
testing makes tests long, and difficult to read (tests are documentation). They
495-
can slow down execution, we want unit tests to run first, fast, and often.
489+
When the need for extensive testing starts to conflict with the readability of
490+
test cases and their usefulness as documentation for users and other developers,
491+
the tests should be re-organized into public-facing (concise, expressive, easily
492+
readable), and technical (complex, extensive) test files.
496493

497-
- Place them in separate files from unit tests, to improve readability
498-
- [mark them](https://docs.pytest.org/en/stable/how-to/mark.html) so that they
499-
can be run as a separate test suite, after your unit test pass
494+
- To maintain readability:
495+
- tests may need to include fewer inputs
496+
- extensive edgecase testing may be moved into different sections or files
497+
- the code itself may need to be refactored
498+
- Avoid testing invalid input; the range of invalid input is infinite, and is
499+
the programming equivalent of trying to prove a negative.
500+
- Focus on inputs relevant to the code under test, and avoid testing the code in
501+
dependencies. Some integration testing of specific behaviors your code relies
502+
on is justifiable.
503+
- [Fuzz Tests](#fuzz-tests) are the best place to handle extensive and
504+
exhaustive input testing.
505+
506+
### In Public Interface Tests
507+
508+
These are the most appropriate place to test certain invalid inputs and
509+
dependencies. Public Interface tests act like a contract with users; each
510+
behavior that is tested is like a promise that users can rely on, and expect
511+
that it will not change without warning (and probably a major version bump). So
512+
any input/output and side-effects included in these tests should be considered
513+
_officially supported behavior_ and given careful consideration.
514+
515+
### In project level integration tests
516+
517+
These are a good place to handle more extensive input testing. Integration tests
518+
already tend to be more verbose, with a lot of setup and teardown, and much more
519+
behavior to cover than other kinds of tests. These are the kinds of tests that
520+
should focus on edgecases.
521+
522+
### In Unit Tests
523+
524+
Unit Tests should focus on the "happy-path" of execution. In most cases one
525+
representative example of the _expected_ input is sufficient. The test case
526+
should illustrate how the unit is expected to be used.
527+
528+
Invalid input should only be tested when the unit itself includes logic to
529+
handle that invalid input.
530+
531+
for example, this code:
532+
533+
```python
534+
def foo(x: int):
535+
return x + 1
536+
```
537+
538+
should not test its behavior when passed a string (the type annotation already
539+
covers that).
540+
541+
This code should be tested with a string, to cover the exception path.
542+
543+
```python
544+
def bar(x):
545+
if type(x) is str:
546+
raise RuntimeError("invalid input")
547+
return x + 1
548+
```
500549

501550
## Additional Types of Test Suites
502551

0 commit comments

Comments
 (0)