Files
temp/features/steps/uko_l2_coverage_ttl_steps.py

149 lines
4.9 KiB
Python

"""Behave steps for UKO Layer 2 TTL validation and additional coverage.
Covers Turtle file loading, ParadigmVocabulary frozen-model checks,
and miscellaneous validation edge-cases.
All step definitions use the ``for uko_l2`` suffix to avoid
AmbiguousStep collisions with other feature files.
"""
from __future__ import annotations
from pathlib import Path
from _uko_l2_test_helpers import capture_error
from behave import then, when
from behave.runner import Context
from pydantic import ValidationError
from cleveragents.acms.uko.vocabularies import (
ParadigmVocabulary,
VocabularyProperty,
get_oo_vocabulary,
)
from cleveragents.application.services.uko_loader import UKOLoader
_TTL_PATH = Path(__file__).resolve().parents[2] / "docs" / "ontology" / "uko.ttl"
# ---------------------------------------------------------------------------
# Turtle validation
# ---------------------------------------------------------------------------
@when("I load the UKO TTL file for uko_l2")
def step_load_ttl(ctx: Context) -> None:
loader = UKOLoader()
ctx.ontology = loader.load(_TTL_PATH)
@then("the ontology should load without errors for uko_l2")
def step_check_ontology_loaded(ctx: Context) -> None:
assert ctx.ontology is not None
assert len(ctx.ontology.nodes) > 0
@then("the ontology should contain uko-func prefix for uko_l2")
def step_check_func_prefix(ctx: Context) -> None:
prefixes = {p.prefix for p in ctx.ontology.prefixes}
assert "uko-func" in prefixes, f"uko-func not in {prefixes}"
@then("the ontology should contain uko-proc prefix for uko_l2")
def step_check_proc_prefix(ctx: Context) -> None:
prefixes = {p.prefix for p in ctx.ontology.prefixes}
assert "uko-proc" in prefixes, f"uko-proc not in {prefixes}"
@then('the ontology should contain node "{label}" for uko_l2')
def step_check_node_exists(ctx: Context, label: str) -> None:
labels = {n.label for n in ctx.ontology.nodes}
assert label in labels, f"Node '{label}' not in {labels}"
@then("the ontology should have at least {count:d} layer 2 nodes for uko_l2")
def step_check_layer2_count(ctx: Context, count: int) -> None:
layer2 = [n for n in ctx.ontology.nodes if n.layer == 2]
assert len(layer2) >= count, f"Expected >= {count} layer 2 nodes, got {len(layer2)}"
# ---------------------------------------------------------------------------
# ParadigmVocabulary frozen
# ---------------------------------------------------------------------------
@when("I try to mutate the vocabulary prefix for uko_l2")
def step_mutate_vocab_prefix(ctx: Context) -> None:
with capture_error(ctx, ValidationError):
ctx.vocabulary.prefix = "changed:" # type: ignore[misc] # deliberate mutation to test frozen model
# ---------------------------------------------------------------------------
# Additional coverage steps
# ---------------------------------------------------------------------------
@when("I create a paradigm vocabulary with empty prefix for uko_l2")
def step_create_vocab_empty_prefix(ctx: Context) -> None:
with capture_error(ctx, ValidationError):
ParadigmVocabulary(
prefix="",
iri="http://test",
layer=2,
parent_domain="uko-code:",
max_depth=0,
)
@when("I create a paradigm vocabulary with whitespace prefix for uko_l2")
def step_create_vocab_whitespace_prefix(ctx: Context) -> None:
with capture_error(ctx, ValidationError):
ParadigmVocabulary(
prefix=" ",
iri="http://test",
layer=2,
parent_domain="uko-code:",
max_depth=0,
)
@when("I create a vocabulary property with whitespace uri for uko_l2")
def step_create_vocab_prop_whitespace_uri(ctx: Context) -> None:
with capture_error(ctx, ValidationError):
VocabularyProperty(
uri=" ",
label="test",
domain_uri="https://example.com/d",
range_uri="https://example.com/r",
)
@then("the registry should return False for non-string contains for uko_l2")
def step_check_non_string_contains(ctx: Context) -> None:
assert 42 not in ctx.registry
assert None not in ctx.registry
@when("I try to register a vocabulary with duplicate IRI for uko_l2")
def step_register_duplicate_iri(ctx: Context) -> None:
oo = get_oo_vocabulary()
dup = ParadigmVocabulary(
prefix="uko-dup:",
iri=oo.iri,
layer=2,
parent_domain="uko-code:",
)
with capture_error(ctx, ValueError):
ctx.registry.register(dup)
@when("I create a paradigm vocabulary with prefix missing colon for uko_l2")
def step_create_paradigm_vocab_no_colon(ctx: Context) -> None:
with capture_error(ctx, ValidationError):
ParadigmVocabulary(
prefix="uko-test",
iri="https://example.org/test#",
layer=2,
parent_domain="uko-code:",
)