pdac-knowledge-agent-dev / tests /test_identifiers.py
avoigt1121
Claude Opus 5.5
feat: governed ToolUniverse core for the knowledge specialist (s1)
377417d
Raw History Blame Contribute Delete
3.26 kB
"""What may leave the Space: identifiers only (ADR-0001 §6). Refusals are data."""
from __future__ import annotations
import pytest
from src.identifiers import MAX_IDENTIFIERS, parse_disease, parse_gene_list, parse_nct
# Real HGNC symbols chosen to exercise the edges of the pattern and of the sample-id prefixes.
VALID_SYMBOLS = [
"KRAS",
"TP53",
"ELAVL1",
"C1orf112",
"HLA-DRB1",
"NKX2-1",
"IGHV1-69-2",
"CPT1A",
"ERRFI1",
"DOK1",
"SAA1",
"SORD2P",
]
@pytest.mark.parametrize("symbol", VALID_SYMBOLS)
def test_real_symbols_pass(symbol):
parsed = parse_gene_list(symbol)
assert parsed.ok, parsed.message
assert parsed.identifiers[0].kind == "symbol"
def test_a_list_splits_on_commas_spaces_and_semicolons_and_keeps_order():
parsed = parse_gene_list("JAK1, JAK2;STAT1 jak1")
assert parsed.ok
assert [i.value for i in parsed.identifiers] == ["JAK1", "JAK2", "STAT1"]
assert parsed.duplicates_dropped == 1
def test_ensembl_ids_are_genes_and_uniprot_only_when_allowed():
assert parse_gene_list("ENSG00000133703").identifiers[0].kind == "ensembl"
assert parse_gene_list("P05161", allow_uniprot=True).identifiers[0].kind == "uniprot"
assert parse_gene_list("P05161").identifiers[0].kind == "symbol"
@pytest.mark.parametrize(
"raw",
[
"what drugs target KRAS?",
"TCGA-2J-AAB1-01A",
"GSM1234567",
"C3L-00017",
"12.5",
"KRAS 3.2 1.1",
"<script>",
"SELECT * FROM genes",
],
)
def test_free_text_sample_ids_and_numbers_are_refused(raw):
parsed = parse_gene_list(raw)
assert not parsed.ok
assert parsed.reason == "invalid_identifier"
assert "free text, sample ids and numbers are not" in parsed.message
def test_an_empty_list_is_refused():
assert parse_gene_list(" ").reason == "invalid_identifier"
assert parse_gene_list([]).reason == "invalid_identifier"
def test_more_than_the_cap_is_refused_with_the_cap():
raw = ",".join(f"GENE{i}" for i in range(MAX_IDENTIFIERS + 1))
parsed = parse_gene_list(raw)
assert parsed.reason == "too_many_identifiers"
assert str(MAX_IDENTIFIERS) in parsed.message
assert parse_gene_list(",".join(f"GENE{i}" for i in range(MAX_IDENTIFIERS))).ok
def test_a_refusal_never_echoes_a_long_token():
parsed = parse_gene_list("x" * 200 + "!")
assert len(parsed.message) < 250
assert "x" * 30 not in parsed.message
@pytest.mark.parametrize(
"raw,kind",
[
("EFO_0002618", "disease_id"),
("MONDO_0005192", "disease_id"),
("pancreatic ductal adenocarcinoma", "disease_name"),
("Crohn's disease", "disease_name"),
("type 2 diabetes mellitus", "disease_name"),
],
)
def test_diseases(raw, kind):
parsed = parse_disease(raw)
assert parsed.ok and parsed.identifiers[0].kind == kind
@pytest.mark.parametrize(
"raw", ["", "a" * 81, "patient 12; DOB 1950-01-01?", "1234", "TCGA-2J-AAB1"]
)
def test_bad_diseases_are_refused(raw):
assert parse_disease(raw).reason == "invalid_identifier"
def test_nct_ids():
assert parse_nct("nct04635059").identifiers[0].value == "NCT04635059"
assert parse_nct("NCT123").reason == "invalid_identifier"