3.5 KiB
3.5 KiB
Testing
Database Fixture Tests
- Live in-crate (e.g.
storyteller-web's omni_gen video pricing tests) and use themysql_testingcrate (crates/schema/database/mysql_testing) for guarded pools, schema setup, and account/session/wallet fixtures - They RUN BY DEFAULT with
cargo test -p storyteller-weband from the IDE (requires a local MySQL with anartcraft_testdatabase). Machines/CI without MySQL skip them via the off switch:SQLX_OFFLINE=true cargo test -p storyteller-web --features skip_database_tests - They connect ONLY via
ARTCRAFT_TEST_DATABASE_URL(defaultmysql://root:@localhost:3306/artcraft_test); the guard panics on any database whose name lacks "test", onstoryteller/artcraft, and on cloud hosts — seemysql_testing/README.md - Database tests run in PARALLEL: each test creates its own users, wallets,
and rows; schema setup single-flights via a MySQL named lock. Only tests
mutating shared/global state take
mysql_testing::serial::acquire_serial_test_lock().await - External providers must never be called: the harness stubs Kinovi with an
in-process HTTP server via
KINOVI_CUSTOM_API_HOST/KINOVI_CUSTOM_CDN_HOST
Running Tests
- Most crates:
cargo test -p {crate_name} - Crates using SQLx offline mode:
SQLX_OFFLINE=true cargo test -p {crate_name} - The
storyteller-webandmysql_queriescrates requireSQLX_OFFLINE=truefor compilation - Use
cargo check -p {crate_name}for fast compilation checks without running tests
Test Patterns
- Tests live in
#[cfg(test)] mod tests { ... }at the bottom of each file - Group related tests into sub-modules by category (e.g.
mod pricing_tests,mod resolution_tests) - Only create a sub-module when it has 2+ tests — don't wrap a single test in its own module
- Keep nesting shallow:
mod tests { mod category { ... } }is fine; a third level is rarely needed - Shared helpers used by multiple sub-modules belong in the parent
mod tests, not duplicated in each sub-module - Enum tests should cover: serialization, deserialization,
to_str/from_strround-trip, variant count - Password/crypto tests: be mindful of computation cost, don't add too many bcrypt test cases
Test File Layout
Put test cases first, helpers last. Engineers should see the actual tests before scrolling to understand helper plumbing.
Within a mod tests { ... } block:
- Imports at the top
- Constants (test data IDs, URLs, etc.) — small context that tests reference
- Test functions (
#[test]/#[tokio::test]) grouped by category - Helper functions (builders, pipeline runners, etc.) at the very bottom
If tests are grouped into sub-modules, the same rule applies within each sub-module: constants first, then tests, then helpers at the end of that sub-module.
What to Test
- New error types and their mappings
- Enum variant serialization stability (these are stored in the database)
- Hash/deduplication functions with known inputs
- Edge cases in parsers (empty input, missing fields, malformed data)
Imports in Tests
- Import test fixtures and constants with
use, not inline fully-qualified paths. Writeuse test_data::web::image_urls::JUNO_AT_LAKE_IMAGE_URL;at the top, then referenceJUNO_AT_LAKE_IMAGE_URLin test bodies. - Same rule applies to enum variants used in match arms — import them, don't write
crate::some::deep::module::MyEnum::Variantinline.
What Not to Test
- Don't add integration tests that require a running database unless explicitly asked
- Don't add tests for simple struct construction or trivial getters