From 8d1bff252183ac8ff0839ed428a1c37e73e0c8d0 Mon Sep 17 00:00:00 2001 From: edithatogo <15080672+edithatogo@users.noreply.github.com> Date: Fri, 31 Jul 2026 04:03:06 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=AA=20[Testing=20Improvement]=20Add=20?= =?UTF-8?q?comprehensive=20tests=20for=20trace=5Fequivalence?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🎯 What: Extracted the existing test for trace_equivalence from test_pic_traces_schema.py into its own dedicated file test_traces.py and expanded it. 📊 Coverage: The new tests now completely check the returned dictionaries, particularly verifying that the diffs array correctly contains the right levels and messages when output, path, or semantic diffs occur. It also covers empty trace cases and missing keys. ✨ Result: Enhanced test coverage that explicitly checks error messages and edge cases, solidifying confidence in the trace equivalence logic without changing functionality. --- .../tools/tests/test_pic_traces_schema.py | 30 ------ contracts/tools/tests/test_traces.py | 98 +++++++++++++++++++ 2 files changed, 98 insertions(+), 30 deletions(-) create mode 100644 contracts/tools/tests/test_traces.py diff --git a/contracts/tools/tests/test_pic_traces_schema.py b/contracts/tools/tests/test_pic_traces_schema.py index 8c72b60c..ad087e39 100644 --- a/contracts/tools/tests/test_pic_traces_schema.py +++ b/contracts/tools/tests/test_pic_traces_schema.py @@ -1,8 +1,6 @@ -from copy import deepcopy from pathlib import Path from pic_contracts.schema_utils import CONTRACTS_ROOT, load_json, validator_for -from pic_contracts.traces import trace_equivalence BASE = CONTRACTS_ROOT / "pic-traces" / "0.1.0" / "examples" @@ -30,31 +28,3 @@ def test_invalid_traces_fail_for_intended_reason() -> None: assert any(message in error.message for error in errors) -def test_trace_equivalence_levels() -> None: - trace = load_json(BASE / "valid" / "oia-response-deadline.json") - equal = deepcopy(trace) - assert trace_equivalence(trace, equal) == { - "output": True, - "path": True, - "semantic": True, - "diffs": [], - } - - output_only = deepcopy(trace) - output_only["steps"][0]["stepId"] = "alternate_path" - assert trace_equivalence(trace, output_only)["output"] is True - assert trace_equivalence(trace, output_only)["path"] is False - - path_different = deepcopy(trace) - path_different["outputs"]["nz-oia/decision.response_deadline"]["value"] = "2026-02-11" - result = trace_equivalence(trace, path_different) - assert result["output"] is False - assert result["path"] is False - assert result["semantic"] is False - - semantic_different = deepcopy(trace) - semantic_different["steps"][0]["sourceRefs"] = ["different source"] - result = trace_equivalence(trace, semantic_different) - assert result["output"] is True - assert result["path"] is True - assert result["semantic"] is False diff --git a/contracts/tools/tests/test_traces.py b/contracts/tools/tests/test_traces.py new file mode 100644 index 00000000..9e2cd9d3 --- /dev/null +++ b/contracts/tools/tests/test_traces.py @@ -0,0 +1,98 @@ +from copy import deepcopy + +from pic_contracts.schema_utils import CONTRACTS_ROOT, load_json +from pic_contracts.traces import trace_equivalence + +BASE = CONTRACTS_ROOT / "pic-traces" / "0.1.0" / "examples" + + +def test_trace_equivalence_levels() -> None: + trace = load_json(BASE / "valid" / "oia-response-deadline.json") + equal = deepcopy(trace) + result = trace_equivalence(trace, equal) + assert result == { + "output": True, + "path": True, + "semantic": True, + "diffs": [], + } + + output_only = deepcopy(trace) + output_only["steps"][0]["stepId"] = "alternate_path" + result = trace_equivalence(trace, output_only) + assert result["output"] is True + assert result["path"] is False + assert result["semantic"] is False + assert result["diffs"] == [ + {"level": "path", "message": "step IDs or parameter versions differ"} + ] + + path_different = deepcopy(trace) + path_different["outputs"]["nz-oia/decision.response_deadline"]["value"] = "2026-02-11" + result = trace_equivalence(trace, path_different) + assert result["output"] is False + assert result["path"] is False + assert result["semantic"] is False + assert result["diffs"] == [ + {"level": "output", "message": "outputs differ"} + ] + + semantic_different = deepcopy(trace) + semantic_different["steps"][0]["sourceRefs"] = ["different source"] + result = trace_equivalence(trace, semantic_different) + assert result["output"] is True + assert result["path"] is True + assert result["semantic"] is False + assert result["diffs"] == [ + {"level": "semantic", "message": "step source references differ"} + ] + +def test_trace_equivalence_empty() -> None: + # Test completely empty dictionaries + result = trace_equivalence({}, {}) + assert result == { + "output": True, + "path": True, + "semantic": True, + "diffs": [], + } + + # Test one empty dictionary + trace = load_json(BASE / "valid" / "oia-response-deadline.json") + result = trace_equivalence(trace, {}) + assert result["output"] is False + assert result["path"] is False + assert result["semantic"] is False + assert result["diffs"] == [ + {"level": "output", "message": "outputs differ"} + ] + +def test_trace_equivalence_missing_keys() -> None: + # Test traces missing 'outputs' or 'steps' but otherwise populated + trace1 = {"some_other_key": "value"} + trace2 = {"some_other_key": "value2"} + + result = trace_equivalence(trace1, trace2) + assert result == { + "output": True, + "path": True, + "semantic": True, + "diffs": [], + } + + trace_with_steps = { + "steps": [ + { + "stepId": "s1", + "parameterVersions": [{"id": "p1", "effectiveFrom": "d1"}], + } + ] + } + trace_without_steps = {} + result = trace_equivalence(trace_with_steps, trace_without_steps) + assert result["output"] is True + assert result["path"] is False + assert result["semantic"] is False + assert result["diffs"] == [ + {"level": "path", "message": "step IDs or parameter versions differ"} + ]