# ComfyUI MCP Server - Test Guidelines
**Purpose**: Behavioral guide for AI coding assistants when working on the test suite.
---
## Test Architecture
### Current Structure
All tests have been updated to use the refactored architecture:
```
tests/
├── conftest.py ✅ Fixtures for AssetOrchestrator, NoAuth
├── test_asset_registry.py ✅ Unit tests for AssetOrchestrator
├── test_basic.py ✅ Basic smoke tests
├── test_edge_cases.py ✅ Edge case and boundary tests
├── test_job_tools.py ✅ Job management tool tests
├── test_publish.py ✅ Publish manager tests
└── clients/
└── test_client.py ✅ HTTP client for manual testing
```
---
## Test Principles
### 1. Test Intent Over Implementation
When updating tests:
1. **Understand the intent**: What behavior is being validated?
2. **Preserve the intent**: Keep the test's purpose intact
3. **Update the implementation**: Use current API/structure
4. **Don't change behavior**: Unless it's actually broken
### 2. Use Current Architecture
All tests should use:
- `src.orchestrators.asset.AssetOrchestrator` (not `managers.asset_registry.AssetRegistry`)
- `src.auth.base.NoAuth` for test authentication
- `src.models.asset.AssetRecord` for asset data structures
- `src.orchestrators.publish.PublishManager` for publish tests
### 3. Fixture Guidelines
**conftest.py fixtures:**
```python
@pytest.fixture
def asset_orchestrator():
"""Create a fresh AssetOrchestrator for each test."""
auth = NoAuth("http://localhost:8188")
return AssetOrchestrator(auth=auth, ttl_hours=24)
```
**Usage in tests:**
```python
def test_something(asset_orchestrator):
# Register asset
asset_record = asset_orchestrator.register_asset(
filename="test.png",
subfolder="",
folder_type="output",
workflow_id="generate_image",
prompt_id="test_123",
comfy_history={},
submitted_workflow={}
)
# Look up asset
found = asset_orchestrator.get_asset_record(asset_record.asset_id)
assert found is not None
```
---
## API Changes
### Old vs New API
| Old API (managers.asset_registry) | New API (orchestrators.asset) |
|-----------------------------------|-------------------------------|
| `AssetRegistry(comfyui_base_url="...")` | `AssetOrchestrator(auth=NoAuth("..."))` |
| `registry.get_asset(asset_id)` | `orchestrator.get_asset_record(asset_id)` |
| `registry.register_asset(...)` | `orchestrator.register_asset(...)` (same signature) |
| `registry.list_assets(...)` | `orchestrator.list_assets(...)` (same signature) |
### Publish Manager
| Old Import | New Import |
|------------|------------|
| `from managers.publish_manager import ...` | `from src.orchestrators.publish import ...` |
---
## Running Tests
### Quick Start
```bash
# Install dependencies (if needed)
uv sync
# Run all tests
pytest tests/ -v
# Run specific test file
pytest tests/test_asset_registry.py -v
# Run specific test
pytest tests/test_asset_registry.py::test_register_and_lookup -v
# Run with coverage
pytest tests/ --cov=src --cov-report=html
```
### Test Categories
**Unit Tests** (fast, no external dependencies):
- `test_asset_registry.py` - Asset orchestrator logic
- `test_basic.py` - Basic functionality
- `test_edge_cases.py` - Boundary conditions
- `test_job_tools.py` - Tool registration (simplified)
**Integration Tests** (require ComfyUI running):
- `test_publish.py` - Publish manager with real filesystem
- Manual testing with `clients/test_client.py`
---
## Common Test Patterns
### 1. Asset Registration and Lookup
```python
def test_asset_lifecycle(asset_orchestrator):
# Register
asset = asset_orchestrator.register_asset(
filename="test.png",
subfolder="",
folder_type="output",
workflow_id="generate_image",
prompt_id="prompt_123",
comfy_history={},
submitted_workflow={}
)
# Lookup by ID
found = asset_orchestrator.get_asset_record(asset.asset_id)
assert found is not None
# Lookup by identity
found2 = asset_orchestrator.get_asset_by_identity(
"test.png", "", "output"
)
assert found2.asset_id == asset.asset_id
```
### 2. TTL and Expiration
```python
def test_expiration(asset_orchestrator):
import time
# Use short TTL
auth = NoAuth("http://localhost:8188")
registry = AssetOrchestrator(auth=auth, ttl_hours=0.0001)
asset = registry.register_asset(...)
time.sleep(1)
# Cleanup expired
removed = registry.cleanup_expired()
assert removed == 1
# Asset should be gone
assert registry.get_asset_record(asset.asset_id) is None
```
### 3. Publish Manager Setup
```python
def test_publish(tmp_path, asset_orchestrator):
# Setup directories
output_root = tmp_path / "comfyui" / "output"
output_root.mkdir(parents=True)
# Create source file
source_file = output_root / "test.png"
source_file.write_text("test content")
# Configure publish manager
config = PublishConfig(
project_root=tmp_path,
publish_root=tmp_path / "publish",
comfyui_output_root=output_root
)
manager = PublishManager(config)
# Register asset
asset = asset_orchestrator.register_asset(
filename="test.png",
subfolder="",
folder_type="output",
workflow_id="generate_image",
prompt_id="test_123"
)
# Test publish logic...
```
---
## Troubleshooting
### Import Errors
If you see:
```
ModuleNotFoundError: No module named 'managers'
```
**Fix**: Update imports to use `src.orchestrators.*`
### Fixture Errors
If you see:
```
fixture 'asset_registry' not found
```
**Fix**: Update test signature to use `asset_orchestrator` (defined in conftest.py)
### API Errors
If you see:
```
AttributeError: 'AssetOrchestrator' object has no attribute 'get_asset'
```
**Fix**: Use `get_asset_record()` instead of `get_asset()`
### Auth Errors
If you see:
```
TypeError: __init__() missing required positional argument: 'auth'
```
**Fix**: Pass `NoAuth` instance:
```python
auth = NoAuth("http://localhost:8188")
orchestrator = AssetOrchestrator(auth=auth)
```
---
## Minimizing Codebase Changes
When updating tests:
### ✅ Safe to Update
- Import paths (old `managers.*` → new `src.orchestrators.*`)
- Method names (`.get_asset()` → `.get_asset_record()`)
- Constructor signatures (`AssetRegistry(comfyui_base_url=...)` → `AssetOrchestrator(auth=...)`)
- Test fixtures (use `asset_orchestrator` from conftest.py)
### ❌ Avoid Changing
- Test logic and assertions (preserve intent)
- Expected behavior (unless fixing actual bugs)
- Test data and scenarios (unless broken)
- Core architecture code (unless truly broken)
### 🤔 When to Change Core Code
Only modify core codebase if:
1. **Actual bug found**: Test reveals real broken behavior
2. **Missing functionality**: Test expects feature that should exist
3. **API inconsistency**: Method signature doesn't match documented behavior
**Before changing core code:**
1. Verify the bug with manual testing
2. Check AGENTS.md for architectural guidance
3. Document the bug and fix in commit message
---
## Test Coverage Goals
### Current Status
- ✅ Asset lifecycle (registration, lookup, expiration)
- ✅ URL encoding and special characters
- ✅ Duplicate filename handling
- ✅ List/filter operations
- ✅ Publish manager path safety
- ⚠️ Job tools (simplified, integration tests needed)
- ⚠️ HTTP client tests (manual only)
### Next Steps
1. Add async tests for route functions (optional)
2. Integration tests with live ComfyUI (marked with `@pytest.mark.integration`)
3. Performance tests for large asset sets (optional)
---
## Quick Reference
### Test Commands
```bash
# Run all tests
pytest tests/ -v
# Run with coverage
pytest tests/ --cov=src --cov-report=term-missing
# Run specific test
pytest tests/test_asset_registry.py::test_register_and_lookup -v
# Run and stop on first failure
pytest tests/ -x
# Run and show print statements
pytest tests/ -s
# Run only tests matching pattern
pytest tests/ -k "asset" -v
```
### Key Fixtures
- `asset_orchestrator` - Fresh AssetOrchestrator instance
- `sample_asset_data` - Template asset data dict
- `tmp_path` - Pytest built-in temporary directory
### Key Imports
```python
# Orchestrators
from src.orchestrators.asset import AssetOrchestrator
from src.orchestrators.publish import PublishManager, PublishConfig
# Models
from src.models.asset import AssetRecord
# Auth
from src.auth.base import NoAuth
# Tools (for registration tests)
from src.tools.job import register_job_tools
```
---
**Last Updated**: January 23, 2025
**Status**: Tests updated for Phase 3 refactoring