diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/testing.md | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/docs/testing.md b/docs/testing.md new file mode 100644 index 0000000..c6f3654 --- /dev/null +++ b/docs/testing.md @@ -0,0 +1,27 @@ +# Testing + +Run `cargo test`. + +Most of the tests for this project use an integration-based testing approach: + +* Spin up a scratch copy of the application, using an in-memory database; +* Perform operations against that database using the `app` abstraction to set up the scenario; +* Interact with route endpoint functions directly to perform the test; +* Inspect both the return values from the endpoint function to validate the results; and +* Perform additional operations against the scratch database using the `app` absraction to validate behaviour. + +Tests can vary around this theme. + +Rather than hard-coding test data, tests use `faker_rand` and similar tools to synthesize data on a run-by-run basis. While this makes tests marginally less predictable, it avoids some of the issues of bad programmer-determined static testing data in favour of bad programmer-determined random testing data. Improvements in this area would be welcome - `proptest` would be ideal. + +The code for carrying out testing interactions lives in `src/test/fixtures`. By convention, only `crate::test::fixtures` is imported, with qualified names from there to communicate the specific kinds of fixtures that a test is using. + +## Style + +Prefer writing "flat" fixtures that do one thing, over compound fixtures that do several, so that the test itself conveys as much information as possible about the scenario under test. For example, even though nearly all tests involve an app with at least one user provisioned, there are separate fixtures for creating a scratch app and provisioning a user, and no fixture for "an app and its main user." + +Prefer role-specific names for test values: use, for example, `sender` for a login related to sending messages, rather than `login`. Fixture data is cheap, so make as many entities as make sense for the test. They'll vanish at the end of the test anyways. + +Prefer testing a single endpoint at a time. Other interactions, which may be needed to set up the scenario or verify the results, should be done against the `app` abstraction directly. It's okay if this leads to redundant tests (see for example `src/channel/routes/test/on_send.rs` and `src/events/routes/test.rs`, which overlap heavily). + +Panicking in tests is fine. Panic messages should describe why the preconditions were expected, and can be terse. |
