From economist-agents
Testing patterns for the economist-agents multi-agent system. Use when writing tests for agent code, when mocking API calls, when setting up test fixtures, when debugging coverage gaps.
npx claudepluginhub oviney/economist-agentsThis skill uses the workspace's default tool permissions.
All agent code must be testable. Mock all external API calls (OpenAI, Anthropic), test both success and failure paths, validate agent outputs against schemas, and maintain ≥80% coverage.
Applies Acme Corporation brand guidelines including colors, fonts, layouts, and messaging to generated PowerPoint, Excel, and PDF documents.
Guides strict Test-Driven Development (TDD): write failing tests first for features, bugfixes, refactors before any production code. Enforces red-green-refactor cycle.
Share bugs, ideas, or general feedback.
All agent code must be testable. Mock all external API calls (OpenAI, Anthropic), test both success and failure paths, validate agent outputs against schemas, and maintain ≥80% coverage.
python-qualityquality-gatesarticle-evaluationdef test_function_name():
# Arrange — set up test data and mocks
mock_client = Mock()
expected = {"key": "value"}
# Act — call the function under test
result = function_under_test(mock_client)
# Assert — verify the results
assert result == expected
OpenAI:
@pytest.fixture
def mock_openai_client():
with patch('openai.OpenAI') as mock:
instance = Mock()
response = Mock()
response.choices = [Mock(message=Mock(content='{"result": "success"}'))]
response.usage = Mock(total_tokens=100)
response.model = "gpt-4o"
instance.chat.completions.create.return_value = response
mock.return_value = instance
yield instance
Anthropic:
@pytest.fixture
def mock_anthropic_client():
with patch('anthropic.Anthropic') as mock:
instance = Mock()
response = Mock()
response.content = [Mock(text='{"result": "success"}')]
response.usage = Mock(input_tokens=100, output_tokens=50)
instance.messages.create.return_value = response
mock.return_value = instance
yield instance
Error handling:
def test_api_error_handling(mock_openai_client, caplog):
mock_openai_client.chat.completions.create.side_effect = APIError("Rate limit")
with pytest.raises(APIError):
my_function(mock_openai_client)
assert "API call failed" in caplog.text
# Use tmp_path for file operations
def test_save_output(tmp_path):
path = tmp_path / "output.json"
save_output({"key": "value"}, path)
assert path.exists()
# Use monkeypatch for env vars
def test_missing_api_key(monkeypatch):
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
with pytest.raises(ValueError):
initialize_client()
pytest --cov=scripts --cov-report=term-missing tests/
Minimum: 80%. Uncovered lines should only be __main__ blocks and sys.path guards.
tests/test_<module_name>.pytests/test_mcp_servers/test_<server_name>.pytest_<function>_<scenario>tests/conftest.py| Rationalization | Reality |
|---|---|
| "Mocking is too complex for this function" | If the function is hard to mock, it's doing too much — refactor it |
| "We'll add tests after the feature ships" | Tests after shipping means bugs ship first; write tests alongside code |
| "80% coverage is arbitrary" | It's a ratchet — uncovered code is untested code, and untested agent code fails silently |
| "Integration tests are enough" | Integration tests are slow and flaky; unit tests with mocks give fast, deterministic feedback |
| "This is just a script, it doesn't need tests" | Scripts become library code when agents compose them — test them like library code |
monkeypatch not used for environment variablestmp_path not used for file operations (tests write to repo)test_1, test_basic)git diff --name-only shows test files for each source fileMock or patch in test files, no real API imports_success and _error/_failure variantspytest --cov outputtmp_path for file I/O — evidence: no hardcoded paths in test filesmonkeypatch for env vars — evidence: no os.environ direct manipulationpytest tests/ -v — evidence: zero failures