Files
jaypy/tests/jaydiff/test_real_data.py
T
2026-05-27 13:33:52 +02:00

94 lines
3.3 KiB
Python

"""
Round-trip tests for diff using real snapshot records from ./tests/data/.
For every pair of consecutive records (within a file and across adjacent files)
we verify:
merge_full(a, diff_full(a, b)) == b
We also verify that diffing identical records produces an empty diff, and that
applying an empty diff is a no-op.
"""
import json
import pathlib
import pytest
from jaydiff.diff import diff_full
from jaydiff.merge import merge_full
DATA_DIR = pathlib.Path(__file__).parent / "data"
def _load_all_records() -> list[dict]:
"""Return all records from all data files, sorted by timestamp."""
records: list[dict] = []
for path in sorted(DATA_DIR.glob("*.json")):
store = json.loads(path.read_text())
records.extend(store.get("records", []))
records.sort(key=lambda r: r.get("ts", ""))
return records
ALL_RECORDS = _load_all_records()
CONSECUTIVE_PAIRS = list(zip(ALL_RECORDS, ALL_RECORDS[1:]))
class TestRealDataRoundTrip:
"""Diff+merge of every consecutive snapshot pair must reconstruct the target."""
@pytest.mark.parametrize("pair_index", range(len(CONSECUTIVE_PAIRS)))
def test_consecutive_round_trip(self, pair_index: int) -> None:
a, b = CONSECUTIVE_PAIRS[pair_index]
diff = diff_full(a, b)
result = merge_full(a, diff)
assert result == b, (
f"Round-trip failed for pair #{pair_index} "
f"(ts: {a.get('ts')}{b.get('ts')})"
)
@pytest.mark.parametrize("pair_index", range(len(CONSECUTIVE_PAIRS)))
def test_diff_of_identical_is_empty(self, pair_index: int) -> None:
a, _ = CONSECUTIVE_PAIRS[pair_index]
assert diff_full(a, a) == {}
@pytest.mark.parametrize("pair_index", range(len(CONSECUTIVE_PAIRS)))
def test_empty_diff_is_noop(self, pair_index: int) -> None:
a, _ = CONSECUTIVE_PAIRS[pair_index]
assert merge_full(a, {}) == a
class TestRealDataProperties:
"""Structural invariants on the real snapshot data."""
def test_data_dir_has_files(self) -> None:
assert len(list(DATA_DIR.glob("*.json"))) > 0, "No JSON files in tests/data/"
def test_all_records_have_timestamp(self) -> None:
for rec in ALL_RECORDS:
assert "ts" in rec, f"Record missing 'ts': {list(rec.keys())}"
def test_records_are_sorted(self) -> None:
ts_list = [r["ts"] for r in ALL_RECORDS]
assert ts_list == sorted(ts_list), "Records are not in ascending timestamp order"
def test_total_record_count(self) -> None:
assert len(ALL_RECORDS) > 100, (
f"Expected >100 records across all files, got {len(ALL_RECORDS)}"
)
def test_diff_size_smaller_than_full_snapshot(self) -> None:
"""Diffs between similar consecutive records should usually be smaller."""
savings = 0
for a, b in CONSECUTIVE_PAIRS:
diff = diff_full(a, b)
if diff: # skip identical pairs
diff_len = len(json.dumps(diff))
full_len = len(json.dumps(b))
if diff_len < full_len:
savings += 1
ratio = savings / len(CONSECUTIVE_PAIRS) if CONSECUTIVE_PAIRS else 1.0
assert ratio > 0.5, (
f"Expected diffs to be smaller than full snapshots for >50% of pairs, "
f"got {ratio:.0%}"
)