test: add integration tests for all modules
Some checks failed
Continuous Integration / Build Package (push) Successful in 34s
Continuous Integration / Lint, Check & Test (push) Failing after 48s

- 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
This commit is contained in:
Konstantin Fickel 2026-02-14 11:07:36 +01:00
parent 452b3c4eb0
commit eef9712924
Signed by: kfickel
GPG key ID: A793722F9933C1A5
10 changed files with 1662 additions and 0 deletions

79
tests/conftest.py Normal file
View file

@ -0,0 +1,79 @@
"""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