68 lines
2.5 KiB
Markdown
68 lines
2.5 KiB
Markdown
# mysql_testing
|
|
|
|
Test-only MySQL harness: guarded connections to a **test** database, schema
|
|
setup from the checked-in migrations, and shared fixtures (accounts,
|
|
sessions, wallets, media files). Use it as a `dev-dependency` only.
|
|
|
|
## Safety model
|
|
|
|
Every connection goes through `guard::guard_test_database_url`, which PANICS
|
|
unless:
|
|
|
|
- the database name contains `"test"`,
|
|
- the database name is not `storyteller` or `artcraft` (the real databases),
|
|
- the host does not look like a managed/cloud database (`digitalocean`,
|
|
`aws`, `amazonaws`, `rds`, `gcp`, `googleapis`, `cloudsql`, `azure`, ...).
|
|
|
|
Test code reads its URL from exactly one env var —
|
|
`ARTCRAFT_TEST_DATABASE_URL` — never `MYSQL_URL` or `DATABASE_URL`, so test
|
|
runs can't inherit a real database by accident. The default is
|
|
`mysql://root:@localhost:3306/artcraft_test`.
|
|
|
|
## One-time local setup
|
|
|
|
```bash
|
|
mysql -u root -e "CREATE DATABASE IF NOT EXISTS artcraft_test;"
|
|
```
|
|
|
|
The harness creates the database itself when the connecting user has the
|
|
privilege, applies all `_database/sql/migrations/*/up.sql` in order (tracked
|
|
in `mysql_testing_applied_migrations`, so repeat runs are fast), and seeds
|
|
`user_roles`. If the schema ever wedges: `DROP DATABASE artcraft_test;` and
|
|
rerun.
|
|
|
|
## Writing a database test
|
|
|
|
Database tests run by default; mark them with the `skip_database_tests`
|
|
off switch so database-less machines/CI can exclude them. Tests run in
|
|
PARALLEL — create your own users/wallets/rows and never touch another
|
|
test's data (schema setup single-flights via a MySQL named lock). Only a
|
|
test that must mutate shared/global state takes
|
|
`mysql_testing::serial::acquire_serial_test_lock()`.
|
|
|
|
```rust
|
|
#[tokio::test]
|
|
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
|
async fn my_database_test() {
|
|
let pool = mysql_testing::pool::create_test_pool().await;
|
|
|
|
let user = mysql_testing::fixtures::users::create_test_user(&pool).await.unwrap();
|
|
mysql_testing::fixtures::wallets::fund_wallet_banked(&pool, &user.user_token, 10_000)
|
|
.await
|
|
.unwrap();
|
|
// ...
|
|
}
|
|
```
|
|
|
|
Skip them (machines/CI without MySQL) with:
|
|
|
|
```bash
|
|
SQLX_OFFLINE=true cargo test -p storyteller-web --features skip_database_tests
|
|
```
|
|
|
|
The first end-to-end consumers are the omni_gen video pricing tests in
|
|
`crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/tests/`,
|
|
which drive the real generate handler with dummy Actix requests, stub the
|
|
provider with an in-process HTTP server, and assert the exact credits
|
|
debited from the wallet.
|