round-trip-testing
round-trip-testing
Verifies processing, migration, and conversion through realistic end-to-end round-trip cases—fixture input, run pipeline, compare to explicit expected output, iterate until stable. Use when validating transforms preserve meaning/structure, when adding migration or format conversion confidence, or when the user mentions round-trip tests, golden files, E2E data processing, or compatibility regressions.
When to apply
Use when behavior spans input → transform → output (or A → B → A) and correctness depends on semantic and structural fidelity, not only unit-level pieces. Typical contexts: format conversion, serializers, migrations, codegen, import/export, and lossy-or-delicate pipelines.
Workflow
-
Define the round-trip
State the forward path, optional inverse path, and what "same meaning / same structure" means for this task (fields preserved, ordering, types, whitespace rules, unknown fields, etc.). -
Create representative fixtures
- Happy paths: realistic production-like samples (size, shape, and content diversity).
- Edge cases: empty/minimal, very large, boundary values, unusual but valid combinations.
- Malformed / invalid (when in scope): document whether the pipeline should reject, repair, or degrade gracefully—assert that behavior explicitly.
- Compatibility-sensitive: version skew, optional features, legacy vs new formats, encoding and locale quirks.
-
Make expected outputs explicit and reviewable
Prefer committed golden files or structured expectations (snapshots only if the project already uses them and churn is acceptable). Expected artifacts should be human-diffable where practical (formatted JSON/YAML/XML/text, stable sorting). Record any intentional normalization (timestamps, IDs) in the test or a short comment beside the fixture. -
Run the program on fixtures
Use the project's normal CLI, scripts, or test harness. Keep commands reproducible (documented in the test or README if non-obvious). -
Compare and iterate
- Diff actual vs expected; classify mismatches as bugs, spec drift, or fixture wrong.
- Fix code or expectations; re-run the full round-trip scope after each change until results are correct and stable (no flaky ordering, timestamps, or env dependence unless explicitly controlled).
-
Assert invariants, not only byte equality
When byte-for-byte round-trip is impossible, assert invariants: canonical form, checksum of normalized content, schema validation, semantic equivalence (e.g. parse both sides and compare AST/object model).
Checklist
Round-trip progress:
- [ ] Fixtures cover happy, edge, compatibility, and (if needed) malformed cases
- [ ] Expected outputs are explicit (golden files or clear assertions)
- [ ] Meaning/structure preservation criteria are stated
- [ ] Commands are reproducible
- [ ] Loop closed: failures fixed or expectations updated with rationale
- [ ] No hidden nondeterminism (time, random IDs, unstable sort) unless pinned
Expected outcomes
- Conversion and processing workflows are verified end to end.
- Transform regressions surface as clear fixture diffs.
- Migrations and data-processing changes ship with higher confidence.
Project specifics
Discover how the repo runs the pipeline (package scripts, cargo test, pytest, CLI binaries). Prefer automated tests that load fixtures from a dedicated directory (e.g. tests/fixtures/, testdata/). If no harness exists, still produce fixtures and a repeatable command sequence the user can turn into tests next.
Related skills
- test-to-completion — Ensure round-trip tests are part of the broader test suite and run before completion.