pino-source-code / tests /test_verifier_pipeline.py
Matthew Ford
Add Fraterworks ingestion and upload data split support
2671b56
Raw
History Blame Contribute Delete
3.91 kB
import pytest
from pino.verifier import FragrancePipelineVerifier
from pathlib import Path
import sys
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from scripts.ingest_fraterworks_free_formulas import extract_pdf_text, parse_formula_text
def test_classic_accord_evaporation():
# Test formula: 10% Limonene, 20% Linalool, 70% Ethanol base
formula = [
{"cas": "5989-27-5", "weight_fraction": 0.10}, # Limonene
{"cas": "78-70-6", "weight_fraction": 0.20}, # Linalool
{"cas": "64-17-5", "weight_fraction": 0.70} # Ethanol
]
verifier = FragrancePipelineVerifier()
trajectory = verifier.run_sim(formula, duration_seconds=3600)
assert "trajectory" in trajectory
assert len(trajectory["trajectory"]) > 0
# Ensure ethanol depletes significantly faster than linalool
assert trajectory["depletion_rates"]["64-17-5"] > trajectory["depletion_rates"]["78-70-6"]
def test_out_of_applicability_domain_graceful():
# Invalid CAS that PubChem and the registry cannot resolve.
formula = [
{"cas": "0000-00-0", "weight_fraction": 0.50},
{"cas": "64-17-5", "weight_fraction": 0.50},
]
verifier = FragrancePipelineVerifier()
result = verifier.run_sim(formula, duration_seconds=3600)
assert result["status"] == "rejected"
assert result["applicability_errors"]
def test_ifra_rejection():
# Cinnamaldehyde is restricted/prohibited in the embedded IFRA table.
formula = [
{"cas": "104-55-2", "weight_fraction": 0.10},
{"cas": "64-17-5", "weight_fraction": 0.90},
]
verifier = FragrancePipelineVerifier()
result = verifier.run_sim(formula, duration_seconds=3600)
assert result["status"] == "rejected"
assert result["ifra_report"]["passed"] is False
def test_five_component_accord_with_registry():
# Classic 5-component accord in ethanol base via the registry path.
formula = [
{"cas": "64-17-5", "weight_fraction": 0.70},
{"cas": "5989-27-5", "weight_fraction": 0.10},
{"cas": "78-70-6", "weight_fraction": 0.08},
{"cas": "24851-98-7", "weight_fraction": 0.06}, # Hedione via registry
{"cas": "1222-05-5", "weight_fraction": 0.04}, # Galaxolide
{"cas": "6790-58-5", "weight_fraction": 0.02}, # Ambroxan
]
verifier = FragrancePipelineVerifier()
result = verifier.run_sim(formula, duration_seconds=28800, interval_seconds=600)
assert result["status"] == "passed"
assert len(result["trajectory"]) == 49
# Ethanol depletes faster than musks
assert result["depletion_rates"]["64-17-5"] > result["depletion_rates"]["6790-58-5"]
def test_fraterworks_parser_skips_multipage_title_rows():
pdf = Path("data/fraterworks_free_pdfs/F_FABULOUS_242463.pdf")
if not pdf.exists():
pytest.skip("Fraterworks fixture PDF is not present")
parsed = parse_formula_text(extract_pdf_text(pdf))
assert parsed["name"] == "F* Fabulous"
assert parsed["formula_code"] == "242463"
assert parsed["declared_profile"] == "a leather fragrance"
assert parsed["declared_total_parts"] == 1000.0
assert not any(row["name"] == "F* FABULOUS" for row in parsed["raw_formula"])
assert max(row["parts"] for row in parsed["raw_formula"]) == 230.0
def test_fraterworks_parser_handles_title_after_total():
pdf = Path("data/fraterworks_free_pdfs/incense-rori.pdf")
if not pdf.exists():
pytest.skip("Fraterworks fixture PDF is not present")
parsed = parse_formula_text(extract_pdf_text(pdf))
assert parsed["name"] == "Incense Rori"
assert parsed["formula_code"] == "989045"
assert parsed["declared_profile"] == "an oriental woody attar"
assert parsed["declared_total_parts"] == 1000.0
assert parsed["raw_formula"][0]["name"] == "Helvetolide®"
assert not any(row["name"] == "INCENSE RORI" for row in parsed["raw_formula"])