Skip to content

Commit 2dc5f7a

Browse files
committed
Add unit tests for compendium and research modules; remove deprecated test file
1 parent 0d0d180 commit 2dc5f7a

File tree

10 files changed

+487
-469
lines changed

10 files changed

+487
-469
lines changed

tests/compendium/__init__.py

Whitespace-only changes.
Lines changed: 12 additions & 227 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import json
1+
from __future__ import annotations
2+
23
import xml.etree.ElementTree as ET
34

45
from compendiumscribe.compendium import (
@@ -9,10 +10,6 @@
910
Section,
1011
etree_to_string,
1112
)
12-
from compendiumscribe.research import (
13-
ResearchConfig,
14-
build_compendium,
15-
)
1613

1714

1815
def test_compendium_to_xml_contains_expected_structure():
@@ -33,13 +30,12 @@ def test_compendium_to_xml_contains_expected_structure():
3330
Insight(
3431
title="Coherence is fragile",
3532
evidence=(
36-
"Most systems retain coherence "
37-
"for microseconds before error "
38-
"correction overwhelms throughput."
33+
"Most systems retain coherence for microseconds"
34+
" before error correction overwhelms throughput."
3935
),
4036
implications=(
41-
"Large-scale machines require aggressive "
42-
"error mitigation."
37+
"Large-scale machines require aggressive error"
38+
" mitigation."
4339
),
4440
citation_refs=["C1"],
4541
)
@@ -54,8 +50,8 @@ def test_compendium_to_xml_contains_expected_structure():
5450
publisher="ACM",
5551
published_at="2023-04-01",
5652
summary=(
57-
"Overview of leading quantum error correction "
58-
"strategies."
53+
"Overview of leading quantum error correction"
54+
" strategies."
5955
),
6056
)
6157
],
@@ -196,12 +192,11 @@ def test_compendium_from_payload_normalizes_fields():
196192
{
197193
"title": "Private investment surged",
198194
"evidence": (
199-
"Funding grew 45% year over year "
200-
"according to PitchBook."
195+
"Funding grew 45% year over year according to"
196+
" PitchBook."
201197
),
202198
"implications": (
203-
"Competition for talent is "
204-
"increasing."
199+
"Competition for talent is increasing."
205200
),
206201
"citations": ["C1"],
207202
}
@@ -215,10 +210,7 @@ def test_compendium_from_payload_normalizes_fields():
215210
"url": "https://example.com/pitchbook",
216211
"publisher": "PitchBook",
217212
"published_at": "2024-01-15",
218-
"summary": (
219-
"Investment trends across quantum "
220-
"startups."
221-
),
213+
"summary": "Investment trends across quantum startups.",
222214
}
223215
],
224216
"open_questions": ["How will regulation shape deployment?"],
@@ -244,213 +236,6 @@ def test_compendium_from_payload_normalizes_fields():
244236
assert compendium.trace[0].event_id == "ws_1"
245237

246238

