|
| 1 | +# SQL to SQLx Test Migration Guide |
| 2 | + |
| 3 | +This guide explains how to port SQL tests to Rust/SQLx while ensuring complete coverage. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +We have three tools to track coverage during migration: |
| 8 | + |
| 9 | +1. **Test Inventory** - Which tests have been ported |
| 10 | +2. **Assertion Counts** - How many test assertions ported |
| 11 | +3. **Function Call Tracking** - Which SQL functions are tested |
| 12 | + |
| 13 | +## Workflow |
| 14 | + |
| 15 | +### Before Starting Migration |
| 16 | + |
| 17 | +1. **Generate baseline coverage:** |
| 18 | + |
| 19 | + ```bash |
| 20 | + # Enable function tracking |
| 21 | + psql postgres://cipherstash:password@localhost:7432/postgres -c "ALTER SYSTEM SET track_functions = 'all';" |
| 22 | + psql postgres://cipherstash:password@localhost:7432/postgres -c "SELECT pg_reload_conf();" |
| 23 | + |
| 24 | + # Reset stats and run SQL tests |
| 25 | + psql postgres://cipherstash:password@localhost:7432/postgres -c "SELECT pg_stat_reset();" |
| 26 | + mise run test |
| 27 | + |
| 28 | + # Capture baseline |
| 29 | + TEST_TYPE=sql ./tools/track-function-calls.sh sql-function-calls.json |
| 30 | + ./tools/count-assertions.sh |
| 31 | + ./tools/generate-test-inventory.sh |
| 32 | + ``` |
| 33 | + |
| 34 | +2. **Review baseline metrics:** |
| 35 | + - 38 SQL test files |
| 36 | + - ~3,917 lines of tests |
| 37 | + - ~513 assertions |
| 38 | + - Function call coverage saved in `sql-function-calls.json` |
| 39 | + |
| 40 | +### During Migration |
| 41 | + |
| 42 | +For each SQL test file you port: |
| 43 | + |
| 44 | +1. **Pick a test from inventory** (`docs/test-inventory.md`) |
| 45 | + |
| 46 | +2. **Read the SQL test**, understand what it tests |
| 47 | + |
| 48 | +3. **Write equivalent Rust test** in `rust-tests/tests/` |
| 49 | + |
| 50 | +4. **Run the Rust test:** |
| 51 | + ```bash |
| 52 | + cd rust-tests |
| 53 | + cargo test <test_name> -- --nocapture |
| 54 | + ``` |
| 55 | + |
| 56 | +5. **Verify function coverage:** |
| 57 | + ```bash |
| 58 | + psql postgres://cipherstash:password@localhost:7432/postgres -c "SELECT pg_stat_reset();" |
| 59 | + cd rust-tests && cargo test |
| 60 | + TEST_TYPE=rust ./tools/track-function-calls.sh rust-function-calls.json |
| 61 | + ./tools/compare-function-calls.sh sql-function-calls.json rust-function-calls.json |
| 62 | + ``` |
| 63 | + |
| 64 | +6. **Update test inventory:** |
| 65 | + ```bash |
| 66 | + ./tools/generate-test-inventory.sh |
| 67 | + ``` |
| 68 | + |
| 69 | + Manually edit `docs/test-inventory.md` to mark test as ✅ Ported. |
| 70 | + |
| 71 | +7. **Check assertion coverage:** |
| 72 | + ```bash |
| 73 | + ./tools/compare-assertions.sh |
| 74 | + ``` |
| 75 | + |
| 76 | +8. **Commit** when test passes and coverage verified: |
| 77 | + ```bash |
| 78 | + git add rust-tests/tests/<test_file>.rs docs/test-inventory.md |
| 79 | + git commit -m "test: port <feature> tests from SQL to SQLx" |
| 80 | + ``` |
| 81 | + |
| 82 | +### After Migration Complete |
| 83 | + |
| 84 | +1. **Verify 100% coverage:** |
| 85 | + ```bash |
| 86 | + ./tools/check-test-coverage.sh |
| 87 | + ``` |
| 88 | + |
| 89 | +2. **Ensure all checks pass:** |
| 90 | + - ✅ All 38 tests marked as ported |
| 91 | + - ✅ Rust assertion count ≥ SQL assertion count |
| 92 | + - ✅ Rust function calls cover same functions as SQL |
| 93 | + |
| 94 | +3. **Delete SQL tests** (only after verification): |
| 95 | + ```bash |
| 96 | + # DO NOT DO THIS UNTIL MIGRATION COMPLETE |
| 97 | + git rm src/**/*_test.sql |
| 98 | + ``` |
| 99 | + |
| 100 | +## Coverage Metrics Explained |
| 101 | + |
| 102 | +### Test Inventory |
| 103 | + |
| 104 | +Shows 1:1 mapping of SQL test files to Rust test files: |
| 105 | + |
| 106 | +- **Status ❌ TODO** - Not yet ported |
| 107 | +- **Status ✅ Ported** - Rust equivalent exists and passes |
| 108 | + |
| 109 | +### Assertion Counts |
| 110 | + |
| 111 | +Tracks test thoroughness: |
| 112 | + |
| 113 | +- **SQL:** ASSERT statements, PERFORM assert_*, SELECT checks |
| 114 | +- **Rust:** assert!(), assert_eq!(), .expect() |
| 115 | + |
| 116 | +Goal: Rust count ≥ SQL count |
| 117 | + |
| 118 | +### Function Call Tracking |
| 119 | + |
| 120 | +Ensures same code paths exercised: |
| 121 | + |
| 122 | +- Uses PostgreSQL `pg_stat_user_functions` |
| 123 | +- Compares which `eql_v2.*` functions called in SQL vs Rust tests |
| 124 | +- Identifies gaps: functions only in SQL tests = missing coverage |
| 125 | + |
| 126 | +## Troubleshooting |
| 127 | + |
| 128 | +**Q: Rust test passes but function coverage shows missing functions?** |
| 129 | + |
| 130 | +A: Your test might not be exercising the same code paths. Review the SQL test to see which functions it calls. |
| 131 | + |
| 132 | +**Q: Assertion count much lower in Rust?** |
| 133 | + |
| 134 | +A: You may be using fewer, but more comprehensive assertions. That's OK if function coverage matches. Document in test inventory notes. |
| 135 | + |
| 136 | +**Q: pg_stat_user_functions not tracking?** |
| 137 | + |
| 138 | +A: Verify `track_functions = 'all'` in postgresql.conf and PostgreSQL reloaded. |
| 139 | + |
| 140 | +## Tips |
| 141 | + |
| 142 | +- **Port tests in related groups** (e.g., all operator tests together) |
| 143 | +- **Keep both test suites running** until migration complete |
| 144 | +- **Update inventory frequently** to track progress |
| 145 | +- **Compare function coverage often** to catch gaps early |
| 146 | + |
| 147 | +## See Also |
| 148 | + |
| 149 | +- `tools/check-test-coverage.sh` - Run all coverage checks |
| 150 | +- `docs/test-inventory.md` - Current migration status |
| 151 | +- `docs/assertion-counts.md` - Detailed assertion breakdown |
0 commit comments