Files
graphify/tests/test_incremental.py
T
Safi cb5e701c67 make incremental extract tests deterministic under a real LLM env key
test_manifest_written_after_extract assumes a docs corpus fails with no LLM
backend, but _run inherited the developer's environment. With a real
ANTHROPIC_API_KEY exported and the anthropic package present (now pulled by
[all]), the claude backend was detected and the extract succeeded, breaking the
'no backend' assertion. Strip the backend-selecting env vars in _run so the
tests hold regardless of the developer's shell. CI has no keys set, so it was
green there already.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 00:20:39 +01:00

75 lines
2.9 KiB
Python

"""Integration tests for incremental graphify extract behavior."""
from __future__ import annotations
import json
import os
import subprocess
import sys
from pathlib import Path
import pytest
PYTHON = sys.executable
# Backend-selecting env vars. These tests assume no working LLM backend (a docs
# corpus should fail without one); strip them so a developer who has a real
# ANTHROPIC_API_KEY / OPENAI_API_KEY / etc. exported does not make a docs extract
# succeed and break the "no backend" path. CI has none of these set anyway.
_LLM_ENV_KEYS = (
"ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GEMINI_API_KEY", "GOOGLE_API_KEY",
"MOONSHOT_API_KEY", "DEEPSEEK_API_KEY", "OLLAMA_BASE_URL",
"AWS_PROFILE", "AWS_REGION", "AWS_DEFAULT_REGION", "AWS_ACCESS_KEY_ID",
)
def _run(args: list[str], cwd: Path) -> subprocess.CompletedProcess:
env = {k: v for k, v in os.environ.items() if k not in _LLM_ENV_KEYS}
return subprocess.run(
[PYTHON, "-m", "graphify"] + args,
cwd=cwd,
capture_output=True,
text=True,
env=env,
)
def _make_docs_corpus(tmp_path: Path) -> Path:
docs = tmp_path / "docs"
docs.mkdir()
(docs / "intro.md").write_text("# Introduction\nThis doc introduces the system.")
(docs / "api.md").write_text("# API Reference\nThe API has endpoints.")
return docs
def test_manifest_written_after_extract(tmp_path):
"""After a full extract run, manifest.json must exist (or run fails before writing it)."""
docs = _make_docs_corpus(tmp_path)
r = _run(["extract", str(docs)], tmp_path)
# Should fail with no API key — but NOT with a path error
assert "no LLM API key" in r.stderr or r.returncode != 0
# manifest should NOT exist (run failed before writing)
manifest = docs / "graphify-out" / "manifest.json"
assert not manifest.exists()
def test_incremental_mode_detected_via_manifest(tmp_path):
"""If manifest.json + graph.json exist, incremental mode message is shown."""
docs = _make_docs_corpus(tmp_path)
out = docs / "graphify-out"
out.mkdir()
(out / "graph.json").write_text(json.dumps({"nodes": [], "links": []}))
(out / "manifest.json").write_text(json.dumps({"document": [str(docs / "intro.md")]}))
r = _run(["extract", str(docs)], tmp_path)
combined = r.stdout + r.stderr
assert "incremental" in combined.lower() or r.returncode != 0
def test_no_incremental_without_manifest(tmp_path):
"""Without manifest.json, full scan message is shown (not incremental)."""
docs = _make_docs_corpus(tmp_path)
r = _run(["extract", str(docs)], tmp_path)
# Check combined output doesn't contain incremental-mode phrasing.
# Use a phrase rather than a bare word to avoid matching the tmp_path,
# which pytest derives from the test name and contains "incremental".
assert "incremental update" not in r.stdout.lower()
assert "incremental scan" not in r.stdout.lower()