Simon Clematide
feat: release v1.0.0 with restrained interface and versioning
1c44eff
Raw History Blame Contribute Delete
5.35 kB
"""Deterministic comparison and callback regressions; no remote parsing."""
import unittest
from unittest.mock import patch
import app
from core.conllu_utils import compare_trees
def token(form="word", token_id="1", upos="NOUN", head="0", relation="root"):
return f"{token_id}\t{form}\t_\t{upos}\t_\t_\t{head}\t{relation}\t_\t_\n"
class ComparisonTests(unittest.TestCase):
def compare(self, a, b):
return compare_trees(a, "A", b, "B")
def test_identical_and_annotation_differences(self):
a = token()
self.assertTrue(self.compare(a, a)["identical"])
for b, expected in ((token(upos="VERB"), "POS"),
(token(head="2", relation="obj"), "Syntax Arc"),
(token(upos="VERB", relation="obj"), "POS & Syntax")):
with self.subTest(expected=expected):
result = self.compare(a, b)
self.assertFalse(result["identical"])
self.assertEqual(result["diff_table"].iloc[0]["Difference"], expected)
def test_missing_data_never_establishes_identity(self):
for a, b in ((token(), ""), ("", token()), ("", ""), (token(), "# comment\n")):
with self.subTest(a=a, b=b):
self.assertFalse(self.compare(a, b)["identical"])
def test_tokenization_mismatch_prevents_arc_comparison(self):
for b, expected in ((token("other", upos="VERB"), "Token Alignment Mismatch"),
(token(token_id="2"), "Token Alignment Mismatch"),
(token() + token("extra", "2"), "Token Count Mismatch")):
with self.subTest(expected=expected):
result = self.compare(token(), b)
self.assertFalse(result["identical"])
self.assertEqual(result["discrepancy_count"], 1)
self.assertEqual(result["diff_table"].iloc[0]["Difference"], expected)
self.assertIn("cannot be compared", result["diff_summary"])
def test_multiword_headers_and_empty_nodes_are_skipped(self):
extra = token("combined", "1-2") + token("empty", "1.1")
self.assertTrue(self.compare(token(), extra + token())["identical"])
class CallbackTests(unittest.TestCase):
def run_callback(self, responses):
with patch.object(app.client, "parse_sentence", side_effect=responses):
result = app.run_single_or_compare(
"English", "word", "UDPipe · english-ewt-ud-2.17-251125", True, "UDPipe · english-gum-ud-2.17-251125"
)
self.assertEqual(len(result), 6)
return result
def test_result_freshness_tracks_every_parser_input(self):
check = next(block.fn for block in app.demo.fns.values()
if block.fn and block.fn.__name__ == "check_result_freshness")
original = ("English", "word", "model-a", True, "model-b", False)
self.assertEqual(check(*original, original, "comparison summary"), "comparison summary")
for position, replacement in enumerate(("German", "new text", "other", False, "other", True)):
changed = list(original)
changed[position] = replacement
self.assertIn("Input changed", check(*changed, original, "comparison summary"))
def test_example_noop_keeps_fourteen_outputs(self):
callback = next(block.fn for block in app.demo.fns.values()
if block.fn and block.fn.__name__ == "on_example_input")
self.assertEqual(len(callback(None, "English", "a", "b", False, None)), 14)
def test_secondary_failure_preserves_primary_and_clears_differences(self):
for response in ({"conllu": "", "error": "Timeout <unsafe>"},
{"conllu": "", "error": None},
{"conllu": "# comment\n", "error": None}):
with self.subTest(response=response):
result = self.run_callback([{"conllu": token(), "error": None}, response])
self.assertIn("<iframe", result[0])
self.assertEqual(result[2], token())
self.assertIn("Comparison unavailable", result[3])
self.assertNotIn("Matching analyses", result[3])
self.assertNotIn("<unsafe>", result[3])
self.assertFalse(result[4]["visible"])
self.assertTrue(result[5].empty)
def test_primary_failure_clears_outputs(self):
for response in ({"conllu": "", "error": "Timeout <unsafe>"},
{"conllu": "", "error": None}):
result = self.run_callback([response])
self.assertIn("Error:", result[0])
self.assertNotIn("<unsafe>", result[0])
self.assertTrue(result[1].empty)
self.assertEqual(result[2:4], ("", ""))
self.assertFalse(result[4]["visible"])
self.assertTrue(result[5].empty)
def test_successful_comparison_status(self):
for b, identical in ((token(), True), (token("different"), False), (token(upos="VERB"), False)):
result = self.run_callback([{"conllu": token(), "error": None}, {"conllu": b, "error": None}])
self.assertEqual("Matching analyses" in result[3], identical)
self.assertEqual(result[4]["visible"], not identical)
if __name__ == "__main__":
unittest.main()