Add testing infrastructure and refactor DAG transformation
Testing setup: - Add pyproject.toml with mypy and pytest configuration - Add requirements-dev.txt for development dependencies - Create tests/ directory with test fixtures - Add 17 unit tests for DAG transformation pipeline Type annotations: - Add app/types.py with TypedDict definitions for node configs - Add typed helper functions: transform_node, build_input_name_mapping, bind_inputs, prepare_dag_for_execution - Refactor run_recipe to use the new typed helpers Regression tests for today's bugs: - test_effect_cid_key_not_effect_hash: Verifies CID uses 'cid' key - test_source_cid_binding_persists: Verifies bound CIDs in final DAG Run tests with: pytest tests/ -v Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
93
tests/conftest.py
Normal file
93
tests/conftest.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
Pytest fixtures for art-celery tests.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from typing import Any, Dict, List
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_compiled_nodes() -> List[Dict[str, Any]]:
|
||||
"""Sample nodes as produced by the S-expression compiler."""
|
||||
return [
|
||||
{
|
||||
"id": "source_1",
|
||||
"type": "SOURCE",
|
||||
"config": {"asset": "cat"},
|
||||
"inputs": [],
|
||||
"name": None,
|
||||
},
|
||||
{
|
||||
"id": "source_2",
|
||||
"type": "SOURCE",
|
||||
"config": {
|
||||
"input": True,
|
||||
"name": "Second Video",
|
||||
"description": "A user-provided video",
|
||||
},
|
||||
"inputs": [],
|
||||
"name": "second-video",
|
||||
},
|
||||
{
|
||||
"id": "effect_1",
|
||||
"type": "EFFECT",
|
||||
"config": {"effect": "identity"},
|
||||
"inputs": ["source_1"],
|
||||
"name": None,
|
||||
},
|
||||
{
|
||||
"id": "effect_2",
|
||||
"type": "EFFECT",
|
||||
"config": {"effect": "invert", "intensity": 1.0},
|
||||
"inputs": ["source_2"],
|
||||
"name": None,
|
||||
},
|
||||
{
|
||||
"id": "sequence_1",
|
||||
"type": "SEQUENCE",
|
||||
"config": {},
|
||||
"inputs": ["effect_1", "effect_2"],
|
||||
"name": None,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_registry() -> Dict[str, Dict[str, Any]]:
|
||||
"""Sample registry with assets and effects."""
|
||||
return {
|
||||
"assets": {
|
||||
"cat": {
|
||||
"cid": "QmXrj6tSSn1vQXxxEY2Tyoudvt4CeeqR9gGQwSt7WFrhMZ",
|
||||
"url": "https://example.com/cat.jpg",
|
||||
},
|
||||
},
|
||||
"effects": {
|
||||
"identity": {
|
||||
"cid": "QmcWhw6wbHr1GDmorM2KDz8S3yCGTfjuyPR6y8khS2tvko",
|
||||
},
|
||||
"invert": {
|
||||
"cid": "QmPWaW5E5WFrmDjT6w8enqvtJhM8c5jvQu7XN1doHA3Z7J",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_recipe(
|
||||
sample_compiled_nodes: List[Dict[str, Any]],
|
||||
sample_registry: Dict[str, Dict[str, Any]],
|
||||
) -> Dict[str, Any]:
|
||||
"""Sample compiled recipe."""
|
||||
return {
|
||||
"name": "test-recipe",
|
||||
"version": "1.0",
|
||||
"description": "A test recipe",
|
||||
"owner": "@test@example.com",
|
||||
"registry": sample_registry,
|
||||
"dag": {
|
||||
"nodes": sample_compiled_nodes,
|
||||
"output": "sequence_1",
|
||||
},
|
||||
"recipe_id": "Qmtest123",
|
||||
}
|
||||
Reference in New Issue
Block a user