aps-agent/tests/workbook_acceptance.py

48 lines
2.0 KiB
Python

"""Portable source selection and independently maintained workbook expectations.
Ordinary tests may omit external input. Setting ROUND87_REQUIRED=1 makes input
mandatory; a configured but missing/changed file always fails. CLI tools pass
required=True and never fall back to another workbook.
"""
from __future__ import annotations
import hashlib
import json
import os
from pathlib import Path
DEFAULT_EXPECTATIONS = Path(__file__).resolve().parent / "fixtures" / "planning-workbook-acceptance.json"
def load_expectations(path: str | Path | None = None) -> dict:
selected = Path(path or os.environ.get("ROUND87_EXPECTATIONS") or DEFAULT_EXPECTATIONS)
data = json.loads(selected.read_text(encoding="utf-8"))
if data.get("schemaVersion") != 1 or not isinstance(data.get("sourceSha256"), str):
raise ValueError("Invalid workbook acceptance manifest")
return data
def resolve_source(source: str | Path | None = None, *, required: bool | None = None,
expectations: dict | None = None) -> Path | None:
selected = source or os.environ.get("ROUND87_SOURCE")
required = required if required is not None else os.environ.get("ROUND87_REQUIRED") == "1"
if not selected:
if required:
raise ValueError("Set ROUND87_SOURCE or pass --source for the designated workbook")
return None
path = Path(selected).expanduser().resolve(strict=True)
if not path.is_file():
raise ValueError("Workbook source must be a file")
expected = expectations if expectations is not None else load_expectations()
if hashlib.sha256(path.read_bytes()).hexdigest() != expected["sourceSha256"]:
raise ValueError("The designated workbook does not match the independently reviewed SHA-256")
return path
def source_for_test() -> Path:
source = resolve_source()
if source is None:
import pytest
pytest.skip("External workbook not configured; set ROUND87_SOURCE (ROUND87_REQUIRED=1 for acceptance)")
return source