- 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
143 lines
4.8 KiB
Python
143 lines
4.8 KiB
Python
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
|