247-
class FakeResponse:
248-
def __init__(
249-
self,
250-
*,
251-
output_text=None,
252-
output=None,
253-
status="completed",
254-
response_id="resp_1",
255-
):
256-
self.output_text = output_text
257-
self.output = output or []
258-
self.status = status
259-
self.id = response_id
260-
261-
262-
class FakeResponsesAPI:
263-
def __init__(self, plan_json: str, research_json: str):
264-
self.plan_json = plan_json
265-
self.research_json = research_json
266-
self.calls: list[dict[str, str]] = []
267-
268-
def create(self, **kwargs):
269-
model = kwargs.get("model")
270-
self.calls.append(
271-
{"model": model, "input": kwargs.get("input", "")}
272-
)
273-
274-
if model in {"gpt-4.1", "gpt-4.1-mini"}:
275-
return FakeResponse(
276-
output_text=self.plan_json,
277-
response_id="plan_1",
278-
)
279-
280-
if model == "o3-deep-research":
281-
output = [
282-
{
283-
"type": "web_search_call",
284-
"id": "ws_1",
285-
"status": "completed",
286-
"action": {
287-
"type": "search",
288-
"query": "quantum computing breakthroughs",
289-
},
290-
},
291-
{
292-
"type": "message",
293-
"content": [
294-
{
295-
"type": "output_text",
296-
"text": self.research_json,
297-
}
298-
],
299-
},
300-
]
301-
return FakeResponse(
302-
output=output,
303-
status="completed",
304-
response_id="research_1",
305-
)
306-
307-
raise AssertionError(f"Unexpected model request: {model}")
308-
309-
def retrieve(self, response_id: str):
310-
# pragma: no cover - not exercised in this test
311-
raise AssertionError(
312-
f"retrieve called unexpectedly for {response_id}"
313-
)
314-
315-
316-
class FakeOpenAI:
317-
def __init__(self, plan_json: str, research_json: str):
318-
self.responses = FakeResponsesAPI(plan_json, research_json)
319-
320-
321-
def test_build_compendium_with_stub_client():
322-
plan = {
323-
"primary_objective": "Build a comprehensive compendium",
324-
"audience": "Strategic leadership teams",
325-
"key_sections": [
326-
{"title": "Context", "focus": "Historical milestones"},
327-
{"title": "Applications", "focus": "Practical deployments"},
328-
],
329-
"research_questions": [
330-
"What breakthroughs unlocked current capabilities?",
331-
"Who are the leading vendors?",
332-
],
333-
"methodology_preferences": [
334-
"Verify each statistic using at least two sources",
335-
"Prioritize materials from 2022 onward",
336-
],
337-
}
338-
339-
research_payload = {
340-
"topic_overview": (
341-
"Quantum computing is transitioning from lab prototypes to early "
342-
"commercial pilots."
343-
),
344-
"methodology": [
345-
"Surveyed public filings and analyst coverage",
346-
"Aggregated investment data across multiple trackers",
347-
],
348-
"sections": [
349-
{
350-
"id": "S1",
351-
"title": "Technological Foundations",
352-
"summary": (
353-
"Hardware approaches and error correction challenges"
354-
),
355-
"key_terms": ["superconducting qubits"],
356-
"guiding_questions": [
357-
"Which modalities show the most promise?"
358-
],
359-
"insights": [
360-
{
361-
"title": (
362-
"Superconducting qubits dominate near-term "
363-
"roadmaps"
364-
),
365-
"evidence": (
366-
"IBM and Google published roadmaps targeting "
367-
">1000 qubits with heavy error mitigation by 2025."
368-
),
369-
"implications": (
370-
"Vendor lock-in may increase as proprietary "
371-
"control stacks mature."
372-
),
373-
"citations": ["C1", "C2"],
374-
}
375-
],
376-
}
377-
],
378-
"citations": [
379-
{
380-
"id": "C1",
381-
"title": "IBM Quantum Roadmap",
382-
"url": "https://example.com/ibm-roadmap",
383-
"publisher": "IBM",
384-
"published_at": "2023-12-01",
385-
"summary": "Targets for qubit scaling and error mitigation.",
386-
},
387-
{
388-
"id": "C2",
389-
"title": "Google Quantum AI Progress Update",
390-
"url": "https://example.com/google-qa",
391-
"publisher": "Google",
392-
"published_at": "2024-02-10",
393-
"summary": "Highlights on achieving reduced error rates.",
394-
},
395-
],
396-
"open_questions": [
397-
"How will supply chains support dilution refrigerators at scale?"
398-
],
399-
}
400-
401-
client = FakeOpenAI(json.dumps(plan), json.dumps(research_payload))
402-
config = ResearchConfig(background=False, stream_progress=False)
403-
404-
compendium = build_compendium(
405-
"Quantum Computing",
406-
client=client,
407-
config=config,
408-
)
409-
410-
assert compendium.overview.startswith(
411-
"Quantum computing is transitioning"
412-
)
413-
assert compendium.sections[0].insights[0].citation_refs == ["C1", "C2"]
414-
assert (
415-
compendium.citations[1].title
416-
== "Google Quantum AI Progress Update"
417-
)
418-
assert compendium.trace[0].event_type == "web_search_call"
419-
assert len(client.responses.calls) == 2
420-
assert "Quantum Computing" in client.responses.calls[1]["input"]
421-
422-
423-
def test_build_compendium_emits_progress_updates():
424-
plan = {"primary_objective": "Capture topic"}
425-
research_payload = {
426-
"topic_overview": "Overview",
427-
"methodology": [],
428-
"sections": [],
429-
"citations": [],
430-
"open_questions": [],
431-
}
432-
433-
client = FakeOpenAI(json.dumps(plan), json.dumps(research_payload))
434-
captured: list = []
435-
436-
def capture_progress(update):
437-
captured.append(update)
438-
439-
config = ResearchConfig(
440-
background=False,
441-
progress_callback=capture_progress,
442-
stream_progress=False,
443-
)
444-
445-
build_compendium("Test Topic", client=client, config=config)
446-
447-
assert captured, "Expected progress callback to receive updates"
448-
phases = {event.phase for event in captured}
449-
assert "planning" in phases
450-
assert "deep_research" in phases
451-
assert any(event.status == "completed" for event in captured)
452-
453-
454239
def test_compendium_from_payload_generates_event_id_when_missing():
455240
payload = {
456241
"topic_overview": "Overview",

tests/research/__init__.py

Whitespace-only changes.

tests/research/test_config.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from __future__ import annotations
2+
3+
from compendiumscribe.research.config import ResearchConfig
4+
5+
6+
def test_research_config_uses_env_override(monkeypatch):
7+
monkeypatch.setenv("RESEARCH_MODEL", "custom-deep-model")
8+
9+
config = ResearchConfig()
10+
11+
assert config.deep_research_model == "custom-deep-model"

0 commit comments

Comments
 (0)