Skip to content

Tests

Summary

DirectoryTestsWhat it covers
tests/tools/73OSINT tools mocked with respx
tests/investigation/77InvestigationDB, normalize, extract, chunk
tests/integration/17MCP, A2A, service facade
tests/ (root)41Cache, dashboard, session, anomaly detector, market correlation, narrative detector
Total208

Requirements

Ventana de terminal
pip install -e ".[dev]"

Installs development dependencies: pytest, respx, pytest-asyncio, httpx, etc.

Running tests

Ventana de terminal
# Complete suite
pytest tests/ -v
# OSINT tools only (fast, no API keys needed)
pytest tests/tools/ -v
# Investigation only (no API keys needed, SQLite in tmp_path)
pytest tests/investigation/ -v
# Integration only (MCP, A2A)
pytest tests/integration/ -v
# With coverage
pytest tests/ --cov=src --cov-report=html

Tool tests (tests/tools/)

Each tool has its own test file. All HTTP calls are mocked with respx — no real API keys needed.

tests/tools/test_virustotal.py
import pytest
import respx
from httpx import Response
from src.tools.virustotal import virustotal_ip_lookup
@pytest.mark.asyncio
@respx.mock
async def test_virustotal_ip_lookup():
respx.get("https://www.virustotal.com/api/v3/ip_addresses/8.8.8.8").mock(
return_value=Response(200, json={
"data": {
"attributes": {
"last_analysis_stats": {"malicious": 0, "harmless": 89},
"reputation": 8,
"country": "US",
"asn": 15169,
"as_owner": "GOOGLE"
}
}
})
)
result = await virustotal_ip_lookup("8.8.8.8")
assert result["malicious_count"] == 0
assert result["country"] == "US"

Investigation tests (tests/investigation/)

Use pytest’s tmp_path to create temporary SQLite databases — completely isolated, no shared state:

tests/investigation/test_manager.py
import pytest
from src.investigation.manager import InvestigationManager
@pytest.mark.asyncio
async def test_create_investigation(tmp_path):
db_path = tmp_path / "test.db"
manager = InvestigationManager(db_path=str(db_path))
investigation = await manager.create(
name="Test Investigation",
goal="Testing"
)
assert investigation.slug == "test-investigation"
assert investigation.status == "active"

Integration tests (tests/integration/)

Verify that the MCP Server correctly registers all tools and that the A2A Server returns the correct agent card:

tests/integration/test_mcp.py
def test_mcp_tool_count():
from src.mcp_server.server import mcp
tools = mcp.get_tools()
assert len(tools) >= 29
def test_mcp_tool_names():
from src.mcp_server.server import mcp
tool_names = [t.name for t in mcp.get_tools()]
assert "virustotal_ip_lookup" in tool_names
assert "investigate_ioc" in tool_names
assert "create_investigation" in tool_names

Linting and formatting

Ventana de terminal
# Linting
ruff check src/ tests/
# Automatic formatting
ruff format src/ tests/
# Type checking
mypy src/

Pre-commit hooks

The project includes pre-commit hooks:

Ventana de terminal
# Install hooks
pre-commit install
# Run manually
pre-commit run --all-files

Hooks configured in .pre-commit-config.yaml:

  • ruff (lint + format)
  • mypy (type check)

CI

GitHub Actions runs the complete suite on each push to main. See .github/workflows/ for the configuration.

Adding a new test

For a new tool in src/tools/my_tool.py:

  1. Create tests/tools/test_my_tool.py
  2. Use @respx.mock to mock HTTP calls
  3. Cover cases: normal response, 404 error, timeout, invalid key
  4. Run pytest tests/tools/test_my_tool.py -v to verify