Tests
Resumen
| Directorio | Tests | Que cubre |
|---|---|---|
tests/tools/ | 73 | Herramientas OSINT mockeadas con respx |
tests/investigation/ | 77 | InvestigationDB, normalize, extract, chunk |
tests/integration/ | 17 | MCP, A2A, fachada de servicio |
tests/ (raiz) | 41 | Cache, dashboard, sesion, anomaly detector, market correlation, narrative detector |
| Total | 208 | — |
Requisitos
pip install -e ".[dev]"Instala dependencias de desarrollo: pytest, respx, pytest-asyncio, httpx, etc.
Ejecutar los tests
# Suite completapytest tests/ -v
# Solo herramientas OSINT (rapido, no necesita API keys)pytest tests/tools/ -v
# Solo investigaciones (no necesita API keys, SQLite en tmp_path)pytest tests/investigation/ -v
# Solo integracion (MCP, A2A)pytest tests/integration/ -v
# Con coveragepytest tests/ --cov=src --cov-report=htmlTests de herramientas (tests/tools/)
Cada herramienta tiene su propio fichero de tests. Todas las llamadas HTTP estan mockeadas con respx — no necesitas API keys reales.
import pytestimport respxfrom httpx import Responsefrom src.tools.virustotal import virustotal_ip_lookup
@pytest.mark.asyncio@respx.mockasync 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"Tests de investigacion (tests/investigation/)
Usan tmp_path de pytest para crear bases de datos SQLite temporales — completamente aislados, sin estado compartido:
import pytestfrom src.investigation.manager import InvestigationManager
@pytest.mark.asyncioasync 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"Tests de integracion (tests/integration/)
Verifican que el MCP Server registra correctamente todas las tools y que el A2A Server devuelve el agent card correcto:
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_namesLinting y formato
# Lintingruff check src/ tests/
# Formato automaticoruff format src/ tests/
# Type checkingmypy src/Pre-commit hooks
El proyecto incluye hooks de pre-commit:
# Instalar hookspre-commit install
# Ejecutar manualmentepre-commit run --all-filesHooks configurados en .pre-commit-config.yaml:
- ruff (lint + format)
- mypy (type check)
CI
GitHub Actions ejecuta la suite completa en cada push a main. Ver .github/workflows/ para la configuracion.
Añadir un test nuevo
Para una nueva herramienta en src/tools/mi_herramienta.py:
- Crea
tests/tools/test_mi_herramienta.py - Usa
@respx.mockpara mockear las llamadas HTTP - Cubre los casos: respuesta normal, error 404, timeout, clave invalida
- Ejecuta
pytest tests/tools/test_mi_herramienta.py -vpara verificar