test: lock training error contract inventory
This commit is contained in:
@@ -57,6 +57,20 @@ PUBLIC_PRIVACY_CONTRACT_TEST_SURFACES = (
|
||||
"route annotation lifecycle",
|
||||
)
|
||||
|
||||
PUBLIC_VALIDATION_ERROR_CONTRACT_TEST_SURFACES = (
|
||||
"invalid path identifiers",
|
||||
"invalid and blank limit query values",
|
||||
"malformed/non-object JSON bodies",
|
||||
"attempt request field validation",
|
||||
"annotation request field validation",
|
||||
"submit request field validation",
|
||||
"import request field validation",
|
||||
"not_found behavior",
|
||||
"internal_server_error masking",
|
||||
)
|
||||
|
||||
VALIDATION_ERROR_CONTRACT_TEST_FILE = ROOT / "tests" / "unit" / "test_training_api_error_contract_m9.py"
|
||||
|
||||
PUBLIC_PRIVACY_CONTRACT_TEST_INVENTORY = (
|
||||
{
|
||||
"surface": "service public export",
|
||||
@@ -114,6 +128,70 @@ PUBLIC_PRIVACY_CONTRACT_TEST_INVENTORY = (
|
||||
},
|
||||
)
|
||||
|
||||
PUBLIC_VALIDATION_ERROR_CONTRACT_TEST_INVENTORY = (
|
||||
{
|
||||
"surface": "invalid path identifiers",
|
||||
"file": VALIDATION_ERROR_CONTRACT_TEST_FILE,
|
||||
"class_name": "TrainingApiErrorContractM9Tests",
|
||||
"test_names": (
|
||||
"test_invalid_case_path_identifier_returns_public_400",
|
||||
"test_missing_and_invalid_annotation_fields_return_public_400",
|
||||
"test_invalid_submit_fields_return_public_400",
|
||||
),
|
||||
},
|
||||
{
|
||||
"surface": "invalid and blank limit query values",
|
||||
"file": VALIDATION_ERROR_CONTRACT_TEST_FILE,
|
||||
"class_name": "TrainingApiErrorContractM9Tests",
|
||||
"test_names": (
|
||||
"test_invalid_limits_are_rejected_before_training_handlers_run",
|
||||
"test_route_request_helper_rejects_blank_training_limits",
|
||||
),
|
||||
},
|
||||
{
|
||||
"surface": "malformed/non-object JSON bodies",
|
||||
"file": VALIDATION_ERROR_CONTRACT_TEST_FILE,
|
||||
"class_name": "TrainingApiErrorContractM9Tests",
|
||||
"test_names": ("test_malformed_or_non_object_bodies_return_public_400",),
|
||||
},
|
||||
{
|
||||
"surface": "attempt request field validation",
|
||||
"file": VALIDATION_ERROR_CONTRACT_TEST_FILE,
|
||||
"class_name": "TrainingApiErrorContractM9Tests",
|
||||
"test_names": ("test_missing_and_invalid_attempt_fields_return_public_400",),
|
||||
},
|
||||
{
|
||||
"surface": "annotation request field validation",
|
||||
"file": VALIDATION_ERROR_CONTRACT_TEST_FILE,
|
||||
"class_name": "TrainingApiErrorContractM9Tests",
|
||||
"test_names": ("test_missing_and_invalid_annotation_fields_return_public_400",),
|
||||
},
|
||||
{
|
||||
"surface": "submit request field validation",
|
||||
"file": VALIDATION_ERROR_CONTRACT_TEST_FILE,
|
||||
"class_name": "TrainingApiErrorContractM9Tests",
|
||||
"test_names": ("test_invalid_submit_fields_return_public_400",),
|
||||
},
|
||||
{
|
||||
"surface": "import request field validation",
|
||||
"file": VALIDATION_ERROR_CONTRACT_TEST_FILE,
|
||||
"class_name": "TrainingApiErrorContractM9Tests",
|
||||
"test_names": ("test_missing_and_invalid_import_fields_return_public_400",),
|
||||
},
|
||||
{
|
||||
"surface": "not_found behavior",
|
||||
"file": VALIDATION_ERROR_CONTRACT_TEST_FILE,
|
||||
"class_name": "TrainingApiErrorContractM9Tests",
|
||||
"test_names": ("test_missing_case_returns_public_not_found",),
|
||||
},
|
||||
{
|
||||
"surface": "internal_server_error masking",
|
||||
"file": VALIDATION_ERROR_CONTRACT_TEST_FILE,
|
||||
"class_name": "TrainingApiErrorContractM9Tests",
|
||||
"test_names": ("test_handler_internal_error_does_not_echo_raw_detail",),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class _TrainingRouteProbe:
|
||||
def __init__(self) -> None:
|
||||
@@ -583,6 +661,31 @@ class TrainingPublicApiContractM8Tests(unittest.TestCase):
|
||||
seen_test_names.add(seen_key)
|
||||
self.assertIn(test_name, class_methods[class_name])
|
||||
|
||||
def test_public_validation_error_contract_inventory_names_exist_by_surface(self) -> None:
|
||||
surfaces = tuple(entry["surface"] for entry in PUBLIC_VALIDATION_ERROR_CONTRACT_TEST_INVENTORY)
|
||||
self.assertEqual(surfaces, PUBLIC_VALIDATION_ERROR_CONTRACT_TEST_SURFACES)
|
||||
|
||||
parsed_methods_by_path = {}
|
||||
seen_inventory_entries = set()
|
||||
for entry in PUBLIC_VALIDATION_ERROR_CONTRACT_TEST_INVENTORY:
|
||||
path = entry["file"]
|
||||
class_name = entry["class_name"]
|
||||
test_names = entry["test_names"]
|
||||
self.assertGreater(len(test_names), 0, entry["surface"])
|
||||
|
||||
if path not in parsed_methods_by_path:
|
||||
self.assertTrue(path.exists(), path)
|
||||
parsed_methods_by_path[path] = _test_methods_by_class(path)
|
||||
|
||||
class_methods = parsed_methods_by_path[path]
|
||||
self.assertIn(class_name, class_methods)
|
||||
for test_name in test_names:
|
||||
seen_key = (entry["surface"], path, class_name, test_name)
|
||||
with self.subTest(surface=entry["surface"], test_name=test_name):
|
||||
self.assertNotIn(seen_key, seen_inventory_entries)
|
||||
seen_inventory_entries.add(seen_key)
|
||||
self.assertIn(test_name, class_methods[class_name])
|
||||
|
||||
def test_documented_training_routes_resolve_to_expected_handlers(self) -> None:
|
||||
self.assertEqual(_documented_routes(), DOCUMENTED_TRAINING_ROUTES)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user