Testing
Testing guidelines for Copinance OS. Favor unit tests on pure domain and tool logic; integration tests with mocked providers for I/O; use the DI container’s overrides to inject fakes for ResearchOrchestrator / JobRunner when testing orchestration.
Test Structure
Tests are organized to mirror the source code structure:
tests/
├── unit/ # Unit tests
│ └── copinance_os/
│ ├── domain/
│ ├── research/workflows/
│ ├── data/
│ ├── core/
│ ├── ai/
│ ├── infra/
│ └── interfaces/cli/
└── integration/ # Integration tests
└── copinance_os/
├── data/
└── core/execution_engine/Running Tests
pyproject.toml enables coverage in the default pytest invocation (addopts). Use pytest --no-cov for a faster loop when you do not need a coverage report.
# All tests (includes coverage per project defaults)
pytest
# Skip coverage
pytest --no-cov
# Unit tests only
pytest -m unit
# Integration tests only
pytest -m integration
# Explicit coverage HTML (also on by default unless --no-cov)
pytest --cov=copinance_os --cov-report=htmlWriting Tests
Unit Tests
Test individual components in isolation:
import pytest
from copinance_os.domain.models.job import Job, JobScope, JobStatus, JobTimeframe
from copinance_os.domain.models.market import MarketType
def test_job_creation():
job = Job(
scope=JobScope.INSTRUMENT,
market_type=MarketType.EQUITY,
instrument_symbol="AAPL",
timeframe=JobTimeframe.MID_TERM,
execution_type="deterministic_instrument_analysis",
)
assert job.status == JobStatus.PENDINGIntegration Tests
Test component interactions using fixtures from tests/conftest.py:
import pytest
from copinance_os.data.repositories import StockRepositoryImpl
from copinance_os.domain.models.stock import Stock
@pytest.mark.integration
async def test_stock_repository_save_and_get(isolated_storage):
repo = StockRepositoryImpl(storage=isolated_storage)
stock = Stock(symbol="AAPL", name="Apple Inc.", exchange="NASDAQ")
saved = await repo.save(stock)
retrieved = await repo.get_by_symbol(saved.symbol)
assert retrieved is not None
assert retrieved.symbol == saved.symbolTest Fixtures
Common fixtures are available in tests/conftest.py:
isolated_storage: Isolated storage for each testprofile_repository: Profile repository with isolated storage
Test Markers
Use markers to categorize tests:
@pytest.mark.unit
def test_unit_example():
pass
@pytest.mark.integration
async def test_integration_example():
passBest Practices
- Isolation: Each test should be independent
- Fixtures: Use fixtures for common setup
- Async: Use
pytest-asynciofor async tests - Coverage: Aim for high test coverage
- Naming: Use descriptive test names