- Add pytest-asyncio dev dependency and configure asyncio_mode=auto - Add filterwarnings to suppress third-party PydanticDeprecatedSince20 - Add conftest.py with shared fixtures (project_dir, write_config, etc.) - Add test_config.py: YAML loading, target type inference, model resolution - Add test_graph.py: DAG construction, cycle detection, build ordering - Add test_state.py: hash functions, state persistence, dirty checking - Add test_builder.py: full build pipeline with FakeProvider, incremental builds, selective builds, error isolation, dependency cascading - Add test_providers.py: ImageProvider and TextProvider with mocked clients - Add test_cli.py: build/clean/graph commands via typer CliRunner - All 94 tests pass with 0 basedpyright warnings
79 lines
2.2 KiB
Python
79 lines
2.2 KiB
Python
"""Shared fixtures for bulkgen integration tests."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
import yaml
|
|
|
|
from bulkgen.config import ProjectConfig, load_config
|
|
|
|
WriteConfig = Callable[[dict[str, object]], ProjectConfig]
|
|
|
|
|
|
@pytest.fixture
|
|
def project_dir(tmp_path: Path) -> Path:
|
|
"""A temporary directory acting as the project root."""
|
|
return tmp_path
|
|
|
|
|
|
@pytest.fixture
|
|
def write_config(project_dir: Path) -> WriteConfig:
|
|
"""Write a bulkgen YAML config and return the loaded ProjectConfig.
|
|
|
|
Usage::
|
|
|
|
config = write_config({"targets": {"out.txt": {"prompt": "hello"}}})
|
|
"""
|
|
|
|
def _write(raw: dict[str, object]) -> ProjectConfig:
|
|
config_path = project_dir / "project.bulkgen.yaml"
|
|
_ = config_path.write_text(yaml.dump(raw, default_flow_style=False))
|
|
return load_config(config_path)
|
|
|
|
return _write
|
|
|
|
|
|
@pytest.fixture
|
|
def simple_text_config(write_config: WriteConfig) -> ProjectConfig:
|
|
"""A minimal config with one text target."""
|
|
return write_config({"targets": {"output.txt": {"prompt": "Generate something"}}})
|
|
|
|
|
|
@pytest.fixture
|
|
def multi_target_config(project_dir: Path, write_config: WriteConfig) -> ProjectConfig:
|
|
"""Config with multiple targets forming a dependency chain.
|
|
|
|
input.txt (external file) -> summary.md -> final.txt
|
|
Also has an independent image target: hero.png
|
|
"""
|
|
_ = (project_dir / "input.txt").write_text("Some input content")
|
|
return write_config(
|
|
{
|
|
"targets": {
|
|
"summary.md": {
|
|
"prompt": "Summarize the input",
|
|
"inputs": ["input.txt"],
|
|
},
|
|
"final.txt": {
|
|
"prompt": "Finalize the summary",
|
|
"inputs": ["summary.md"],
|
|
},
|
|
"hero.png": {
|
|
"prompt": "A heroic landscape",
|
|
"width": 1024,
|
|
"height": 768,
|
|
},
|
|
}
|
|
}
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def prompt_file(project_dir: Path) -> Path:
|
|
"""Create a prompt file on disk and return its path."""
|
|
p = project_dir / "my_prompt.txt"
|
|
_ = p.write_text("This prompt comes from a file")
|
|
return p
|