feat(tests): adicionar suite completa de testes automatizados
- 198 testes cobrindo todos os módulos do backend - Testes unitários para calculador de pontuação (56 testes) - Testes para value objects de período (23 testes) - Testes para cliente Elasticsearch com mocks (27 testes) - Testes para repository de consultores (48 testes) - Testes de integração ES + Repository (6 testes) - Testes para API routes FastAPI (23 testes) - Testes para job de processamento (16 testes) - Cobertura de 54% do código
This commit is contained in:
142
backend/tests/integration/test_scroll_flow.py
Normal file
142
backend/tests/integration/test_scroll_flow.py
Normal file
@@ -0,0 +1,142 @@
|
||||
import pytest
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
from httpx import Response
|
||||
|
||||
from src.infrastructure.elasticsearch.client import ElasticsearchClient
|
||||
from src.infrastructure.repositories.consultor_repository_impl import ConsultorRepositoryImpl
|
||||
from src.domain.services.calculador_pontuacao import CalculadorPontuacao
|
||||
|
||||
|
||||
def create_mock_response(json_data, status_code=200):
|
||||
response = MagicMock(spec=Response)
|
||||
response.json.return_value = json_data
|
||||
response.status_code = status_code
|
||||
response.raise_for_status = MagicMock()
|
||||
return response
|
||||
|
||||
|
||||
def criar_doc_consultor(id_pessoa, nome, atuacoes):
|
||||
return {
|
||||
"id": id_pessoa,
|
||||
"dadosPessoais": {"nome": nome},
|
||||
"atuacoes": atuacoes
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def es_client():
|
||||
return ElasticsearchClient(
|
||||
url="http://localhost:9200",
|
||||
index="atuacapes_test"
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def repository(es_client):
|
||||
return ConsultorRepositoryImpl(es_client)
|
||||
|
||||
|
||||
class TestScrollFlowCompleto:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_processamento_scroll_com_ranking(self, es_client, repository):
|
||||
docs_batch_1 = [
|
||||
criar_doc_consultor(1, "COORD AREA", [{
|
||||
"tipo": "Coordenação de Área de Avaliação",
|
||||
"inicio": "01/01/2018",
|
||||
"dadosCoordenacaoArea": {"tipo": "Coordenador de Área"}
|
||||
}]),
|
||||
criar_doc_consultor(2, "COORD ADJUNTO", [{
|
||||
"tipo": "Coordenação de Área de Avaliação",
|
||||
"inicio": "01/01/2020",
|
||||
"dadosCoordenacaoArea": {"tipo": "Coordenador Adjunto"}
|
||||
}]),
|
||||
]
|
||||
|
||||
docs_batch_2 = [
|
||||
criar_doc_consultor(3, "CONSULTOR ATIVO", [{
|
||||
"tipo": "Consultor",
|
||||
"inicio": "01/01/2015",
|
||||
"dadosConsultoria": {"situacaoConsultoria": "Atividade Contínua"}
|
||||
}]),
|
||||
criar_doc_consultor(4, "PESSOA SEM ATUACAO", []),
|
||||
]
|
||||
|
||||
scroll_1 = {
|
||||
"_scroll_id": "scroll_1",
|
||||
"hits": {
|
||||
"total": {"value": 4},
|
||||
"hits": [{"_source": d} for d in docs_batch_1]
|
||||
}
|
||||
}
|
||||
|
||||
scroll_2 = {
|
||||
"_scroll_id": "scroll_2",
|
||||
"hits": {"hits": [{"_source": d} for d in docs_batch_2]}
|
||||
}
|
||||
|
||||
scroll_empty = {"_scroll_id": "scroll_3", "hits": {"hits": []}}
|
||||
|
||||
ranking_results = []
|
||||
|
||||
async def processar_batch(docs, progress):
|
||||
for doc in docs:
|
||||
consultor = await repository._construir_consultor(doc)
|
||||
pontuacao = CalculadorPontuacao.calcular_pontuacao_completa(consultor)
|
||||
ranking_results.append({
|
||||
"id": consultor.id_pessoa,
|
||||
"nome": consultor.nome,
|
||||
"total": pontuacao.total
|
||||
})
|
||||
|
||||
with patch.object(es_client, '_client') as mock_client:
|
||||
mock_client.is_closed = False
|
||||
mock_client.post = AsyncMock(side_effect=[
|
||||
create_mock_response(scroll_1),
|
||||
create_mock_response(scroll_2),
|
||||
create_mock_response(scroll_empty)
|
||||
])
|
||||
mock_client.delete = AsyncMock(return_value=create_mock_response({}))
|
||||
|
||||
result = await es_client.buscar_todos_consultores(processar_batch, batch_size=2)
|
||||
|
||||
assert result["total"] == 4
|
||||
assert result["processados"] == 4
|
||||
assert len(ranking_results) == 4
|
||||
|
||||
|
||||
class TestProgressoScroll:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_progress_callback(self, es_client):
|
||||
progress_history = []
|
||||
|
||||
async def callback(docs, progress):
|
||||
progress_history.append(progress.copy())
|
||||
|
||||
scroll_1 = {
|
||||
"_scroll_id": "s1",
|
||||
"hits": {"total": {"value": 100}, "hits": [{"_source": {"id": i}} for i in range(50)]}
|
||||
}
|
||||
scroll_2 = {
|
||||
"_scroll_id": "s2",
|
||||
"hits": {"hits": [{"_source": {"id": i}} for i in range(50, 100)]}
|
||||
}
|
||||
scroll_empty = {"_scroll_id": "s3", "hits": {"hits": []}}
|
||||
|
||||
with patch.object(es_client, '_client') as mock_client:
|
||||
mock_client.is_closed = False
|
||||
mock_client.post = AsyncMock(side_effect=[
|
||||
create_mock_response(scroll_1),
|
||||
create_mock_response(scroll_2),
|
||||
create_mock_response(scroll_empty)
|
||||
])
|
||||
mock_client.delete = AsyncMock(return_value=create_mock_response({}))
|
||||
|
||||
await es_client.buscar_todos_consultores(callback, batch_size=50)
|
||||
|
||||
assert len(progress_history) == 2
|
||||
assert progress_history[0]["percentual"] == 50
|
||||
assert progress_history[0]["processados"] == 50
|
||||
assert progress_history[1]["percentual"] == 100
|
||||
assert progress_history[1]["processados"] == 100
|
||||
Reference in New Issue
Block a user