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:
0
backend/tests/domain/__init__.py
Normal file
0
backend/tests/domain/__init__.py
Normal file
0
backend/tests/domain/services/__init__.py
Normal file
0
backend/tests/domain/services/__init__.py
Normal file
599
backend/tests/domain/services/test_calculador_pontuacao.py
Normal file
599
backend/tests/domain/services/test_calculador_pontuacao.py
Normal file
@@ -0,0 +1,599 @@
|
||||
import pytest
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from src.domain.services.calculador_pontuacao import CalculadorPontuacao
|
||||
from src.domain.entities.consultor import (
|
||||
Consultor,
|
||||
CoordenacaoCapes,
|
||||
Consultoria,
|
||||
Inscricao,
|
||||
AvaliacaoComissao,
|
||||
Premiacao,
|
||||
BolsaCNPQ,
|
||||
Participacao,
|
||||
)
|
||||
from src.domain.value_objects.periodo import Periodo
|
||||
from src.domain.value_objects.criterios_pontuacao import CRITERIOS
|
||||
|
||||
|
||||
def criar_periodo(anos_atras: int, ativo: bool = False, duracao_anos: int = 0) -> Periodo:
|
||||
inicio = datetime.now() - relativedelta(years=anos_atras)
|
||||
if ativo:
|
||||
fim = None
|
||||
else:
|
||||
fim = inicio + relativedelta(years=duracao_anos) if duracao_anos > 0 else datetime.now()
|
||||
return Periodo(inicio=inicio, fim=fim)
|
||||
|
||||
|
||||
class TestBlocoACoordenacaoCapes:
|
||||
|
||||
def test_coordenacao_vazia_retorna_bloco_vazio(self):
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a([])
|
||||
assert resultado.bloco == "A"
|
||||
assert resultado.total == 0
|
||||
assert len(resultado.atuacoes) == 0
|
||||
|
||||
def test_coordenador_area_base_200_pontos(self):
|
||||
coord = CoordenacaoCapes(
|
||||
codigo="CA",
|
||||
tipo="Coordenador de Área",
|
||||
area_avaliacao="CIÊNCIAS AMBIENTAIS",
|
||||
periodo=criar_periodo(anos_atras=0, duracao_anos=0),
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a([coord])
|
||||
assert resultado.total >= 200
|
||||
|
||||
def test_coordenador_area_ativo_recebe_bonus_atualidade(self):
|
||||
coord = CoordenacaoCapes(
|
||||
codigo="CA",
|
||||
tipo="Coordenador de Área",
|
||||
area_avaliacao="CIÊNCIAS AMBIENTAIS",
|
||||
periodo=criar_periodo(anos_atras=1, ativo=True),
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a([coord])
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.bonus >= 30
|
||||
|
||||
def test_coordenador_area_historico_sem_bonus_atualidade(self):
|
||||
coord = CoordenacaoCapes(
|
||||
codigo="CA",
|
||||
tipo="Coordenador de Área",
|
||||
area_avaliacao="MEDICINA I",
|
||||
periodo=criar_periodo(anos_atras=5, duracao_anos=3),
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a([coord])
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.codigo == "CA"
|
||||
assert 30 not in [atuacao.bonus] or atuacao.bonus < 30
|
||||
|
||||
def test_coordenador_area_5_anos_pontos_tempo(self):
|
||||
coord = CoordenacaoCapes(
|
||||
codigo="CA",
|
||||
tipo="Coordenador de Área",
|
||||
area_avaliacao="CIÊNCIAS AMBIENTAIS",
|
||||
periodo=criar_periodo(anos_atras=5, duracao_anos=5),
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a([coord])
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.tempo == 50
|
||||
|
||||
def test_coordenador_area_teto_tempo_100_pontos(self):
|
||||
coord = CoordenacaoCapes(
|
||||
codigo="CA",
|
||||
tipo="Coordenador de Área",
|
||||
area_avaliacao="CIÊNCIAS AMBIENTAIS",
|
||||
periodo=criar_periodo(anos_atras=15, duracao_anos=15),
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a([coord])
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.tempo == 100
|
||||
|
||||
def test_coordenador_area_teto_maximo_450(self):
|
||||
coord = CoordenacaoCapes(
|
||||
codigo="CA",
|
||||
tipo="Coordenador de Área",
|
||||
area_avaliacao="CIÊNCIAS AMBIENTAIS",
|
||||
periodo=criar_periodo(anos_atras=20, ativo=True),
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a([coord])
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.total <= 450
|
||||
|
||||
def test_coordenador_adjunto_base_150_pontos(self):
|
||||
coord = CoordenacaoCapes(
|
||||
codigo="CAJ",
|
||||
tipo="Coordenador Adjunto",
|
||||
area_avaliacao="ENGENHARIA I",
|
||||
periodo=criar_periodo(anos_atras=0, duracao_anos=0),
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a([coord])
|
||||
assert resultado.total >= 150
|
||||
|
||||
def test_coordenador_adjunto_mp_base_120_pontos(self):
|
||||
coord = CoordenacaoCapes(
|
||||
codigo="CAJ_MP",
|
||||
tipo="Coordenador Adjunto de Mestrado Profissionalizante",
|
||||
area_avaliacao="ADMINISTRAÇÃO",
|
||||
periodo=criar_periodo(anos_atras=0, duracao_anos=0),
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a([coord])
|
||||
assert resultado.total >= 120
|
||||
|
||||
def test_camara_tematica_base_100_pontos(self):
|
||||
coord = CoordenacaoCapes(
|
||||
codigo="CAM",
|
||||
tipo="Câmara Temática",
|
||||
area_avaliacao="INTERDISCIPLINAR",
|
||||
periodo=criar_periodo(anos_atras=0, duracao_anos=0),
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a([coord])
|
||||
assert resultado.total >= 100
|
||||
|
||||
def test_multiplas_coordenacoes_mesmo_tipo_soma_tempo(self):
|
||||
periodo1 = criar_periodo(anos_atras=10, duracao_anos=3)
|
||||
periodo2 = criar_periodo(anos_atras=5, duracao_anos=3)
|
||||
coords = [
|
||||
CoordenacaoCapes(
|
||||
codigo="CA", tipo="Coordenador de Área",
|
||||
area_avaliacao="ÁREA 1", periodo=periodo1
|
||||
),
|
||||
CoordenacaoCapes(
|
||||
codigo="CA", tipo="Coordenador de Área",
|
||||
area_avaliacao="ÁREA 2", periodo=periodo2
|
||||
),
|
||||
]
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a(coords)
|
||||
assert len(resultado.atuacoes) == 1
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.quantidade == 2
|
||||
assert atuacao.tempo == 60
|
||||
|
||||
def test_retorno_coordenacao_gera_bonus(self):
|
||||
periodo1 = criar_periodo(anos_atras=10, duracao_anos=3)
|
||||
periodo2 = criar_periodo(anos_atras=3, ativo=True)
|
||||
coords = [
|
||||
CoordenacaoCapes(
|
||||
codigo="CA", tipo="Coordenador de Área",
|
||||
area_avaliacao="ÁREA 1", periodo=periodo1
|
||||
),
|
||||
CoordenacaoCapes(
|
||||
codigo="CA", tipo="Coordenador de Área",
|
||||
area_avaliacao="ÁREA 1", periodo=periodo2
|
||||
),
|
||||
]
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a(coords)
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.bonus >= 20
|
||||
|
||||
def test_tipos_diferentes_geram_atuacoes_separadas(self):
|
||||
coords = [
|
||||
CoordenacaoCapes(
|
||||
codigo="CA", tipo="Coordenador de Área",
|
||||
area_avaliacao="ÁREA 1", periodo=criar_periodo(2, duracao_anos=2)
|
||||
),
|
||||
CoordenacaoCapes(
|
||||
codigo="CAJ", tipo="Coordenador Adjunto",
|
||||
area_avaliacao="ÁREA 1", periodo=criar_periodo(2, duracao_anos=2)
|
||||
),
|
||||
]
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a(coords)
|
||||
assert len(resultado.atuacoes) == 2
|
||||
|
||||
def test_codigo_com_hifen_normalizado(self):
|
||||
coord = CoordenacaoCapes(
|
||||
codigo="CAJ-MP",
|
||||
tipo="Coordenador Adjunto de Mestrado Profissionalizante",
|
||||
area_avaliacao="ADMINISTRAÇÃO",
|
||||
periodo=criar_periodo(anos_atras=2, duracao_anos=2),
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_a([coord])
|
||||
assert len(resultado.atuacoes) == 1
|
||||
assert resultado.atuacoes[0].codigo == "CAJ_MP"
|
||||
|
||||
|
||||
class TestBlocoBConsultoria:
|
||||
|
||||
def test_consultoria_vazia_retorna_bloco_vazio(self):
|
||||
resultado = CalculadorPontuacao.calcular_bloco_b(None)
|
||||
assert resultado.bloco == "B"
|
||||
assert resultado.total == 0
|
||||
|
||||
def test_consultor_ativo_base_150_pontos(self):
|
||||
consultoria = Consultoria(
|
||||
codigo="CONS_ATIVO",
|
||||
situacao="Atividade Contínua",
|
||||
periodo=criar_periodo(anos_atras=1, ativo=True),
|
||||
anos_consecutivos=1,
|
||||
retornos=0,
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_b(consultoria)
|
||||
assert resultado.total >= 150
|
||||
|
||||
def test_consultor_historico_base_100_pontos(self):
|
||||
consultoria = Consultoria(
|
||||
codigo="CONS_HIST",
|
||||
situacao="Inativo",
|
||||
periodo=criar_periodo(anos_atras=5, duracao_anos=3),
|
||||
anos_consecutivos=3,
|
||||
retornos=0,
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_b(consultoria)
|
||||
assert resultado.total >= 100
|
||||
|
||||
def test_consultor_falecido_base_100_pontos(self):
|
||||
consultoria = Consultoria(
|
||||
codigo="CONS_FALECIDO",
|
||||
situacao="Falecido",
|
||||
periodo=criar_periodo(anos_atras=10, duracao_anos=8),
|
||||
anos_consecutivos=8,
|
||||
retornos=0,
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_b(consultoria)
|
||||
assert resultado.total >= 100
|
||||
|
||||
def test_consultoria_5_anos_pontos_tempo(self):
|
||||
consultoria = Consultoria(
|
||||
codigo="CONS_ATIVO",
|
||||
situacao="Atividade Contínua",
|
||||
periodo=criar_periodo(anos_atras=5, ativo=True),
|
||||
periodos=[criar_periodo(anos_atras=5, ativo=True)],
|
||||
anos_consecutivos=5,
|
||||
retornos=0,
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_b(consultoria)
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.tempo == 25
|
||||
|
||||
def test_consultoria_teto_tempo_50_pontos(self):
|
||||
consultoria = Consultoria(
|
||||
codigo="CONS_ATIVO",
|
||||
situacao="Atividade Contínua",
|
||||
periodo=criar_periodo(anos_atras=15, ativo=True),
|
||||
periodos=[criar_periodo(anos_atras=15, ativo=True)],
|
||||
anos_consecutivos=15,
|
||||
retornos=0,
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_b(consultoria)
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.tempo == 50
|
||||
|
||||
def test_consultor_ativo_bonus_atualidade_20(self):
|
||||
consultoria = Consultoria(
|
||||
codigo="CONS_ATIVO",
|
||||
situacao="Atividade Contínua",
|
||||
periodo=criar_periodo(anos_atras=1, ativo=True),
|
||||
anos_consecutivos=1,
|
||||
retornos=0,
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_b(consultoria)
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.bonus >= 20
|
||||
|
||||
def test_consultor_8_anos_bonus_continuidade(self):
|
||||
consultoria = Consultoria(
|
||||
codigo="CONS_ATIVO",
|
||||
situacao="Atividade Contínua",
|
||||
periodo=criar_periodo(anos_atras=8, ativo=True),
|
||||
anos_consecutivos=8,
|
||||
retornos=0,
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_b(consultoria)
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.bonus >= 40
|
||||
|
||||
def test_consultor_com_retorno_bonus_15(self):
|
||||
consultoria = Consultoria(
|
||||
codigo="CONS_ATIVO",
|
||||
situacao="Atividade Contínua",
|
||||
periodo=criar_periodo(anos_atras=2, ativo=True),
|
||||
periodos=[
|
||||
criar_periodo(anos_atras=8, duracao_anos=3),
|
||||
criar_periodo(anos_atras=2, ativo=True),
|
||||
],
|
||||
anos_consecutivos=2,
|
||||
retornos=1,
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_b(consultoria)
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.bonus >= 35
|
||||
|
||||
def test_consultoria_teto_maximo_230(self):
|
||||
consultoria = Consultoria(
|
||||
codigo="CONS_ATIVO",
|
||||
situacao="Atividade Contínua",
|
||||
periodo=criar_periodo(anos_atras=20, ativo=True),
|
||||
periodos=[criar_periodo(anos_atras=20, ativo=True)],
|
||||
anos_consecutivos=20,
|
||||
retornos=1,
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_b(consultoria)
|
||||
atuacao = resultado.atuacoes[0]
|
||||
assert atuacao.total <= 230
|
||||
|
||||
|
||||
class TestBlocoCPremiacoesAvaliacoes:
|
||||
|
||||
def test_bloco_c_vazio(self):
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c([], [], [], [], [])
|
||||
assert resultado.bloco == "C"
|
||||
assert resultado.total == 0
|
||||
|
||||
def test_inscricao_autor_base_10_pontos(self):
|
||||
inscricao = Inscricao(
|
||||
codigo="INSC_AUTOR", tipo="Autor",
|
||||
premio="PCT", ano=2024
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c([inscricao], [], [], [], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "INSC_AUTOR"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.base >= 10
|
||||
|
||||
def test_inscricao_institucional_base_20_pontos(self):
|
||||
inscricao = Inscricao(
|
||||
codigo="INSC_INST_AUTOR", tipo="Institucional",
|
||||
premio="PCT", ano=2024
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c([inscricao], [], [], [], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "INSC_INST_AUTOR"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.base >= 20
|
||||
|
||||
def test_avaliacao_comissao_premio_base_30(self):
|
||||
avaliacao = AvaliacaoComissao(
|
||||
codigo="AVAL_COMIS_PREMIO", tipo="Membro de Comissão",
|
||||
premio="PCT", ano=2024
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c([], [avaliacao], [], [], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "AVAL_COMIS_PREMIO"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.base >= 30
|
||||
|
||||
def test_avaliacao_comissao_gp_base_40(self):
|
||||
avaliacao = AvaliacaoComissao(
|
||||
codigo="AVAL_COMIS_GP", tipo="Membro de Comissão",
|
||||
premio="Grande Prêmio", ano=2024
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c([], [avaliacao], [], [], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "AVAL_COMIS_GP"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.base >= 40
|
||||
|
||||
def test_coord_comissao_premio_base_40(self):
|
||||
avaliacao = AvaliacaoComissao(
|
||||
codigo="COORD_COMIS_PREMIO", tipo="Coordenador",
|
||||
premio="PCT", ano=2024
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c([], [avaliacao], [], [], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "COORD_COMIS_PREMIO"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.base >= 40
|
||||
|
||||
def test_coord_comissao_gp_base_50(self):
|
||||
avaliacao = AvaliacaoComissao(
|
||||
codigo="COORD_COMIS_GP", tipo="Coordenador",
|
||||
premio="Grande Prêmio", ano=2024
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c([], [avaliacao], [], [], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "COORD_COMIS_GP"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.base >= 50
|
||||
|
||||
def test_premiacao_gp_autor_base_100(self):
|
||||
premiacao = Premiacao(
|
||||
codigo="PREMIACAO_GP_AUTOR", tipo="Grande Prêmio",
|
||||
nome_premio="Grande Prêmio CAPES", ano=2024
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c([], [], [premiacao], [], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "PREMIACAO_GP_AUTOR"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.base >= 100
|
||||
|
||||
def test_premiacao_autor_base_50(self):
|
||||
premiacao = Premiacao(
|
||||
codigo="PREMIACAO_AUTOR", tipo="Prêmio",
|
||||
nome_premio="Prêmio CAPES de Tese", ano=2024
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c([], [], [premiacao], [], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "PREMIACAO_AUTOR"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.base >= 50
|
||||
|
||||
def test_mencao_autor_base_30(self):
|
||||
premiacao = Premiacao(
|
||||
codigo="MENCAO_AUTOR", tipo="Menção Honrosa",
|
||||
nome_premio="Prêmio CAPES de Tese", ano=2024
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c([], [], [premiacao], [], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "MENCAO_AUTOR"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.base >= 30
|
||||
|
||||
def test_avaliacao_recorrente_bonus_anual(self):
|
||||
avaliacoes = [
|
||||
AvaliacaoComissao(
|
||||
codigo="AVAL_COMIS_PREMIO", tipo="Membro",
|
||||
premio="PCT", ano=2022
|
||||
),
|
||||
AvaliacaoComissao(
|
||||
codigo="AVAL_COMIS_PREMIO", tipo="Membro",
|
||||
premio="PCT", ano=2023
|
||||
),
|
||||
AvaliacaoComissao(
|
||||
codigo="AVAL_COMIS_PREMIO", tipo="Membro",
|
||||
premio="PCT", ano=2024
|
||||
),
|
||||
]
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c([], avaliacoes, [], [], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "AVAL_COMIS_PREMIO"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.bonus > 0
|
||||
assert atuacao.quantidade == 3
|
||||
|
||||
def test_inscricoes_multiplas_acumulam(self):
|
||||
inscricoes = [
|
||||
Inscricao(codigo="INSC_AUTOR", tipo="Autor", premio="PCT", ano=2022),
|
||||
Inscricao(codigo="INSC_AUTOR", tipo="Autor", premio="PCT", ano=2023),
|
||||
]
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c(inscricoes, [], [], [], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "INSC_AUTOR"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.quantidade == 2
|
||||
assert atuacao.base == 20
|
||||
|
||||
def test_teto_inscricao_autor_20_pontos(self):
|
||||
inscricoes = [
|
||||
Inscricao(codigo="INSC_AUTOR", tipo="Autor", premio="PCT", ano=i)
|
||||
for i in range(2015, 2025)
|
||||
]
|
||||
resultado = CalculadorPontuacao.calcular_bloco_c(inscricoes, [], [], [], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "INSC_AUTOR"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.total <= 20
|
||||
|
||||
|
||||
class TestBlocoDParticipacoes:
|
||||
|
||||
def test_bloco_d_vazio(self):
|
||||
resultado = CalculadorPontuacao.calcular_bloco_d([], [])
|
||||
assert resultado.bloco == "D"
|
||||
assert resultado.total == 0
|
||||
|
||||
def test_bolsa_cnpq_base_30(self):
|
||||
bolsa = BolsaCNPQ(codigo="BOL_BPQ_NIVEL", nivel="1A")
|
||||
resultado = CalculadorPontuacao.calcular_bloco_d([bolsa], [])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "BOL_BPQ_NIVEL"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.base >= 30
|
||||
|
||||
def test_evento_base_1_ponto(self):
|
||||
evento = Participacao(codigo="EVENTO", tipo="Evento", ano=2024)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_d([], [evento])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "EVENTO"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.base >= 1
|
||||
|
||||
def test_projeto_base_10_pontos(self):
|
||||
projeto = Participacao(codigo="PROJ", tipo="Projeto", ano=2024)
|
||||
resultado = CalculadorPontuacao.calcular_bloco_d([], [projeto])
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "PROJ"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.base >= 10
|
||||
|
||||
def test_eventos_multiplos_bonus_recorrencia(self):
|
||||
eventos = [
|
||||
Participacao(codigo="EVENTO", tipo="Evento", ano=i)
|
||||
for i in range(2020, 2025)
|
||||
]
|
||||
resultado = CalculadorPontuacao.calcular_bloco_d([], eventos)
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "EVENTO"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.quantidade == 5
|
||||
assert atuacao.bonus > 0
|
||||
|
||||
def test_evento_teto_5_pontos(self):
|
||||
eventos = [
|
||||
Participacao(codigo="EVENTO", tipo="Evento", ano=i)
|
||||
for i in range(2000, 2025)
|
||||
]
|
||||
resultado = CalculadorPontuacao.calcular_bloco_d([], eventos)
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "EVENTO"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.total <= 5
|
||||
|
||||
def test_projeto_teto_30_pontos(self):
|
||||
projetos = [
|
||||
Participacao(codigo="PROJ", tipo="Projeto", ano=i)
|
||||
for i in range(2000, 2025)
|
||||
]
|
||||
resultado = CalculadorPontuacao.calcular_bloco_d([], projetos)
|
||||
atuacao = next((a for a in resultado.atuacoes if a.codigo == "PROJ"), None)
|
||||
assert atuacao is not None
|
||||
assert atuacao.total <= 30
|
||||
|
||||
|
||||
class TestBlocoECoordPPG:
|
||||
|
||||
def test_bloco_e_sem_coordenador(self):
|
||||
resultado = CalculadorPontuacao.calcular_bloco_e(False)
|
||||
assert resultado.bloco == "E"
|
||||
assert resultado.total == 0
|
||||
|
||||
def test_bloco_e_com_coordenador(self):
|
||||
resultado = CalculadorPontuacao.calcular_bloco_e(True)
|
||||
assert resultado.bloco == "E"
|
||||
assert len(resultado.atuacoes) == 1
|
||||
assert resultado.atuacoes[0].codigo == "PPG_COORD"
|
||||
|
||||
|
||||
class TestPontuacaoCompleta:
|
||||
|
||||
def test_consultor_vazio_pontuacao_zero(self, consultor_vazio):
|
||||
resultado = CalculadorPontuacao.calcular_pontuacao_completa(consultor_vazio)
|
||||
assert resultado.total == 0
|
||||
|
||||
def test_consultor_com_coordenacao(self, coordenacao_ca_ativa):
|
||||
consultor = Consultor(
|
||||
id_pessoa=1,
|
||||
nome="Coordenador",
|
||||
coordenacoes_capes=[coordenacao_ca_ativa],
|
||||
)
|
||||
resultado = CalculadorPontuacao.calcular_pontuacao_completa(consultor)
|
||||
assert resultado.bloco_a.total > 0
|
||||
assert resultado.bloco_b.total == 0
|
||||
|
||||
def test_consultor_completo_todos_blocos(self, consultor_completo):
|
||||
resultado = CalculadorPontuacao.calcular_pontuacao_completa(consultor_completo)
|
||||
assert resultado.bloco_a.total > 0
|
||||
assert resultado.bloco_b.total > 0
|
||||
assert resultado.bloco_c.total > 0
|
||||
assert resultado.bloco_d.total > 0
|
||||
|
||||
def test_pontuacao_total_soma_blocos(self, consultor_completo):
|
||||
resultado = CalculadorPontuacao.calcular_pontuacao_completa(consultor_completo)
|
||||
soma_esperada = (
|
||||
resultado.bloco_a.total
|
||||
+ resultado.bloco_b.total
|
||||
+ resultado.bloco_c.total
|
||||
+ resultado.bloco_d.total
|
||||
+ resultado.bloco_e.total
|
||||
)
|
||||
assert resultado.total == soma_esperada
|
||||
|
||||
def test_detalhamento_retorna_dict(self, consultor_completo):
|
||||
resultado = CalculadorPontuacao.calcular_pontuacao_completa(consultor_completo)
|
||||
detalhes = resultado.detalhamento
|
||||
assert isinstance(detalhes, dict)
|
||||
assert "bloco_a" in detalhes
|
||||
assert "bloco_b" in detalhes
|
||||
assert "bloco_c" in detalhes
|
||||
assert "bloco_d" in detalhes
|
||||
assert "bloco_e" in detalhes
|
||||
assert "pontuacao_total" in detalhes
|
||||
|
||||
|
||||
class TestCriteriosConfigurados:
|
||||
|
||||
def test_criterio_ca_existe(self):
|
||||
assert "CA" in CRITERIOS
|
||||
criterio = CRITERIOS["CA"]
|
||||
assert criterio.base == 200
|
||||
assert criterio.teto == 450
|
||||
|
||||
def test_criterio_caj_existe(self):
|
||||
assert "CAJ" in CRITERIOS
|
||||
criterio = CRITERIOS["CAJ"]
|
||||
assert criterio.base == 150
|
||||
assert criterio.teto == 370
|
||||
|
||||
def test_criterio_cons_ativo_existe(self):
|
||||
assert "CONS_ATIVO" in CRITERIOS
|
||||
criterio = CRITERIOS["CONS_ATIVO"]
|
||||
assert criterio.base == 150
|
||||
assert criterio.teto == 230
|
||||
|
||||
def test_todos_criterios_tem_codigo_valido(self):
|
||||
for codigo, criterio in CRITERIOS.items():
|
||||
assert criterio.codigo == codigo
|
||||
assert criterio.base >= 0
|
||||
assert criterio.teto >= 0
|
||||
0
backend/tests/domain/value_objects/__init__.py
Normal file
0
backend/tests/domain/value_objects/__init__.py
Normal file
169
backend/tests/domain/value_objects/test_periodo.py
Normal file
169
backend/tests/domain/value_objects/test_periodo.py
Normal file
@@ -0,0 +1,169 @@
|
||||
import pytest
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from src.domain.value_objects.periodo import (
|
||||
Periodo,
|
||||
mesclar_periodos,
|
||||
anos_completos_periodos,
|
||||
)
|
||||
|
||||
|
||||
class TestPeriodo:
|
||||
|
||||
def test_periodo_ativo_sem_fim(self):
|
||||
inicio = datetime(2020, 1, 1)
|
||||
periodo = Periodo(inicio=inicio, fim=None)
|
||||
assert periodo.ativo is True
|
||||
|
||||
def test_periodo_inativo_com_fim(self):
|
||||
inicio = datetime(2020, 1, 1)
|
||||
fim = datetime(2023, 1, 1)
|
||||
periodo = Periodo(inicio=inicio, fim=fim)
|
||||
assert periodo.ativo is False
|
||||
|
||||
def test_anos_decorridos_3_anos(self):
|
||||
inicio = datetime.now() - relativedelta(years=3)
|
||||
fim = datetime.now()
|
||||
periodo = Periodo(inicio=inicio, fim=fim)
|
||||
assert periodo.anos_decorridos >= 2.9
|
||||
assert periodo.anos_decorridos <= 3.1
|
||||
|
||||
def test_anos_decorridos_periodo_ativo(self):
|
||||
inicio = datetime.now() - relativedelta(years=5)
|
||||
periodo = Periodo(inicio=inicio, fim=None)
|
||||
assert periodo.anos_decorridos >= 4.9
|
||||
assert periodo.anos_decorridos <= 5.1
|
||||
|
||||
def test_anos_completos_retorna_inteiro(self):
|
||||
inicio = datetime(2020, 1, 1)
|
||||
fim = datetime(2023, 6, 15)
|
||||
periodo = Periodo(inicio=inicio, fim=fim)
|
||||
assert periodo.anos_completos() == 3
|
||||
|
||||
def test_anos_completos_menos_de_um_ano(self):
|
||||
inicio = datetime.now() - relativedelta(months=6)
|
||||
fim = datetime.now()
|
||||
periodo = Periodo(inicio=inicio, fim=fim)
|
||||
assert periodo.anos_completos() == 0
|
||||
|
||||
def test_anos_completos_com_data_referencia(self):
|
||||
inicio = datetime(2020, 1, 1)
|
||||
periodo = Periodo(inicio=inicio, fim=None)
|
||||
data_ref = datetime(2025, 1, 1)
|
||||
assert periodo.anos_completos(data_ref) == 5
|
||||
|
||||
def test_fim_anterior_inicio_corrige_para_none(self):
|
||||
inicio = datetime(2023, 1, 1)
|
||||
fim = datetime(2020, 1, 1)
|
||||
periodo = Periodo(inicio=inicio, fim=fim)
|
||||
assert periodo.fim is None
|
||||
assert periodo.ativo is True
|
||||
|
||||
|
||||
class TestMesclarPeriodos:
|
||||
|
||||
def test_lista_vazia_retorna_vazia(self):
|
||||
resultado = mesclar_periodos([])
|
||||
assert resultado == []
|
||||
|
||||
def test_um_periodo_retorna_mesmo(self):
|
||||
periodo = Periodo(datetime(2020, 1, 1), datetime(2023, 1, 1))
|
||||
resultado = mesclar_periodos([periodo])
|
||||
assert len(resultado) == 1
|
||||
assert resultado[0].inicio == periodo.inicio
|
||||
|
||||
def test_periodos_consecutivos_mesclados(self):
|
||||
p1 = Periodo(datetime(2020, 1, 1), datetime(2022, 1, 1))
|
||||
p2 = Periodo(datetime(2021, 6, 1), datetime(2024, 1, 1))
|
||||
resultado = mesclar_periodos([p1, p2])
|
||||
assert len(resultado) == 1
|
||||
assert resultado[0].inicio == datetime(2020, 1, 1)
|
||||
assert resultado[0].fim == datetime(2024, 1, 1)
|
||||
|
||||
def test_periodos_separados_nao_mesclados(self):
|
||||
p1 = Periodo(datetime(2015, 1, 1), datetime(2017, 1, 1))
|
||||
p2 = Periodo(datetime(2020, 1, 1), datetime(2023, 1, 1))
|
||||
resultado = mesclar_periodos([p1, p2])
|
||||
assert len(resultado) == 2
|
||||
|
||||
def test_periodo_ativo_preservado(self):
|
||||
p1 = Periodo(datetime(2020, 1, 1), datetime(2022, 1, 1))
|
||||
p2 = Periodo(datetime(2021, 1, 1), None)
|
||||
resultado = mesclar_periodos([p1, p2])
|
||||
assert len(resultado) == 1
|
||||
assert resultado[0].ativo is True
|
||||
|
||||
def test_tres_periodos_mesclados(self):
|
||||
p1 = Periodo(datetime(2018, 1, 1), datetime(2020, 1, 1))
|
||||
p2 = Periodo(datetime(2019, 1, 1), datetime(2021, 1, 1))
|
||||
p3 = Periodo(datetime(2020, 6, 1), datetime(2023, 1, 1))
|
||||
resultado = mesclar_periodos([p1, p2, p3])
|
||||
assert len(resultado) == 1
|
||||
assert resultado[0].inicio == datetime(2018, 1, 1)
|
||||
assert resultado[0].fim == datetime(2023, 1, 1)
|
||||
|
||||
def test_ordenacao_automatica(self):
|
||||
p1 = Periodo(datetime(2022, 1, 1), datetime(2024, 1, 1))
|
||||
p2 = Periodo(datetime(2018, 1, 1), datetime(2020, 1, 1))
|
||||
resultado = mesclar_periodos([p1, p2])
|
||||
assert resultado[0].inicio == datetime(2018, 1, 1)
|
||||
|
||||
|
||||
class TestAnosCompletosPeriodos:
|
||||
|
||||
def test_lista_vazia_retorna_zero(self):
|
||||
resultado = anos_completos_periodos([])
|
||||
assert resultado == 0
|
||||
|
||||
def test_um_periodo_3_anos(self):
|
||||
periodo = Periodo(datetime(2020, 1, 1), datetime(2023, 1, 1))
|
||||
resultado = anos_completos_periodos([periodo])
|
||||
assert resultado == 3
|
||||
|
||||
def test_dois_periodos_soma(self):
|
||||
p1 = Periodo(datetime(2015, 1, 1), datetime(2017, 1, 1))
|
||||
p2 = Periodo(datetime(2020, 1, 1), datetime(2023, 1, 1))
|
||||
resultado = anos_completos_periodos([p1, p2])
|
||||
assert resultado == 5
|
||||
|
||||
def test_com_data_referencia(self):
|
||||
p1 = Periodo(datetime(2020, 1, 1), None)
|
||||
p2 = Periodo(datetime(2015, 1, 1), datetime(2017, 1, 1))
|
||||
data_ref = datetime(2025, 1, 1)
|
||||
resultado = anos_completos_periodos([p1, p2], data_ref)
|
||||
assert resultado == 7
|
||||
|
||||
|
||||
class TestCasosEspeciais:
|
||||
|
||||
def test_periodo_muito_curto(self):
|
||||
inicio = datetime.now() - relativedelta(days=30)
|
||||
fim = datetime.now()
|
||||
periodo = Periodo(inicio=inicio, fim=fim)
|
||||
assert periodo.anos_completos() == 0
|
||||
|
||||
def test_periodo_exatamente_um_ano(self):
|
||||
inicio = datetime(2023, 1, 1)
|
||||
fim = datetime(2024, 1, 1)
|
||||
periodo = Periodo(inicio=inicio, fim=fim)
|
||||
assert periodo.anos_completos() == 1
|
||||
|
||||
def test_periodo_quase_um_ano(self):
|
||||
inicio = datetime(2023, 1, 1)
|
||||
fim = datetime(2023, 12, 31)
|
||||
periodo = Periodo(inicio=inicio, fim=fim)
|
||||
assert periodo.anos_completos() == 0
|
||||
|
||||
def test_mesclagem_periodos_sobrepostos_complexos(self):
|
||||
periodos = [
|
||||
Periodo(datetime(2010, 1, 1), datetime(2012, 1, 1)),
|
||||
Periodo(datetime(2011, 6, 1), datetime(2014, 1, 1)),
|
||||
Periodo(datetime(2013, 1, 1), datetime(2015, 1, 1)),
|
||||
Periodo(datetime(2018, 1, 1), datetime(2020, 1, 1)),
|
||||
Periodo(datetime(2019, 6, 1), None),
|
||||
]
|
||||
resultado = mesclar_periodos(periodos)
|
||||
assert len(resultado) == 2
|
||||
assert resultado[0].fim == datetime(2015, 1, 1)
|
||||
assert resultado[1].ativo is True
|
||||
Reference in New Issue
Block a user