From b77a46c02c161816fa8d7cf16ef09ebd6e39f921 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Thu, 8 Aug 2024 16:28:05 -0300 Subject: [PATCH 01/27] Make clearer reference to PE in docstring arguments --- tests/plano_trabalho/core_test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/plano_trabalho/core_test.py b/tests/plano_trabalho/core_test.py index a96dc59..b34e841 100644 --- a/tests/plano_trabalho/core_test.py +++ b/tests/plano_trabalho/core_test.py @@ -82,8 +82,10 @@ def setup( """Configurar o ambiente de teste. Args: - truncate_pe (callable): Fixture para truncar a tabela PE. - truncate_pt (callable): Fixture para truncar a tabela PT. + truncate_pe (callable): Fixture para truncar a tabela de + Planos de Entrega. + truncate_pt (callable): Fixture para truncar a tabela de + Planos de Trabalho. example_pe (callable): Fixture que cria exemplo de PE. input_pt (dict): Dados usados para ciar um PT user1_credentials (dict): Credenciais do usuário 1. From 46a19964b740043b4924806ae6e04a085df462d1 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Thu, 8 Aug 2024 16:28:57 -0300 Subject: [PATCH 02/27] Add response class to return type hinting --- tests/plano_trabalho/core_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/plano_trabalho/core_test.py b/tests/plano_trabalho/core_test.py index b34e841..45979f4 100644 --- a/tests/plano_trabalho/core_test.py +++ b/tests/plano_trabalho/core_test.py @@ -5,7 +5,7 @@ from typing import Optional -from httpx import Client +from httpx import Client, Response from fastapi import status import pytest @@ -157,7 +157,7 @@ def create_pt( origem_unidade: Optional[str] = None, cod_unidade_autorizadora: Optional[int] = None, header_usr: Optional[dict] = None, - ): + ) -> Response: """Criar um Plano de Trabalho. Args: @@ -196,7 +196,7 @@ def get_pt( cod_unidade_autorizadora: int, origem_unidade: Optional[str] = "SIAPE", header_usr: Optional[dict] = None, - ): + ) -> Response: """Obter um Plano de Trabalho. Args: From 12ba79706ed3fbaee501bc5e92988f32f9979bcd Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Thu, 8 Aug 2024 17:00:31 -0300 Subject: [PATCH 03/27] Create base test class for Plano de Entrega --- tests/plano_entregas/core_test.py | 193 ++++++++++++++----- tests/plano_entregas/date_validation_test.py | 8 +- tests/plano_entregas/permissions_test.py | 4 +- 3 files changed, 152 insertions(+), 53 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 17d73f1..543cd01 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -2,7 +2,9 @@ Testes relacionados ao Plano de Entregas da Unidade """ -from httpx import Client +from typing import Optional + +from httpx import Client, Response from fastapi import status as http_status import pytest @@ -47,35 +49,135 @@ } -# Helper functions +# Classe base de testes -def assert_equal_plano_entregas(plano_entregas_1: dict, plano_entregas_2: dict): - """Verifica a igualdade de dois planos de entregas, considerando - apenas os campos obrigatórios. - """ - # Compara o conteúdo de todos os campos obrigatórios do plano de - # entregas, exceto a lista de entregas - assert all( - plano_entregas_1[attribute] == plano_entregas_2[attribute] - for attributes in FIELDS_PLANO_ENTREGAS["mandatory"] - for attribute in attributes - if attribute not in ("entregas") - ) +class BasePETest: + """Classe base para testes de Plano de Entregas.""" - # Compara o conteúdo de cada entrega, somente campos obrigatórios - first_plan_by_entrega = { - entrega["id_entrega"]: entrega for entrega in plano_entregas_1["entregas"] - } - second_plan_by_entrega = { - entrega["id_entrega"]: entrega for entrega in plano_entregas_2["entregas"] - } - assert all( - first_plan_by_entrega[id_entrega][attribute] == entrega[attribute] - for attributes in FIELDS_ENTREGA["mandatory"] - for attribute in attributes - for id_entrega, entrega in second_plan_by_entrega.items() - ) + # pylint: disable=too-many-arguments + @pytest.fixture(autouse=True) + def setup( + self, + truncate_pe, # pylint: disable=unused-argument + input_pe: dict, + user1_credentials: dict, + header_usr_1: dict, + client: Client, + ): + """Configurar o ambiente de teste. + + Args: + truncate_pe (callable): Fixture para truncar a tabela de + Planos de Entrega (PE). + input_pe (dict): Dados usados para criar um PE. + user1_credentials (dict): Credenciais do usuário 1. + header_usr_1 (dict): Cabeçalhos HTTP para o usuário 1. + client (Client): Uma instância do cliente HTTPX. + """ + # pylint: disable=attribute-defined-outside-init + self.input_pe = input_pe + self.user1_credentials = user1_credentials + self.header_usr_1 = header_usr_1 + self.client = client + + @staticmethod + def assert_equal_plano_entregas(plano_entregas_1: dict, plano_entregas_2: dict): + """Verifica a igualdade de dois planos de entregas, considerando + apenas os campos obrigatórios. + """ + # Compara o conteúdo de todos os campos obrigatórios do plano de + # entregas, exceto a lista de entregas + assert all( + plano_entregas_1[attribute] == plano_entregas_2[attribute] + for attributes in FIELDS_PLANO_ENTREGAS["mandatory"] + for attribute in attributes + if attribute not in ("entregas") + ) + + # Compara o conteúdo de cada entrega, somente campos obrigatórios + first_plan_by_entrega = { + entrega["id_entrega"]: entrega for entrega in plano_entregas_1["entregas"] + } + second_plan_by_entrega = { + entrega["id_entrega"]: entrega for entrega in plano_entregas_2["entregas"] + } + assert all( + first_plan_by_entrega[id_entrega][attribute] == entrega[attribute] + for attributes in FIELDS_ENTREGA["mandatory"] + for attribute in attributes + for id_entrega, entrega in second_plan_by_entrega.items() + ) + + def create_plano_entregas( + self, + input_pe: dict, + id_plano_entregas: Optional[str] = None, + origem_unidade: Optional[str] = None, + cod_unidade_autorizadora: Optional[int] = None, + header_usr: Optional[dict] = None, + ) -> Response: + """Criar um Plano de Entregas. + + Args: + input_pe (dict): O dicionário de entrada do Plano de Entregas. + id_plano_entregas (str): O ID do Plano de Entregas. + origem_unidade (str): origem do código da unidade. + cod_unidade_autorizadora (int): O ID da unidade autorizadora. + header_usr (dict): Cabeçalhos HTTP para o usuário. + + Returns: + httpx.Response: A resposta da API. + """ + if id_plano_entregas is None: + id_plano_entregas = input_pe["id_plano_entregas"] + if origem_unidade is None: + origem_unidade = input_pe["origem_unidade"] + if cod_unidade_autorizadora is None: + cod_unidade_autorizadora = self.user1_credentials[ + "cod_unidade_autorizadora" + ] + if header_usr is None: + header_usr = self.header_usr_1 + + response = self.client.put( + ( + f"/organizacao/{origem_unidade}/{cod_unidade_autorizadora}" + f"/plano_entregas/{id_plano_entregas}" + ), + json=input_pe, + headers=header_usr, + ) + return response + + def get_pe( + self, + id_plano_entregas: str, + cod_unidade_autorizadora: int, + origem_unidade: Optional[str] = "SIAPE", + header_usr: Optional[dict] = None, + ) -> Response: + """Obter um Plano de Entregas. + + Args: + id_plano_entregas (str): O ID do Plano de Entregas. + cod_unidade_autorizadora (int): O ID da unidade autorizadora. + origem_unidade (str): origem do código da unidade. + header_usr (dict): Cabeçalhos HTTP para o usuário. + + Returns: + httpx.Response: A resposta da API. + """ + if header_usr is None: + header_usr = self.header_usr_1 + response = self.client.get( + ( + f"/organizacao/{origem_unidade}/{cod_unidade_autorizadora}" + f"/plano_entregas/{id_plano_entregas}" + ), + headers=header_usr, + ) + return response # Os testes usam muitas fixtures, então necessariamente precisam de @@ -103,7 +205,7 @@ def test_create_plano_entregas_completo( assert response.status_code == http_status.HTTP_201_CREATED assert response.json().get("detail", None) is None - assert_equal_plano_entregas(response.json(), input_pe) + BasePETest.assert_equal_plano_entregas(response.json(), input_pe) def test_update_plano_entregas( @@ -169,7 +271,7 @@ def test_create_plano_entregas_entrega_omit_optional_fields( headers=header_usr_1, ) assert response.status_code == http_status.HTTP_201_CREATED - assert_equal_plano_entregas(response.json(), input_pe) + BasePETest.assert_equal_plano_entregas(response.json(), input_pe) @pytest.mark.parametrize("nulled_fields", enumerate(FIELDS_ENTREGA["optional"])) @@ -197,7 +299,7 @@ def test_create_plano_entregas_entrega_null_optional_fields( headers=header_usr_1, ) assert response.status_code == http_status.HTTP_201_CREATED - assert_equal_plano_entregas(response.json(), input_pe) + BasePETest.assert_equal_plano_entregas(response.json(), input_pe) @pytest.mark.parametrize( @@ -265,13 +367,15 @@ def create_huge_entrega(id_entrega: int): # Compara o conteúdo do plano de entregas, somente campos obrigatórios assert response.status_code == http_status.HTTP_201_CREATED - assert_equal_plano_entregas(response.json(), input_pe) + BasePETest.assert_equal_plano_entregas(response.json(), input_pe) # Compara o conteúdo de cada entrega, somente campos obrigatórios response_by_entrega = { entrega["id_entrega"]: entrega for entrega in response.json()["entregas"] } - input_by_entrega = {entrega["id_entrega"]: entrega for entrega in input_pe["entregas"]} + input_by_entrega = { + entrega["id_entrega"]: entrega for entrega in input_pe["entregas"] + } assert all( response_by_entrega[id_entrega][attribute] == entrega[attribute] for attributes in FIELDS_ENTREGA["mandatory"] @@ -387,7 +491,7 @@ def test_get_plano_entregas( headers=header_usr_1, ) assert response.status_code == http_status.HTTP_200_OK - assert_equal_plano_entregas(response.json(), input_pe) + BasePETest.assert_equal_plano_entregas(response.json(), input_pe) def test_get_pe_inexistente( @@ -409,10 +513,10 @@ def test_get_pe_inexistente( "id_plano_entregas, status, avaliacao, data_avaliacao", [ ("78", 5, 2, "2023-06-11"), - ("79", 5, 2, None), # falta data_avaliacao - ("80", 5, None, "2023-06-11"), # falta avaliacao - ("81", 5, None, None), # faltam ambos - ("81", 2, None, None), # status não é 5 + ("79", 5, 2, None), # falta data_avaliacao + ("80", 5, None, "2023-06-11"), # falta avaliacao + ("81", 5, None, None), # faltam ambos + ("81", 2, None, None), # status não é 5 ], ) def test_create_pe_status_avaliado( @@ -527,7 +631,7 @@ def test_create_pe_duplicate_id_plano( assert response.status_code == http_status.HTTP_200_OK assert response.json().get("detail", None) is None - assert_equal_plano_entregas(response.json(), input_pe) + BasePETest.assert_equal_plano_entregas(response.json(), input_pe) def test_create_pe_same_id_plano_different_instituidora( @@ -589,8 +693,7 @@ def test_create_invalid_cod_unidade( assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY detail_message = "Input should be greater than 0" assert any( - detail_message in error["msg"] - for error in response.json().get("detail") + detail_message in error["msg"] for error in response.json().get("detail") ) @@ -639,12 +742,9 @@ def test_create_entrega_invalid_percent( ) elif tipo_meta == "unidade" and (meta_entrega < 0): assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - detail_message = ( - "Input should be greater than or equal to 0" - ) + detail_message = "Input should be greater than or equal to 0" assert any( - detail_message in error["msg"] - for error in response.json().get("detail") + detail_message in error["msg"] for error in response.json().get("detail") ) else: assert response.status_code == http_status.HTTP_201_CREATED @@ -675,8 +775,7 @@ def test_create_entrega_invalid_tipo_meta( assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY detail_message = "Input should be 'unidade' or 'percentual'" assert any( - detail_message in error["msg"] - for error in response.json().get("detail") + detail_message in error["msg"] for error in response.json().get("detail") ) diff --git a/tests/plano_entregas/date_validation_test.py b/tests/plano_entregas/date_validation_test.py index 8000b0f..ce990c5 100644 --- a/tests/plano_entregas/date_validation_test.py +++ b/tests/plano_entregas/date_validation_test.py @@ -10,7 +10,7 @@ import pytest from util import over_a_year -from .core_test import assert_equal_plano_entregas +from .core_test import BasePETest # Datas básicas @@ -59,7 +59,7 @@ def test_create_plano_entregas_date_interval_over_a_year( ) else: assert response.status_code == http_status.HTTP_201_CREATED - assert_equal_plano_entregas(response.json(), input_pe) + BasePETest.assert_equal_plano_entregas(response.json(), input_pe) @pytest.mark.parametrize( @@ -257,7 +257,7 @@ def test_create_plano_entregas_overlapping_date_interval( ): # um dos planos está cancelado, pode ser criado assert response.status_code == http_status.HTTP_201_CREATED - assert_equal_plano_entregas(response.json(), input_pe) + BasePETest.assert_equal_plano_entregas(response.json(), input_pe) else: if any( ( @@ -279,4 +279,4 @@ def test_create_plano_entregas_overlapping_date_interval( else: # não há sobreposição de datas assert response.status_code == http_status.HTTP_201_CREATED - assert_equal_plano_entregas(response.json(), input_pe) + BasePETest.assert_equal_plano_entregas(response.json(), input_pe) diff --git a/tests/plano_entregas/permissions_test.py b/tests/plano_entregas/permissions_test.py index d24a2fd..8e4dd3a 100644 --- a/tests/plano_entregas/permissions_test.py +++ b/tests/plano_entregas/permissions_test.py @@ -5,7 +5,7 @@ from httpx import Client from fastapi import status as http_status -from .core_test import assert_equal_plano_entregas +from .core_test import BasePETest def test_get_plano_entregas_different_unit( @@ -61,4 +61,4 @@ def test_get_plano_entregas_different_unit_admin( assert response.status_code == http_status.HTTP_201_CREATED assert response.json().get("detail", None) is None - assert_equal_plano_entregas(response.json(), input_pe) + BasePETest.assert_equal_plano_entregas(response.json(), input_pe) From e6070366f775967902ee6b7421b270294a6f7ed1 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Thu, 8 Aug 2024 17:50:51 -0300 Subject: [PATCH 04/27] Refactor some test functions into methods of class TestCreatePlanoEntrega --- tests/plano_entregas/core_test.py | 296 +++++++++++------------------- 1 file changed, 111 insertions(+), 185 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 543cd01..6a1eb0a 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -188,200 +188,126 @@ def get_pe( # pylint: disable=too-many-arguments -def test_create_plano_entregas_completo( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um novo plano de entregas""" - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) - - assert response.status_code == http_status.HTTP_201_CREATED - assert response.json().get("detail", None) is None - BasePETest.assert_equal_plano_entregas(response.json(), input_pe) +class TestCreatePlanoEntrega(BasePETest): + """Testes para a criação de um novo Plano de Entregas.""" + def test_create_plano_entregas_completo(self): + """Tenta criar um novo Plano de Entregas.""" + response = self.create_plano_entregas(self.input_pe) + assert response.status_code == http_status.HTTP_201_CREATED + assert response.json().get("detail", None) is None + self.assert_equal_plano_entregas(response.json(), self.input_pe) -def test_update_plano_entregas( - truncate_pe, # pylint: disable=unused-argument - example_pe, # pylint: disable=unused-argument - input_pe: dict, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um novo plano de entregas e atualizar alguns campos. - A fixture example_pe cria um novo Plano de Entregas na API. - O teste altera um campo do PE e reenvia pra API (update). - """ - - input_pe["avaliacao"] = 3 - input_pe["data_avaliacao"] = "2023-08-15" - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) - - assert response.status_code == http_status.HTTP_200_OK - assert response.json()["avaliacao"] == 3 - assert response.json()["data_avaliacao"] == "2023-08-15" - - # Consulta API para conferir se a alteração foi persistida - response = client.get( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - headers=header_usr_1, - ) - - assert response.status_code == http_status.HTTP_200_OK - assert response.json()["avaliacao"] == 3 - assert response.json()["data_avaliacao"] == "2023-08-15" - - -@pytest.mark.parametrize("omitted_fields", enumerate(FIELDS_ENTREGA["optional"])) -def test_create_plano_entregas_entrega_omit_optional_fields( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - omitted_fields: list, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um novo plano de entregas omitindo campos opcionais""" - - offset, field_list = omitted_fields - for field in field_list: - for entrega in input_pe["entregas"]: - if field in entrega: - del entrega[field] - - input_pe["id_plano_entregas"] = str(557 + offset) - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) - assert response.status_code == http_status.HTTP_201_CREATED - BasePETest.assert_equal_plano_entregas(response.json(), input_pe) - - -@pytest.mark.parametrize("nulled_fields", enumerate(FIELDS_ENTREGA["optional"])) -def test_create_plano_entregas_entrega_null_optional_fields( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - nulled_fields: list, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um novo plano de entregas com o valor null nos campos opcionais""" - - offset, field_list = nulled_fields - for field in field_list: - for entrega in input_pe["entregas"]: - if field in entrega: - entrega[field] = None - - input_pe["id_plano_entregas"] = str(557 + offset) - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) - assert response.status_code == http_status.HTTP_201_CREATED - BasePETest.assert_equal_plano_entregas(response.json(), input_pe) - + def test_update_plano_entregas(self, example_pe): + """Tenta criar um novo Plano de Entregas e atualizar alguns campos. + A fixture example_pe cria um novo Plano de Entregas na API. + O teste altera um campo do PE e reenvia pra API (update). + """ + self.input_pe["avaliacao"] = 3 + self.input_pe["data_avaliacao"] = "2023-08-15" + response = self.create_plano_entregas(self.input_pe) + assert response.status_code == http_status.HTTP_200_OK + assert response.json()["avaliacao"] == 3 + assert response.json()["data_avaliacao"] == "2023-08-15" + + # Consulta API para conferir se a alteração foi persistida + response = self.get_pe( + self.input_pe["id_plano_entregas"], + self.user1_credentials["cod_unidade_autorizadora"], + ) + assert response.status_code == http_status.HTTP_200_OK + assert response.json()["avaliacao"] == 3 + assert response.json()["data_avaliacao"] == "2023-08-15" + + @pytest.mark.parametrize("omitted_fields", enumerate(FIELDS_ENTREGA["optional"])) + def test_create_plano_entregas_entrega_omit_optional_fields(self, omitted_fields): + """Tenta criar um novo Plano de Entregas omitindo campos opcionais.""" + offset, field_list = omitted_fields + for field in field_list: + for entrega in self.input_pe["entregas"]: + if field in entrega: + del entrega[field] + + self.input_pe["id_plano_entregas"] = str(557 + offset) + response = self.create_plano_entregas(self.input_pe) + assert response.status_code == http_status.HTTP_201_CREATED + self.assert_equal_plano_entregas(response.json(), self.input_pe) + + @pytest.mark.parametrize("nulled_fields", enumerate(FIELDS_ENTREGA["optional"])) + def test_create_plano_entregas_entrega_null_optional_fields(self, nulled_fields): + """Tenta criar um novo Plano de Entregas com o valor null nos campos opcionais.""" + offset, field_list = nulled_fields + for field in field_list: + for entrega in self.input_pe["entregas"]: + if field in entrega: + entrega[field] = None + + self.input_pe["id_plano_entregas"] = str(557 + offset) + response = self.create_plano_entregas(self.input_pe) + assert response.status_code == http_status.HTTP_201_CREATED + self.assert_equal_plano_entregas(response.json(), self.input_pe) -@pytest.mark.parametrize( - "missing_fields", enumerate(FIELDS_PLANO_ENTREGAS["mandatory"]) -) -def test_create_plano_entregas_missing_mandatory_fields( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - missing_fields: list, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um plano de entregas, faltando campos obrigatórios. - Na atualização com PUT, ainda assim é necessário informar todos os - campos obrigatórios, uma vez que o conteúdo será substituído. - """ - offset, field_list = missing_fields - for field in field_list: - del input_pe[field] - - # para usar na URL, necessário existir caso tenha sido removido - # como campo obrigatório - id_plano_entregas = 1800 + offset - if input_pe.get("id_plano_entregas", None): - # Atualiza o id_plano_entrega somente se existir. - # Se não existir, é porque foi removido como campo obrigatório. - input_pe["id_plano_entregas"] = id_plano_entregas - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{id_plano_entregas}", - json=input_pe, - headers=header_usr_1, + @pytest.mark.parametrize( + "missing_fields", enumerate(FIELDS_PLANO_ENTREGAS["mandatory"]) ) - assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - - -def test_create_huge_plano_entregas( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Testa a criação de um plano de entregas com grande volume de dados.""" + def test_create_plano_entregas_missing_mandatory_fields(self, missing_fields): + """Tenta criar um Plano de Entregas, faltando campos obrigatórios. + Na atualização com PUT, ainda assim é necessário informar todos os + campos obrigatórios, uma vez que o conteúdo será substituído. + """ + offset, field_list = missing_fields + input_pe = self.input_pe.copy() + # define um id_plano_entregas diferente para cada teste + input_pe["id_plano_entregas"] = 1800 + offset + # Estes campos fazem parte da URL e para omiti-los será necessário + # inclui-los na chamada do método create_pe + fields_in_url = [ + "origem_unidade", + "cod_unidade_autorizadora", + "id_plano_entregas", + ] + placeholder_fields = {} + for field in field_list: + if field in fields_in_url: + placeholder_fields[field] = input_pe[field] + del input_pe[field] + + # Act + response = self.create_plano_entregas(input_pe, **placeholder_fields) + + # Assert + assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - def create_huge_entrega(id_entrega: int): - new_entrega = input_pe["entregas"][0].copy() - new_entrega["id_entrega"] = str(3 + id_entrega) - new_entrega["nome_entrega"] = "x" * 300 # 300 caracteres - new_entrega["nome_unidade_demandante"] = "x" * 300 # 300 caracteres - new_entrega["nome_unidade_destinataria"] = "x" * 300 # 300 caracteres + def test_create_huge_plano_entregas(self): + """Testa a criação de um Plano de Entregas com grande volume de dados.""" - return new_entrega + def create_huge_entrega(id_entrega: int): + new_entrega = self.input_pe["entregas"][0].copy() + new_entrega["id_entrega"] = str(3 + id_entrega) + new_entrega["nome_entrega"] = "x" * 300 # 300 caracteres + new_entrega["nome_unidade_demandante"] = "x" * 300 # 300 caracteres + new_entrega["nome_unidade_destinataria"] = "x" * 300 # 300 caracteres + return new_entrega - for id_entrega in range(200): - input_pe["entregas"].append(create_huge_entrega(id_entrega)) + for id_entrega in range(200): + self.input_pe["entregas"].append(create_huge_entrega(id_entrega)) - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) - - # Compara o conteúdo do plano de entregas, somente campos obrigatórios - assert response.status_code == http_status.HTTP_201_CREATED - BasePETest.assert_equal_plano_entregas(response.json(), input_pe) + response = self.create_plano_entregas(self.input_pe) + assert response.status_code == http_status.HTTP_201_CREATED + self.assert_equal_plano_entregas(response.json(), self.input_pe) - # Compara o conteúdo de cada entrega, somente campos obrigatórios - response_by_entrega = { - entrega["id_entrega"]: entrega for entrega in response.json()["entregas"] - } - input_by_entrega = { - entrega["id_entrega"]: entrega for entrega in input_pe["entregas"] - } - assert all( - response_by_entrega[id_entrega][attribute] == entrega[attribute] - for attributes in FIELDS_ENTREGA["mandatory"] - for attribute in attributes - for id_entrega, entrega in input_by_entrega.items() - ) + response_by_entrega = { + entrega["id_entrega"]: entrega for entrega in response.json()["entregas"] + } + input_by_entrega = { + entrega["id_entrega"]: entrega for entrega in self.input_pe["entregas"] + } + assert all( + response_by_entrega[id_entrega][attribute] == entrega[attribute] + for attributes in FIELDS_ENTREGA["mandatory"] + for attribute in attributes + for id_entrega, entrega in input_by_entrega.items() + ) @pytest.mark.parametrize( From 6f60785ca743cce6398e04e54ab33abc472a6729 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 12:17:32 -0300 Subject: [PATCH 05/27] Refactor some more test functions into a class --- tests/plano_entregas/core_test.py | 155 ++++++++++++++---------------- 1 file changed, 73 insertions(+), 82 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 6a1eb0a..59c09c1 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -310,95 +310,86 @@ def create_huge_entrega(id_entrega: int): ) -@pytest.mark.parametrize( - "id_plano_entregas, nome_entrega, nome_unidade_demandante, nome_unidade_destinataria", - [ - ("1", "x" * 301, "string", "string"), - ("2", "string", "x" * 301, "string"), - ("3", "string", "string", "x" * 301), - ("4", "x" * 300, "x" * 300, "x" * 300), - ], -) -def test_create_pe_exceed_string_max_size( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - id_plano_entregas: str, - nome_entrega: str, # 300 caracteres - nome_unidade_demandante: str, # 300 caracteres - nome_unidade_destinataria: str, # 300 caracteres - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Testa a criação de um plano de entregas excedendo o tamanho - máximo de cada campo""" - - input_pe["id_plano_entregas"] = id_plano_entregas - input_pe["entregas"][0]["nome_entrega"] = nome_entrega # 300 caracteres - input_pe["entregas"][0][ - "nome_unidade_demandante" - ] = nome_unidade_demandante # 300 caracteres - input_pe["entregas"][0][ - "nome_unidade_destinataria" - ] = nome_unidade_destinataria # 300 caracteres +class TestCreatePEInputValidation(BasePETest): + """Testes para a validação de entrada na criação de um Plano de Entregas.""" - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, + @pytest.mark.parametrize( + "id_plano_entregas, nome_entrega, nome_unidade_demandante, nome_unidade_destinataria", + [ + ("1", "x" * 301, "string", "string"), + ("2", "string", "x" * 301, "string"), + ("3", "string", "string", "x" * 301), + ("4", "x" * 300, "x" * 300, "x" * 300), + ], ) - - if any( - len(campo) > STR_MAX_SIZE - for campo in (nome_entrega, nome_unidade_demandante, nome_unidade_destinataria) + def test_create_pe_exceed_string_max_size( + self, + id_plano_entregas: str, + nome_entrega: str, # 300 caracteres + nome_unidade_demandante: str, # 300 caracteres + nome_unidade_destinataria: str, # 300 caracteres ): - assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - detail_message = "String should have at most 300 characters" - assert response.json().get("detail")[0]["msg"] == detail_message - else: - assert response.status_code == http_status.HTTP_201_CREATED - + """Testa a criação de um plano de entregas excedendo o tamanho + máximo de cada campo. + """ + self.input_pe["id_plano_entregas"] = id_plano_entregas + self.input_pe["entregas"][0]["nome_entrega"] = nome_entrega # 300 caracteres + self.input_pe["entregas"][0][ + "nome_unidade_demandante" + ] = nome_unidade_demandante # 300 caracteres + self.input_pe["entregas"][0][ + "nome_unidade_destinataria" + ] = nome_unidade_destinataria # 300 caracteres -def test_create_pe_cod_plano_inconsistent( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um plano de entregas com código de plano divergente""" + response = self.create_plano_entregas(self.input_pe) - input_pe["id_plano_entregas"] = "110" - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/111", # diferente de 110 - json=input_pe, - headers=header_usr_1, - ) - assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - detail_msg = "Parâmetro id_plano_entregas na URL e no JSON devem ser iguais" - assert response.json().get("detail", None) == detail_msg + if any( + len(campo) > STR_MAX_SIZE + for campo in ( + nome_entrega, + nome_unidade_demandante, + nome_unidade_destinataria, + ) + ): + assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY + detail_message = "String should have at most 300 characters" + assert response.json().get("detail")[0]["msg"] == detail_message + else: + assert response.status_code == http_status.HTTP_201_CREATED + + def test_create_pe_cod_plano_inconsistent( + self, + truncate_pe, # pylint: disable=unused-argument + input_pe: dict, + ): + """Tenta criar um plano de entregas com código de plano divergente""" + input_pe["id_plano_entregas"] = "110" + response = self.create_plano_entregas( + input_pe, id_plano_entregas="111" # diferente de 110 + ) + assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY + detail_msg = "Parâmetro id_plano_entregas na URL e no JSON devem ser iguais" + assert response.json().get("detail", None) == detail_msg -def test_create_pe_cod_unidade_inconsistent( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um plano de entregas com código de unidade divergente""" - original_input_pe = input_pe.copy() - input_pe["cod_unidade_autorizadora"] = 999 # era 1 - response = client.put( - f"/organizacao/SIAPE/{original_input_pe['cod_unidade_autorizadora']}" - f"/plano_entregas/{original_input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) - assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - detail_msg = "Parâmetro cod_unidade_autorizadora na URL e no JSON devem ser iguais" - assert response.json().get("detail", None) == detail_msg + def test_create_pe_cod_unidade_inconsistent( + self, + truncate_pe, # pylint: disable=unused-argument + input_pe: dict, + ): + """Tenta criar um plano de entregas com código de unidade divergente""" + original_input_pe = input_pe.copy() + input_pe["cod_unidade_autorizadora"] = 999 # era 1 + response = self.create_plano_entregas( + input_pe, + cod_unidade_autorizadora=original_input_pe["cod_unidade_autorizadora"], + id_plano_entregas=original_input_pe["id_plano_entregas"], + ) + assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY + detail_msg = ( + "Parâmetro cod_unidade_autorizadora na URL e no JSON devem ser iguais" + ) + assert response.json().get("detail", None) == detail_msg def test_get_plano_entregas( From 9019475d2b9c9e667ba453ea5e7be5bb04fcc4bf Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 12:22:15 -0300 Subject: [PATCH 06/27] Refactor the get test functions into a class --- tests/plano_entregas/core_test.py | 51 ++++++++++++++----------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 59c09c1..9d3ddce 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -392,38 +392,33 @@ def test_create_pe_cod_unidade_inconsistent( assert response.json().get("detail", None) == detail_msg -def test_get_plano_entregas( - truncate_pe, # pylint: disable=unused-argument - example_pe, # pylint: disable=unused-argument - user1_credentials: dict, - header_usr_1: dict, - input_pe, - client: Client, -): - """Tenta buscar um plano de entregas existente""" - - response = client.get( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - headers=header_usr_1, - ) - assert response.status_code == http_status.HTTP_200_OK - BasePETest.assert_equal_plano_entregas(response.json(), input_pe) +class TestGetPlanoEntregas(BasePETest): + """Testes para a busca de Planos de Entregas.""" + def test_get_plano_entregas( + self, + truncate_pe, # pylint: disable=unused-argument + example_pe, # pylint: disable=unused-argument + input_pe, + ): + """Tenta buscar um plano de entregas existente""" -def test_get_pe_inexistente( - user1_credentials: dict, header_usr_1: dict, client: Client -): - """Tenta buscar um plano de entregas inexistente""" + response = self.get_pe( + input_pe["id_plano_entregas"], + self.user1_credentials["cod_unidade_autorizadora"], + ) + assert response.status_code == http_status.HTTP_200_OK + self.assert_equal_plano_entregas(response.json(), input_pe) - response = client.get( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - "/plano_entregas/888888888", - headers=header_usr_1, - ) - assert response.status_code == http_status.HTTP_404_NOT_FOUND + def test_get_pe_inexistente(self): + """Tenta buscar um plano de entregas inexistente""" - assert response.json().get("detail", None) == "Plano de entregas não encontrado" + response = self.get_pe( + "888888888", + self.user1_credentials["cod_unidade_autorizadora"], + ) + assert response.status_code == http_status.HTTP_404_NOT_FOUND + assert response.json().get("detail", None) == "Plano de entregas não encontrado" @pytest.mark.parametrize( From e8a13126ef1eef87acbc84a74e0c71ecc534c402 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 12:24:05 -0300 Subject: [PATCH 07/27] Refactor test_create_invalid_cod_unidade into a class --- tests/plano_entregas/core_test.py | 57 ++++++++++++++----------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 9d3ddce..55c43c3 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -391,6 +391,31 @@ def test_create_pe_cod_unidade_inconsistent( ) assert response.json().get("detail", None) == detail_msg + @pytest.mark.parametrize("cod_unidade_executora", [99, 0, -1]) + def test_create_invalid_cod_unidade( + self, + truncate_pe, # pylint: disable=unused-argument + input_pe: dict, + cod_unidade_executora: int, + ): + """Tenta criar uma entrega com código de unidade inválido. + Por ora não será feita validação no sistema, e sim apenas uma + verificação de sanidade. + """ + input_pe["cod_unidade_executora"] = cod_unidade_executora + + response = self.create_plano_entregas(input_pe) + + if cod_unidade_executora > 0: + assert response.status_code == http_status.HTTP_201_CREATED + else: + assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY + detail_message = "Input should be greater than 0" + assert any( + detail_message in error["msg"] + for error in response.json().get("detail") + ) + class TestGetPlanoEntregas(BasePETest): """Testes para a busca de Planos de Entregas.""" @@ -577,38 +602,6 @@ def test_create_pe_same_id_plano_different_instituidora( assert response.status_code == http_status.HTTP_201_CREATED -@pytest.mark.parametrize("cod_unidade_executora", [99, 0, -1]) -def test_create_invalid_cod_unidade( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - cod_unidade_executora: int, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar uma entrega com código de unidade inválido. - Por ora não será feita validação no sistema, e sim apenas uma - verificação de sanidade. - """ - input_pe["cod_unidade_executora"] = cod_unidade_executora - - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) - - if cod_unidade_executora > 0: - assert response.status_code == http_status.HTTP_201_CREATED - else: - assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - detail_message = "Input should be greater than 0" - assert any( - detail_message in error["msg"] for error in response.json().get("detail") - ) - - @pytest.mark.parametrize( "id_plano_entregas, meta_entrega, tipo_meta", [ From 5f8ef61b6b66e3aaa71d8f5abba679bff61a0602 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 12:26:22 -0300 Subject: [PATCH 08/27] Refactor test_create_entrega_invalid_percent into a class --- tests/plano_entregas/core_test.py | 99 ++++++++++++++----------------- 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 55c43c3..5ed2cfe 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -416,6 +416,52 @@ def test_create_invalid_cod_unidade( for error in response.json().get("detail") ) + @pytest.mark.parametrize( + "id_plano_entregas, meta_entrega, tipo_meta", + [ + ("555", 10, "unidade"), + ("556", 100, "percentual"), + ("557", 1, "percentual"), + ("558", -10, "unidade"), + ("559", 200, "percentual"), + ("560", 0, "unidade"), + ], + ) + def test_create_entrega_invalid_percent( + self, + truncate_pe, # pylint: disable=unused-argument + input_pe: dict, + id_plano_entregas: str, + meta_entrega: int, + tipo_meta: str, + ): + """Tenta criar um Plano de Entregas com entrega com percentuais inválidos""" + input_pe["id_plano_entregas"] = id_plano_entregas + input_pe["entregas"][1]["meta_entrega"] = meta_entrega + input_pe["entregas"][1]["tipo_meta"] = tipo_meta + + response = self.create_plano_entregas(input_pe) + + if tipo_meta == "percentual" and (meta_entrega < 0 or meta_entrega > 100): + assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY + detail_message = ( + "Valor meta_entrega deve estar entre 0 e 100 " + "quando tipo_entrega for percentual." + ) + assert any( + f"Value error, {detail_message}" in error["msg"] + for error in response.json().get("detail") + ) + elif tipo_meta == "unidade" and (meta_entrega < 0): + assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY + detail_message = "Input should be greater than or equal to 0" + assert any( + detail_message in error["msg"] + for error in response.json().get("detail") + ) + else: + assert response.status_code == http_status.HTTP_201_CREATED + class TestGetPlanoEntregas(BasePETest): """Testes para a busca de Planos de Entregas.""" @@ -602,59 +648,6 @@ def test_create_pe_same_id_plano_different_instituidora( assert response.status_code == http_status.HTTP_201_CREATED -@pytest.mark.parametrize( - "id_plano_entregas, meta_entrega, tipo_meta", - [ - ("555", 10, "unidade"), - ("556", 100, "percentual"), - ("557", 1, "percentual"), - ("558", -10, "unidade"), - ("559", 200, "percentual"), - ("560", 0, "unidade"), - ], -) -def test_create_entrega_invalid_percent( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - id_plano_entregas: str, - meta_entrega: int, - tipo_meta: str, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um Plano de Entregas com entrega com percentuais inválidos""" - input_pe["id_plano_entregas"] = id_plano_entregas - input_pe["entregas"][1]["meta_entrega"] = meta_entrega - input_pe["entregas"][1]["tipo_meta"] = tipo_meta - - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) - - if tipo_meta == "percentual" and (meta_entrega < 0 or meta_entrega > 100): - assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - detail_message = ( - "Valor meta_entrega deve estar entre 0 e 100 " - "quando tipo_entrega for percentual." - ) - assert any( - f"Value error, {detail_message}" in error["msg"] - for error in response.json().get("detail") - ) - elif tipo_meta == "unidade" and (meta_entrega < 0): - assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - detail_message = "Input should be greater than or equal to 0" - assert any( - detail_message in error["msg"] for error in response.json().get("detail") - ) - else: - assert response.status_code == http_status.HTTP_201_CREATED - - @pytest.mark.parametrize("tipo_meta", ["unidade", "percentual", "invalid"]) def test_create_entrega_invalid_tipo_meta( truncate_pe, # pylint: disable=unused-argument From adbb5bc679f1270b5e805e87fa477d0cb007a5e1 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 12:28:12 -0300 Subject: [PATCH 09/27] Refactor test_create_entrega_invalid_tipo_meta into a class method --- tests/plano_entregas/core_test.py | 51 +++++++++++++------------------ 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 5ed2cfe..c49bd6a 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -462,6 +462,28 @@ def test_create_entrega_invalid_percent( else: assert response.status_code == http_status.HTTP_201_CREATED + @pytest.mark.parametrize("tipo_meta", ["unidade", "percentual", "invalid"]) + def test_create_entrega_invalid_tipo_meta( + self, + truncate_pe, # pylint: disable=unused-argument + input_pe: dict, + tipo_meta: str, + ): + """Tenta criar um Plano de Entregas com tipo de meta inválido""" + input_pe["entregas"][0]["tipo_meta"] = tipo_meta + + response = self.create_plano_entregas(input_pe) + + if tipo_meta in ("unidade", "percentual"): + assert response.status_code == http_status.HTTP_201_CREATED + else: + assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY + detail_message = "Input should be 'unidade' or 'percentual'" + assert any( + detail_message in error["msg"] + for error in response.json().get("detail") + ) + class TestGetPlanoEntregas(BasePETest): """Testes para a busca de Planos de Entregas.""" @@ -648,35 +670,6 @@ def test_create_pe_same_id_plano_different_instituidora( assert response.status_code == http_status.HTTP_201_CREATED -@pytest.mark.parametrize("tipo_meta", ["unidade", "percentual", "invalid"]) -def test_create_entrega_invalid_tipo_meta( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - user1_credentials: dict, - header_usr_1: dict, - tipo_meta: str, - client: Client, -): - """Tenta criar um Plano de Entregas com tipo de meta inválido""" - input_pe["entregas"][0]["tipo_meta"] = tipo_meta - - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) - - if tipo_meta in ("unidade", "percentual"): - assert response.status_code == http_status.HTTP_201_CREATED - else: - assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - detail_message = "Input should be 'unidade' or 'percentual'" - assert any( - detail_message in error["msg"] for error in response.json().get("detail") - ) - - @pytest.mark.parametrize("avaliacao", [-1, 0, 1, 6]) def test_create_pe_invalid_avaliacao( truncate_pe, # pylint: disable=unused-argument From 9aaf56fbef0f1e6f756c69d19e8021782f46c599 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 12:29:57 -0300 Subject: [PATCH 10/27] Refactor test_create_pe_invalid_avaliacao into a class method --- tests/plano_entregas/core_test.py | 52 +++++++++++++------------------ 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index c49bd6a..4df5ec1 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -484,6 +484,28 @@ def test_create_entrega_invalid_tipo_meta( for error in response.json().get("detail") ) + @pytest.mark.parametrize("avaliacao", [-1, 0, 1, 6]) + def test_create_pe_invalid_avaliacao( + self, + truncate_pe, # pylint: disable=unused-argument + input_pe: dict, + avaliacao: int, + ): + """Tenta criar um Plano de Entregas com nota de avaliação inválida""" + + input_pe["avaliacao"] = avaliacao + response = self.create_plano_entregas(input_pe) + + if avaliacao in range(1, 6): + assert response.status_code == http_status.HTTP_201_CREATED + else: + assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY + detail_message = "Nota de avaliação inválida; permitido: 1, 2, 3, 4, 5" + assert any( + f"Value error, {detail_message}" in error["msg"] + for error in response.json().get("detail") + ) + class TestGetPlanoEntregas(BasePETest): """Testes para a busca de Planos de Entregas.""" @@ -668,33 +690,3 @@ def test_create_pe_same_id_plano_different_instituidora( headers=header_usr_2, ) assert response.status_code == http_status.HTTP_201_CREATED - - -@pytest.mark.parametrize("avaliacao", [-1, 0, 1, 6]) -def test_create_pe_invalid_avaliacao( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - avaliacao: int, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um Plano de Entregas com nota de avaliação inválida""" - - input_pe["avaliacao"] = avaliacao - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) - - if avaliacao in range(1, 6): - assert response.status_code == http_status.HTTP_201_CREATED - else: - assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - detail_message = "Nota de avaliação inválida; permitido: 1, 2, 3, 4, 5" - assert any( - f"Value error, {detail_message}" in error["msg"] - for error in response.json().get("detail") - ) From 5f44226ab490f279e5c10591992f9e2919e577fb Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 15:41:13 -0300 Subject: [PATCH 11/27] Refactor test_create_pe_status_avaliado into a class method --- tests/plano_entregas/core_test.py | 92 ++++++++++++++----------------- 1 file changed, 41 insertions(+), 51 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 4df5ec1..bfdf1e7 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -506,6 +506,47 @@ def test_create_pe_invalid_avaliacao( for error in response.json().get("detail") ) + @pytest.mark.parametrize( + "id_plano_entregas, status, avaliacao, data_avaliacao", + [ + ("78", 5, 2, "2023-06-11"), + ("79", 5, 2, None), # falta data_avaliacao + ("80", 5, None, "2023-06-11"), # falta avaliacao + ("81", 5, None, None), # faltam ambos + ("81", 2, None, None), # status não é 5 + ], + ) + def test_create_pe_status_avaliado( + self, + truncate_pe, # pylint: disable=unused-argument + id_plano_entregas: str, + status: int, + avaliacao: int, + data_avaliacao: str, + ): + """Tenta criar um plano de entregas com datas de avaliação omitidas + ou preenchidas, a depender do status. + + O status 5 só poderá ser usado se os campos "avaliacao" e "data_avaliacao" + estiverem preenchidos. + """ + self.input_pe["status"] = status + self.input_pe["avaliacao"] = avaliacao + self.input_pe["data_avaliacao"] = data_avaliacao + self.input_pe["id_plano_entregas"] = id_plano_entregas + + response = self.create_plano_entregas(self.input_pe) + + if status == 5 and not (avaliacao and data_avaliacao): + assert response.status_code == 422 + detail_message = ( + "O status 5 só poderá ser usado se os campos avaliacao e " + "data_avaliacao estiverem preenchidos." + ) + assert_error_message(response, detail_message) + else: + assert response.status_code == http_status.HTTP_201_CREATED + class TestGetPlanoEntregas(BasePETest): """Testes para a busca de Planos de Entregas.""" @@ -536,57 +577,6 @@ def test_get_pe_inexistente(self): assert response.json().get("detail", None) == "Plano de entregas não encontrado" -@pytest.mark.parametrize( - "id_plano_entregas, status, avaliacao, data_avaliacao", - [ - ("78", 5, 2, "2023-06-11"), - ("79", 5, 2, None), # falta data_avaliacao - ("80", 5, None, "2023-06-11"), # falta avaliacao - ("81", 5, None, None), # faltam ambos - ("81", 2, None, None), # status não é 5 - ], -) -def test_create_pe_status_avaliado( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - status: int, - avaliacao: int, - data_avaliacao: str, - id_plano_entregas: str, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um plano de entregas com datas de avaliação omitidas - ou preenchidas, a depender do status. - - O status 5 só poderá ser usado se os campos “avaliacao” e “data_avaliacao” - estiverem preenchidos. - """ - - input_pe["status"] = status - input_pe["avaliacao"] = avaliacao - input_pe["data_avaliacao"] = data_avaliacao - input_pe["id_plano_entregas"] = id_plano_entregas - - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{id_plano_entregas}", - json=input_pe, - headers=header_usr_1, - ) - - if status == 5 and not (avaliacao and data_avaliacao): - assert response.status_code == 422 - detail_message = ( - "O status 5 só poderá ser usado se os campos avaliacao e " - "data_avaliacao estiverem preenchidos." - ) - assert_error_message(response, detail_message) - else: - assert response.status_code == http_status.HTTP_201_CREATED - - @pytest.mark.parametrize( "id_plano_entregas, id_entrega_1, id_entrega_2", [ From 6b13180b1baaa9cfbf19bc98abf1b9dd56746801 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 15:54:01 -0300 Subject: [PATCH 12/27] Use copies of input data instead of the original --- tests/plano_entregas/core_test.py | 81 ++++++++++++++++--------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index bfdf1e7..5a7ae9d 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -198,21 +198,22 @@ def test_create_plano_entregas_completo(self): assert response.json().get("detail", None) is None self.assert_equal_plano_entregas(response.json(), self.input_pe) - def test_update_plano_entregas(self, example_pe): + def test_update_plano_entregas(self, example_pe): # pylint: disable=unused-argument """Tenta criar um novo Plano de Entregas e atualizar alguns campos. A fixture example_pe cria um novo Plano de Entregas na API. O teste altera um campo do PE e reenvia pra API (update). """ - self.input_pe["avaliacao"] = 3 - self.input_pe["data_avaliacao"] = "2023-08-15" - response = self.create_plano_entregas(self.input_pe) + input_pe = self.input_pe.copy() + input_pe["avaliacao"] = 3 + input_pe["data_avaliacao"] = "2023-08-15" + response = self.create_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_200_OK assert response.json()["avaliacao"] == 3 assert response.json()["data_avaliacao"] == "2023-08-15" # Consulta API para conferir se a alteração foi persistida response = self.get_pe( - self.input_pe["id_plano_entregas"], + input_pe["id_plano_entregas"], self.user1_credentials["cod_unidade_autorizadora"], ) assert response.status_code == http_status.HTTP_200_OK @@ -222,30 +223,32 @@ def test_update_plano_entregas(self, example_pe): @pytest.mark.parametrize("omitted_fields", enumerate(FIELDS_ENTREGA["optional"])) def test_create_plano_entregas_entrega_omit_optional_fields(self, omitted_fields): """Tenta criar um novo Plano de Entregas omitindo campos opcionais.""" + input_pe = self.input_pe.copy() offset, field_list = omitted_fields for field in field_list: - for entrega in self.input_pe["entregas"]: + for entrega in input_pe["entregas"]: if field in entrega: del entrega[field] - self.input_pe["id_plano_entregas"] = str(557 + offset) - response = self.create_plano_entregas(self.input_pe) + input_pe["id_plano_entregas"] = str(557 + offset) + response = self.create_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_201_CREATED - self.assert_equal_plano_entregas(response.json(), self.input_pe) + self.assert_equal_plano_entregas(response.json(), input_pe) @pytest.mark.parametrize("nulled_fields", enumerate(FIELDS_ENTREGA["optional"])) def test_create_plano_entregas_entrega_null_optional_fields(self, nulled_fields): """Tenta criar um novo Plano de Entregas com o valor null nos campos opcionais.""" + input_pe = self.input_pe.copy() offset, field_list = nulled_fields for field in field_list: - for entrega in self.input_pe["entregas"]: + for entrega in input_pe["entregas"]: if field in entrega: entrega[field] = None - self.input_pe["id_plano_entregas"] = str(557 + offset) - response = self.create_plano_entregas(self.input_pe) + input_pe["id_plano_entregas"] = str(557 + offset) + response = self.create_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_201_CREATED - self.assert_equal_plano_entregas(response.json(), self.input_pe) + self.assert_equal_plano_entregas(response.json(), input_pe) @pytest.mark.parametrize( "missing_fields", enumerate(FIELDS_PLANO_ENTREGAS["mandatory"]) @@ -280,9 +283,10 @@ def test_create_plano_entregas_missing_mandatory_fields(self, missing_fields): def test_create_huge_plano_entregas(self): """Testa a criação de um Plano de Entregas com grande volume de dados.""" + input_pe = self.input_pe.copy() def create_huge_entrega(id_entrega: int): - new_entrega = self.input_pe["entregas"][0].copy() + new_entrega = input_pe["entregas"][0].copy() new_entrega["id_entrega"] = str(3 + id_entrega) new_entrega["nome_entrega"] = "x" * 300 # 300 caracteres new_entrega["nome_unidade_demandante"] = "x" * 300 # 300 caracteres @@ -290,17 +294,17 @@ def create_huge_entrega(id_entrega: int): return new_entrega for id_entrega in range(200): - self.input_pe["entregas"].append(create_huge_entrega(id_entrega)) + input_pe["entregas"].append(create_huge_entrega(id_entrega)) - response = self.create_plano_entregas(self.input_pe) + response = self.create_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_201_CREATED - self.assert_equal_plano_entregas(response.json(), self.input_pe) + self.assert_equal_plano_entregas(response.json(), input_pe) response_by_entrega = { entrega["id_entrega"]: entrega for entrega in response.json()["entregas"] } input_by_entrega = { - entrega["id_entrega"]: entrega for entrega in self.input_pe["entregas"] + entrega["id_entrega"]: entrega for entrega in input_pe["entregas"] } assert all( response_by_entrega[id_entrega][attribute] == entrega[attribute] @@ -332,16 +336,17 @@ def test_create_pe_exceed_string_max_size( """Testa a criação de um plano de entregas excedendo o tamanho máximo de cada campo. """ - self.input_pe["id_plano_entregas"] = id_plano_entregas - self.input_pe["entregas"][0]["nome_entrega"] = nome_entrega # 300 caracteres - self.input_pe["entregas"][0][ + input_pe = self.input_pe.copy() + input_pe["id_plano_entregas"] = id_plano_entregas + input_pe["entregas"][0]["nome_entrega"] = nome_entrega # 300 caracteres + input_pe["entregas"][0][ "nome_unidade_demandante" ] = nome_unidade_demandante # 300 caracteres - self.input_pe["entregas"][0][ + input_pe["entregas"][0][ "nome_unidade_destinataria" ] = nome_unidade_destinataria # 300 caracteres - response = self.create_plano_entregas(self.input_pe) + response = self.create_plano_entregas(input_pe) if any( len(campo) > STR_MAX_SIZE @@ -360,10 +365,9 @@ def test_create_pe_exceed_string_max_size( def test_create_pe_cod_plano_inconsistent( self, truncate_pe, # pylint: disable=unused-argument - input_pe: dict, ): """Tenta criar um plano de entregas com código de plano divergente""" - + input_pe = self.input_pe.copy() input_pe["id_plano_entregas"] = "110" response = self.create_plano_entregas( input_pe, id_plano_entregas="111" # diferente de 110 @@ -375,9 +379,9 @@ def test_create_pe_cod_plano_inconsistent( def test_create_pe_cod_unidade_inconsistent( self, truncate_pe, # pylint: disable=unused-argument - input_pe: dict, ): """Tenta criar um plano de entregas com código de unidade divergente""" + input_pe = self.input_pe.copy() original_input_pe = input_pe.copy() input_pe["cod_unidade_autorizadora"] = 999 # era 1 response = self.create_plano_entregas( @@ -395,13 +399,13 @@ def test_create_pe_cod_unidade_inconsistent( def test_create_invalid_cod_unidade( self, truncate_pe, # pylint: disable=unused-argument - input_pe: dict, cod_unidade_executora: int, ): """Tenta criar uma entrega com código de unidade inválido. Por ora não será feita validação no sistema, e sim apenas uma verificação de sanidade. """ + input_pe = self.input_pe.copy() input_pe["cod_unidade_executora"] = cod_unidade_executora response = self.create_plano_entregas(input_pe) @@ -430,12 +434,12 @@ def test_create_invalid_cod_unidade( def test_create_entrega_invalid_percent( self, truncate_pe, # pylint: disable=unused-argument - input_pe: dict, id_plano_entregas: str, meta_entrega: int, tipo_meta: str, ): """Tenta criar um Plano de Entregas com entrega com percentuais inválidos""" + input_pe = self.input_pe.copy() input_pe["id_plano_entregas"] = id_plano_entregas input_pe["entregas"][1]["meta_entrega"] = meta_entrega input_pe["entregas"][1]["tipo_meta"] = tipo_meta @@ -466,10 +470,10 @@ def test_create_entrega_invalid_percent( def test_create_entrega_invalid_tipo_meta( self, truncate_pe, # pylint: disable=unused-argument - input_pe: dict, tipo_meta: str, ): """Tenta criar um Plano de Entregas com tipo de meta inválido""" + input_pe = self.input_pe.copy() input_pe["entregas"][0]["tipo_meta"] = tipo_meta response = self.create_plano_entregas(input_pe) @@ -488,11 +492,10 @@ def test_create_entrega_invalid_tipo_meta( def test_create_pe_invalid_avaliacao( self, truncate_pe, # pylint: disable=unused-argument - input_pe: dict, avaliacao: int, ): """Tenta criar um Plano de Entregas com nota de avaliação inválida""" - + input_pe = self.input_pe.copy() input_pe["avaliacao"] = avaliacao response = self.create_plano_entregas(input_pe) @@ -530,12 +533,13 @@ def test_create_pe_status_avaliado( O status 5 só poderá ser usado se os campos "avaliacao" e "data_avaliacao" estiverem preenchidos. """ - self.input_pe["status"] = status - self.input_pe["avaliacao"] = avaliacao - self.input_pe["data_avaliacao"] = data_avaliacao - self.input_pe["id_plano_entregas"] = id_plano_entregas + input_pe = self.input_pe.copy() + input_pe["status"] = status + input_pe["avaliacao"] = avaliacao + input_pe["data_avaliacao"] = data_avaliacao + input_pe["id_plano_entregas"] = id_plano_entregas - response = self.create_plano_entregas(self.input_pe) + response = self.create_plano_entregas(input_pe) if status == 5 and not (avaliacao and data_avaliacao): assert response.status_code == 422 @@ -555,16 +559,15 @@ def test_get_plano_entregas( self, truncate_pe, # pylint: disable=unused-argument example_pe, # pylint: disable=unused-argument - input_pe, ): """Tenta buscar um plano de entregas existente""" response = self.get_pe( - input_pe["id_plano_entregas"], + self.input_pe["id_plano_entregas"], self.user1_credentials["cod_unidade_autorizadora"], ) assert response.status_code == http_status.HTTP_200_OK - self.assert_equal_plano_entregas(response.json(), input_pe) + self.assert_equal_plano_entregas(response.json(), self.input_pe) def test_get_pe_inexistente(self): """Tenta buscar um plano de entregas inexistente""" From 2a7d2e895810af22a3a7d45d1bb262c8b1aefc81 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 15:56:09 -0300 Subject: [PATCH 13/27] Rename methods to improve code readability --- tests/plano_entregas/core_test.py | 8 +++---- .../avaliacao_registros_execucao_test.py | 6 ++--- tests/plano_trabalho/contribuicoes_test.py | 14 +++++------ tests/plano_trabalho/core_test.py | 24 +++++++++---------- tests/plano_trabalho/date_validation_test.py | 14 +++++------ tests/plano_trabalho/permissions_test.py | 8 +++---- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 5a7ae9d..6b4bd25 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -150,7 +150,7 @@ def create_plano_entregas( ) return response - def get_pe( + def get_plano_entregas( self, id_plano_entregas: str, cod_unidade_autorizadora: int, @@ -212,7 +212,7 @@ def test_update_plano_entregas(self, example_pe): # pylint: disable=unused-argu assert response.json()["data_avaliacao"] == "2023-08-15" # Consulta API para conferir se a alteração foi persistida - response = self.get_pe( + response = self.get_plano_entregas( input_pe["id_plano_entregas"], self.user1_credentials["cod_unidade_autorizadora"], ) @@ -562,7 +562,7 @@ def test_get_plano_entregas( ): """Tenta buscar um plano de entregas existente""" - response = self.get_pe( + response = self.get_plano_entregas( self.input_pe["id_plano_entregas"], self.user1_credentials["cod_unidade_autorizadora"], ) @@ -572,7 +572,7 @@ def test_get_plano_entregas( def test_get_pe_inexistente(self): """Tenta buscar um plano de entregas inexistente""" - response = self.get_pe( + response = self.get_plano_entregas( "888888888", self.user1_credentials["cod_unidade_autorizadora"], ) diff --git a/tests/plano_trabalho/avaliacao_registros_execucao_test.py b/tests/plano_trabalho/avaliacao_registros_execucao_test.py index 03e143f..936e40c 100644 --- a/tests/plano_trabalho/avaliacao_registros_execucao_test.py +++ b/tests/plano_trabalho/avaliacao_registros_execucao_test.py @@ -36,7 +36,7 @@ def test_create_pt_missing_mandatory_fields_avaliacao_registros_execucao( input_pt["avaliacoes_registros_execucao"][0][field] = None input_pt["id_plano_trabalho"] = "111222333" - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY @@ -70,7 +70,7 @@ def test_create_pt_invalid_avaliacao_registros_execucao( "avaliacao_registros_execucao" ] = avaliacao_registros_execucao - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) if avaliacao_registros_execucao in range(1, 6): assert response.status_code == status.HTTP_201_CREATED @@ -208,7 +208,7 @@ def test_create_pt_invalid_avaliacao_registros_execucao_date( "data_avaliacao_registros_execucao" ] = data_avaliacao_registros_execucao - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) if date.fromisoformat(data_avaliacao_registros_execucao) > date.fromisoformat( data_inicio_periodo_avaliativo diff --git a/tests/plano_trabalho/contribuicoes_test.py b/tests/plano_trabalho/contribuicoes_test.py index 0099811..24d473b 100644 --- a/tests/plano_trabalho/contribuicoes_test.py +++ b/tests/plano_trabalho/contribuicoes_test.py @@ -45,7 +45,7 @@ def test_create_pt_missing_mandatory_fields_contribuicoes( "percentual_contribuicao" ] = percentual_contribuicao - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY @@ -70,7 +70,7 @@ def test_create_pt_invalid_tipo_contribuicao( input_pt = self.input_pt.copy() input_pt["contribuicoes"][0]["tipo_contribuicao"] = tipo_contribuicao - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) if tipo_contribuicao in [1, 2, 3]: assert response.status_code == status.HTTP_201_CREATED @@ -105,7 +105,7 @@ def test_create_plano_trabalho_percentual_contribuicao( "percentual_contribuicao" ] = percentual_contribuicao - response = self.create_pt(input_pt, header_usr=self.header_usr_1) + response = self.create_plano_trabalho(input_pt, header_usr=self.header_usr_1) if 0 <= percentual_contribuicao <= 100: assert response.status_code == status.HTTP_201_CREATED @@ -142,7 +142,7 @@ def test_create_plano_trabalho_contribuicao_omit_optional_fields( del contribuicao[field] partial_input_pt["id_plano_trabalho"] = str(557 + offset) - response = self.create_pt(partial_input_pt) + response = self.create_plano_trabalho(partial_input_pt) assert response.status_code == status.HTTP_201_CREATED @@ -173,7 +173,7 @@ def test_create_plano_trabalho_contribuicao_null_optional_fields( contribuicao[field] = None partial_input_pt["id_plano_trabalho"] = str(557 + offset) - response = self.create_pt(partial_input_pt) + response = self.create_plano_trabalho(partial_input_pt) assert response.status_code == status.HTTP_201_CREATED @@ -223,7 +223,7 @@ def test_tipo_contribuicao( contribuicao["tipo_contribuicao"] = tipo_contribuicao contribuicao["id_plano_entregas"] = id_plano_entregas contribuicao["id_entrega"] = id_entrega - response = self.create_pt(input_pt, header_usr=self.header_usr_1) + response = self.create_plano_trabalho(input_pt, header_usr=self.header_usr_1) error_messages = [] if tipo_contribuicao == 1: @@ -263,7 +263,7 @@ def test_referencia_entrega_inexistente( contribuicao["id_plano_entregas"] = id_plano_entregas contribuicao["id_entrega"] = id_entrega - response = self.create_pt(input_pt, header_usr=self.header_usr_1) + response = self.create_plano_trabalho(input_pt, header_usr=self.header_usr_1) if id_plano_entregas == input_pe["id_plano_entregas"] and \ id_entrega in [entrega["id_entrega"] for entrega in input_pe["entregas"]]: diff --git a/tests/plano_trabalho/core_test.py b/tests/plano_trabalho/core_test.py index 45979f4..a83e5ac 100644 --- a/tests/plano_trabalho/core_test.py +++ b/tests/plano_trabalho/core_test.py @@ -150,7 +150,7 @@ def assert_equal_plano_trabalho(plano_trabalho_1: dict, plano_trabalho_2: dict): ) assert avaliacao_registros_execucao_1 == avaliacao_registros_execucao_2 - def create_pt( + def create_plano_trabalho( self, input_pt: dict, id_plano_trabalho: Optional[str] = None, @@ -190,7 +190,7 @@ def create_pt( ) return response - def get_pt( + def get_plano_trabalho( self, id_plano_trabalho: str, cod_unidade_autorizadora: int, @@ -227,13 +227,13 @@ def test_completo(self): """Cria um novo Plano de Trabalho do Participante, em uma unidade na qual ele está autorizado, contendo todos os dados necessários. """ - response = self.create_pt(self.input_pt) + response = self.create_plano_trabalho(self.input_pt) assert response.status_code == status.HTTP_201_CREATED self.assert_equal_plano_trabalho(response.json(), self.input_pt) # Consulta API para conferir se a criação foi persistida - response = self.get_pt( + response = self.get_plano_trabalho( self.input_pt["id_plano_trabalho"], self.input_pt["cod_unidade_autorizadora"], ) @@ -270,7 +270,7 @@ def test_create_plano_trabalho_missing_mandatory_fields(self, missing_fields): input_pt["id_plano_trabalho"] = f"{1800 + offset}" # precisa ser um novo plano # Act - response = self.create_pt(input_pt, **placeholder_fields) + response = self.create_plano_trabalho(input_pt, **placeholder_fields) # Assert assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY @@ -284,7 +284,7 @@ def test_create_pt_cod_plano_inconsistent(self): input_pt["id_plano_trabalho"] = "110" # Act - response = self.create_pt( + response = self.create_plano_trabalho( input_pt, id_plano_trabalho="111", header_usr=self.header_usr_1 ) @@ -310,7 +310,7 @@ def test_create_pt_invalid_carga_horaria_disponivel(self, carga_horaria_disponiv input_pt["carga_horaria_disponivel"] = carga_horaria_disponivel # Act - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) # Assert assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY @@ -356,7 +356,7 @@ def test_put_plano_trabalho_invalid_cpf(self, cpf_participante): input_pt["cpf_participante"] = cpf_participante # Act - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) # Assert assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY @@ -408,12 +408,12 @@ def test_update_plano_trabalho(self): input_pt = self.input_pt.copy() input_pt["status"] = 4 # Valor era 3 input_pt["data_termino"] = "2023-01-31" # Valor era "2023-01-15" - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) assert response.status_code == status.HTTP_200_OK self.assert_equal_plano_trabalho(response.json(), input_pt) # Consulta API para conferir se a alteração foi persistida - response = self.get_pt( + response = self.get_plano_trabalho( input_pt["id_plano_trabalho"], self.user1_credentials["cod_unidade_autorizadora"], ) @@ -433,7 +433,7 @@ def test_get_plano_trabalho(self, example_pt): # pylint: disable=unused-argumen input_pt["contribuicoes"][1]["id_entrega"] = None input_pt["contribuicoes"][1]["descricao_contribuicao"] = None - response = self.get_pt( + response = self.get_plano_trabalho( input_pt["id_plano_trabalho"], input_pt["cod_unidade_autorizadora"] ) @@ -444,7 +444,7 @@ def test_get_pt_inexistente(self): """Tenta acessar um plano de trabalho inexistente.""" non_existent_id = "888888888" - response = self.get_pt( + response = self.get_plano_trabalho( non_existent_id, self.user1_credentials["cod_unidade_autorizadora"] ) diff --git a/tests/plano_trabalho/date_validation_test.py b/tests/plano_trabalho/date_validation_test.py index 1c8b39b..93b6201 100644 --- a/tests/plano_trabalho/date_validation_test.py +++ b/tests/plano_trabalho/date_validation_test.py @@ -68,7 +68,7 @@ def test_create_pt_invalid_dates( assert response.status_code in (status.HTTP_200_OK, status.HTTP_201_CREATED) # cria o plano_trabalho com a data_inicio informada - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) if data_inicio > data_termino: assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY detail_message = ( @@ -100,7 +100,7 @@ def test_create_plano_trabalho_date_interval_over_a_year( input_pt["data_inicio"] = data_inicio input_pt["data_termino"] = data_termino - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) if ( over_a_year( @@ -210,7 +210,7 @@ def test_create_plano_trabalho_overlapping_date_interval( "carga_horaria_disponivel": 80, } ] - response = self.create_pt(input_pt2) + response = self.create_plano_trabalho(input_pt2) assert response.status_code == status.HTTP_201_CREATED input_pt["id_plano_trabalho"] = id_plano_trabalho @@ -220,7 +220,7 @@ def test_create_plano_trabalho_overlapping_date_interval( input_pt["data_termino"] = data_termino input_pt["status"] = status_pt input_pt["avaliacoes_registros_execucao"] = [] - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) if ( # se algum dos planos estiver cancelado, não há problema em haver @@ -303,7 +303,7 @@ def test_create_pt_invalid_periodo_avaliativo( "data_fim_periodo_avaliativo" ] = data_fim_periodo_avaliativo - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) if date.fromisoformat(data_fim_periodo_avaliativo) < date.fromisoformat( data_inicio_periodo_avaliativo @@ -357,7 +357,7 @@ def test_create_pt_data_avaliacao_out_of_bounds( "data_avaliacao_registros_execucao" ] = data_avaliacao_registros_execucao - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) if date.fromisoformat(data_avaliacao_registros_execucao) < date.fromisoformat( data_inicio_periodo_avaliativo ): @@ -442,7 +442,7 @@ def test_create_plano_trabalho_avaliacao_overlapping_date_interval( avaliacao_template["data_avaliacao_registros_execucao"] = "2024-01-01" input_pt["avaliacoes_registros_execucao"].append(avaliacao_template) - response = self.create_pt(input_pt) + response = self.create_plano_trabalho(input_pt) periodo_avaliativo.sort(key=lambda avaliacao: avaliacao[0]) for avaliacao_1, avaliacao_2 in zip( diff --git a/tests/plano_trabalho/permissions_test.py b/tests/plano_trabalho/permissions_test.py index e82cb3a..4e4c271 100644 --- a/tests/plano_trabalho/permissions_test.py +++ b/tests/plano_trabalho/permissions_test.py @@ -29,7 +29,7 @@ def test_get_pt_different_unit( example_pe_unidade_3: Fixture para criar um PE na unidade 3. example_pt_unidade_3: Fixture para criar um PT na unidade 3. """ - response = self.get_pt( + response = self.get_plano_trabalho( id_plano_trabalho=self.input_pt["id_plano_trabalho"], cod_unidade_autorizadora=3, # Unidade diferente header_usr=header_usr_2, @@ -60,7 +60,7 @@ def test_get_pt_different_unit_admin( input_pt = self.input_pt.copy() # Obter o plano de trabalho de uma unidade diferente - response = self.get_pt( + response = self.get_plano_trabalho( self.input_pt["id_plano_trabalho"], 3, header_usr=header_admin ) @@ -83,7 +83,7 @@ def test_create_plano_trabalho_unidade_nao_permitida(self, header_usr_2: dict): header_usr_2 (dict): Cabeçalho do usuário na unidade diferente. """ # Criar o Plano de Trabalho em uma unidade diferente - response = self.create_pt( + response = self.create_plano_trabalho( self.input_pt, cod_unidade_autorizadora=3, header_usr=header_usr_2 ) @@ -128,7 +128,7 @@ def test_create_plano_trabalho_outra_unidade_admin( assert admin_data.get("is_admin", None) is True # Criar o Plano de Trabalho em uma unidade diferente - response = self.create_pt( + response = self.create_plano_trabalho( input_pt, cod_unidade_autorizadora=3, header_usr=header_admin ) From 5edef5bddfe38a6551c1774bac29f55ce30567de Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 16:06:06 -0300 Subject: [PATCH 14/27] Refactor into a class functions that test duplicate data --- tests/plano_entregas/core_test.py | 168 +++++++++++++----------------- 1 file changed, 71 insertions(+), 97 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 6b4bd25..6b7ff48 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -580,106 +580,80 @@ def test_get_pe_inexistente(self): assert response.json().get("detail", None) == "Plano de entregas não encontrado" -@pytest.mark.parametrize( - "id_plano_entregas, id_entrega_1, id_entrega_2", - [ - ("90", "401", "402"), - ("91", "403", "403"), # <<<< IGUAIS - ("92", "404", "404"), # <<<< IGUAIS - ("93", "405", "406"), - ], -) -def test_create_pe_duplicate_entrega( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - id_plano_entregas: str, - id_entrega_1: str, - id_entrega_2: str, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um plano de entregas com entregas com id_entrega duplicados""" - - input_pe["id_plano_entregas"] = id_plano_entregas - input_pe["entregas"][0]["id_entrega"] = id_entrega_1 - input_pe["entregas"][1]["id_entrega"] = id_entrega_2 - - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{id_plano_entregas}", - json=input_pe, - headers=header_usr_1, +class TestCreatePEDuplicateData(BasePETest): + """Testes para a criação de um Plano de Entregas com dados duplicados.""" + + @pytest.mark.parametrize( + "id_plano_entregas, id_entrega_1, id_entrega_2", + [ + ("90", "401", "402"), + ("91", "403", "403"), # <<<< IGUAIS + ("92", "404", "404"), # <<<< IGUAIS + ("93", "405", "406"), + ], ) - if id_entrega_1 == id_entrega_2: - assert response.status_code == 422 - detail_message = "Entregas devem possuir id_entrega diferentes" - assert any( - f"Value error, {detail_message}" in error["msg"] - for error in response.json().get("detail") - ) - else: - assert response.status_code == http_status.HTTP_201_CREATED + def test_create_pe_duplicate_entrega( + self, + truncate_pe, # pylint: disable=unused-argument + id_plano_entregas: str, + id_entrega_1: str, + id_entrega_2: str, + ): + """Tenta criar um plano de entregas com entregas com id_entrega duplicados""" + input_pe = self.input_pe.copy() + input_pe["id_plano_entregas"] = id_plano_entregas + input_pe["entregas"][0]["id_entrega"] = id_entrega_1 + input_pe["entregas"][1]["id_entrega"] = id_entrega_2 -def test_create_pe_duplicate_id_plano( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um plano de entregas duplicado. O envio do mesmo - plano de entregas pela segunda vez deve substituir o primeiro. - """ - - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) + response = self.create_plano_entregas(input_pe) + if id_entrega_1 == id_entrega_2: + assert response.status_code == 422 + detail_message = "Entregas devem possuir id_entrega diferentes" + assert any( + f"Value error, {detail_message}" in error["msg"] + for error in response.json().get("detail") + ) + else: + assert response.status_code == http_status.HTTP_201_CREATED + + def test_create_pe_duplicate_id_plano( + self, + truncate_pe, # pylint: disable=unused-argument + input_pe: dict, + ): + """Tenta criar um plano de entregas duplicado. O envio do mesmo + plano de entregas pela segunda vez deve substituir o primeiro. + """ - assert response.status_code == http_status.HTTP_201_CREATED + response = self.create_plano_entregas(input_pe) + assert response.status_code == http_status.HTTP_201_CREATED - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) + response = self.create_plano_entregas(input_pe) + assert response.status_code == http_status.HTTP_200_OK + assert response.json().get("detail", None) is None + self.assert_equal_plano_entregas(response.json(), input_pe) - assert response.status_code == http_status.HTTP_200_OK - assert response.json().get("detail", None) is None - BasePETest.assert_equal_plano_entregas(response.json(), input_pe) - - -def test_create_pe_same_id_plano_different_instituidora( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - user1_credentials: dict, - user2_credentials: dict, - header_usr_1: dict, - header_usr_2: dict, - client: Client, -): - """Tenta criar um plano de entregas duplicado. O envio do mesmo - plano de entregas pela segunda vez deve substituir o primeiro. - """ - - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, - ) - assert response.status_code == http_status.HTTP_201_CREATED - - input_pe["cod_unidade_autorizadora"] = user2_credentials["cod_unidade_autorizadora"] - response = client.put( - f"/organizacao/SIAPE/{user2_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_2, - ) - assert response.status_code == http_status.HTTP_201_CREATED + def test_create_pe_same_id_plano_different_instituidora( + self, + truncate_pe, # pylint: disable=unused-argument + input_pe: dict, + user2_credentials: dict, + header_usr_2: dict, + ): + """Tenta criar um plano de entregas duplicado. O envio do mesmo + plano de entregas pela segunda vez deve substituir o primeiro. + """ + + response = self.create_plano_entregas(input_pe) + assert response.status_code == http_status.HTTP_201_CREATED + + input_pe["cod_unidade_autorizadora"] = user2_credentials[ + "cod_unidade_autorizadora" + ] + response = self.create_plano_entregas( + input_pe, + cod_unidade_autorizadora=user2_credentials["cod_unidade_autorizadora"], + header_usr=header_usr_2, + ) + assert response.status_code == http_status.HTTP_201_CREATED From 614530bb55245c5f0065a18a55c36ab57feca9ee Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 16:06:25 -0300 Subject: [PATCH 15/27] Add spacing after docstring --- tests/plano_entregas/core_test.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 6b7ff48..ffb5a58 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -193,6 +193,7 @@ class TestCreatePlanoEntrega(BasePETest): def test_create_plano_entregas_completo(self): """Tenta criar um novo Plano de Entregas.""" + response = self.create_plano_entregas(self.input_pe) assert response.status_code == http_status.HTTP_201_CREATED assert response.json().get("detail", None) is None @@ -203,6 +204,7 @@ def test_update_plano_entregas(self, example_pe): # pylint: disable=unused-argu A fixture example_pe cria um novo Plano de Entregas na API. O teste altera um campo do PE e reenvia pra API (update). """ + input_pe = self.input_pe.copy() input_pe["avaliacao"] = 3 input_pe["data_avaliacao"] = "2023-08-15" @@ -223,6 +225,7 @@ def test_update_plano_entregas(self, example_pe): # pylint: disable=unused-argu @pytest.mark.parametrize("omitted_fields", enumerate(FIELDS_ENTREGA["optional"])) def test_create_plano_entregas_entrega_omit_optional_fields(self, omitted_fields): """Tenta criar um novo Plano de Entregas omitindo campos opcionais.""" + input_pe = self.input_pe.copy() offset, field_list = omitted_fields for field in field_list: @@ -238,6 +241,7 @@ def test_create_plano_entregas_entrega_omit_optional_fields(self, omitted_fields @pytest.mark.parametrize("nulled_fields", enumerate(FIELDS_ENTREGA["optional"])) def test_create_plano_entregas_entrega_null_optional_fields(self, nulled_fields): """Tenta criar um novo Plano de Entregas com o valor null nos campos opcionais.""" + input_pe = self.input_pe.copy() offset, field_list = nulled_fields for field in field_list: @@ -258,6 +262,7 @@ def test_create_plano_entregas_missing_mandatory_fields(self, missing_fields): Na atualização com PUT, ainda assim é necessário informar todos os campos obrigatórios, uma vez que o conteúdo será substituído. """ + offset, field_list = missing_fields input_pe = self.input_pe.copy() # define um id_plano_entregas diferente para cada teste @@ -336,6 +341,7 @@ def test_create_pe_exceed_string_max_size( """Testa a criação de um plano de entregas excedendo o tamanho máximo de cada campo. """ + input_pe = self.input_pe.copy() input_pe["id_plano_entregas"] = id_plano_entregas input_pe["entregas"][0]["nome_entrega"] = nome_entrega # 300 caracteres @@ -367,6 +373,7 @@ def test_create_pe_cod_plano_inconsistent( truncate_pe, # pylint: disable=unused-argument ): """Tenta criar um plano de entregas com código de plano divergente""" + input_pe = self.input_pe.copy() input_pe["id_plano_entregas"] = "110" response = self.create_plano_entregas( @@ -381,6 +388,7 @@ def test_create_pe_cod_unidade_inconsistent( truncate_pe, # pylint: disable=unused-argument ): """Tenta criar um plano de entregas com código de unidade divergente""" + input_pe = self.input_pe.copy() original_input_pe = input_pe.copy() input_pe["cod_unidade_autorizadora"] = 999 # era 1 @@ -405,6 +413,7 @@ def test_create_invalid_cod_unidade( Por ora não será feita validação no sistema, e sim apenas uma verificação de sanidade. """ + input_pe = self.input_pe.copy() input_pe["cod_unidade_executora"] = cod_unidade_executora @@ -439,6 +448,7 @@ def test_create_entrega_invalid_percent( tipo_meta: str, ): """Tenta criar um Plano de Entregas com entrega com percentuais inválidos""" + input_pe = self.input_pe.copy() input_pe["id_plano_entregas"] = id_plano_entregas input_pe["entregas"][1]["meta_entrega"] = meta_entrega @@ -473,6 +483,7 @@ def test_create_entrega_invalid_tipo_meta( tipo_meta: str, ): """Tenta criar um Plano de Entregas com tipo de meta inválido""" + input_pe = self.input_pe.copy() input_pe["entregas"][0]["tipo_meta"] = tipo_meta @@ -495,6 +506,7 @@ def test_create_pe_invalid_avaliacao( avaliacao: int, ): """Tenta criar um Plano de Entregas com nota de avaliação inválida""" + input_pe = self.input_pe.copy() input_pe["avaliacao"] = avaliacao response = self.create_plano_entregas(input_pe) @@ -533,6 +545,7 @@ def test_create_pe_status_avaliado( O status 5 só poderá ser usado se os campos "avaliacao" e "data_avaliacao" estiverem preenchidos. """ + input_pe = self.input_pe.copy() input_pe["status"] = status input_pe["avaliacao"] = avaliacao From cd88de4b273aac7a684fd4e61ea54dfe5ea04a58 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 16:20:43 -0300 Subject: [PATCH 16/27] Improve upon docstrings and comments --- tests/plano_entregas/core_test.py | 48 ++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index ffb5a58..9673bc8 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -570,10 +570,15 @@ class TestGetPlanoEntregas(BasePETest): def test_get_plano_entregas( self, - truncate_pe, # pylint: disable=unused-argument - example_pe, # pylint: disable=unused-argument + # pylint: disable=unused-argument + truncate_pe, # limpa a base de Planos de Entregas + example_pe, # cria um Plano de Entregas de exemplo ): - """Tenta buscar um plano de entregas existente""" + """Testa a busca de um Plano de Entregas existente. + + Verifica se a API retorna um status 200 OK e se o Plano de Entregas + retornado é igual ao Plano de Entregas criado. + """ response = self.get_plano_entregas( self.input_pe["id_plano_entregas"], @@ -583,7 +588,11 @@ def test_get_plano_entregas( self.assert_equal_plano_entregas(response.json(), self.input_pe) def test_get_pe_inexistente(self): - """Tenta buscar um plano de entregas inexistente""" + """Testa a busca de um Plano de Entregas inexistente. + + Verifica se a API retorna um status 404 Not Found e a mensagem + de erro "Plano de entregas não encontrado". + """ response = self.get_plano_entregas( "888888888", @@ -612,7 +621,14 @@ def test_create_pe_duplicate_entrega( id_entrega_1: str, id_entrega_2: str, ): - """Tenta criar um plano de entregas com entregas com id_entrega duplicados""" + """Testa a criação de um Plano de Entregas com entregas duplicadas. + + Verifica se: + - a API retorna um erro 422 Unprocessable Entity quando as entregas + possuem o mesmo id_entrega; e + - se retorna um status 201 Created quando as entregas possuem ids + diferentes. + """ input_pe = self.input_pe.copy() input_pe["id_plano_entregas"] = id_plano_entregas @@ -633,12 +649,18 @@ def test_create_pe_duplicate_entrega( def test_create_pe_duplicate_id_plano( self, truncate_pe, # pylint: disable=unused-argument - input_pe: dict, ): - """Tenta criar um plano de entregas duplicado. O envio do mesmo - plano de entregas pela segunda vez deve substituir o primeiro. + """Testa o envio, mais de uma vez, de Planos de Entregas com o + mesmo id_plano_entregas. + + Verifica se a API: + - retorna um status 201 Created quando o Plano de Entregas é criado + pela primeira vez; e + - um status 200 OK quando o mesmo Plano de Entregas é enviado + novamente, substituindo o anterior. """ + input_pe = self.input_pe.copy() response = self.create_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_201_CREATED @@ -650,14 +672,18 @@ def test_create_pe_duplicate_id_plano( def test_create_pe_same_id_plano_different_instituidora( self, truncate_pe, # pylint: disable=unused-argument - input_pe: dict, user2_credentials: dict, header_usr_2: dict, ): - """Tenta criar um plano de entregas duplicado. O envio do mesmo - plano de entregas pela segunda vez deve substituir o primeiro. + """Testa a criação de Planos de Entregas com o mesmo + id_plano_entregas, mas com diferentes unidades autorizadoras. + + Uma vez que tratam-se de unidades autorizadoras diferentes, a API + deve considerá-los como Planos de Entrega diferentes. Por isso, + deve retornar o status 201 Created em ambos os casos. """ + input_pe = self.input_pe.copy() response = self.create_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_201_CREATED From 84eeef7792496dfd7610567f2507981a484d2696 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 16:30:15 -0300 Subject: [PATCH 17/27] Improve upon docstrings --- tests/plano_entregas/core_test.py | 40 ++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 9673bc8..c413b1b 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -192,7 +192,12 @@ class TestCreatePlanoEntrega(BasePETest): """Testes para a criação de um novo Plano de Entregas.""" def test_create_plano_entregas_completo(self): - """Tenta criar um novo Plano de Entregas.""" + """Testa a criação de um Plano de Entregas completo. + + Verifica se a API retorna um status 201 Created quando um novo Plano de Entregas + é criado com sucesso, se a resposta não contém uma mensagem de erro e se o + Plano de Entregas criado é igual ao Plano de Entregas enviado na requisição. + """ response = self.create_plano_entregas(self.input_pe) assert response.status_code == http_status.HTTP_201_CREATED @@ -201,7 +206,7 @@ def test_create_plano_entregas_completo(self): def test_update_plano_entregas(self, example_pe): # pylint: disable=unused-argument """Tenta criar um novo Plano de Entregas e atualizar alguns campos. - A fixture example_pe cria um novo Plano de Entregas na API. + A fixture example_pe cria um Plano de Entregas de exemplo usando a API. O teste altera um campo do PE e reenvia pra API (update). """ @@ -224,7 +229,11 @@ def test_update_plano_entregas(self, example_pe): # pylint: disable=unused-argu @pytest.mark.parametrize("omitted_fields", enumerate(FIELDS_ENTREGA["optional"])) def test_create_plano_entregas_entrega_omit_optional_fields(self, omitted_fields): - """Tenta criar um novo Plano de Entregas omitindo campos opcionais.""" + """Tenta criar um novo Plano de Entregas omitindo campos opcionais. + + Verifica se a API retorna um status 201 Created, o que indica ter sido + criado com sucesso. + """ input_pe = self.input_pe.copy() offset, field_list = omitted_fields @@ -240,7 +249,11 @@ def test_create_plano_entregas_entrega_omit_optional_fields(self, omitted_fields @pytest.mark.parametrize("nulled_fields", enumerate(FIELDS_ENTREGA["optional"])) def test_create_plano_entregas_entrega_null_optional_fields(self, nulled_fields): - """Tenta criar um novo Plano de Entregas com o valor null nos campos opcionais.""" + """Tenta criar um novo Plano de Entregas, preenchendo com o valor null + os campos opcionais. + + Verifica se a API retorna um status 201 Created, o que indica ter sido + criado com sucesso.""" input_pe = self.input_pe.copy() offset, field_list = nulled_fields @@ -261,6 +274,9 @@ def test_create_plano_entregas_missing_mandatory_fields(self, missing_fields): """Tenta criar um Plano de Entregas, faltando campos obrigatórios. Na atualização com PUT, ainda assim é necessário informar todos os campos obrigatórios, uma vez que o conteúdo será substituído. + + Verifica se a API retorna um status 422 Unprocessable Entity, o que + indica que a entrada foi rejeitada, conforme o esperado. """ offset, field_list = missing_fields @@ -287,10 +303,22 @@ def test_create_plano_entregas_missing_mandatory_fields(self, missing_fields): assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY def test_create_huge_plano_entregas(self): - """Testa a criação de um Plano de Entregas com grande volume de dados.""" + """Testa a criação de um Plano de Entregas com grande volume de dados. + Os campos que aceitam entrada livre de texto são preenchidos com textos + longos. + """ + input_pe = self.input_pe.copy() - def create_huge_entrega(id_entrega: int): + def create_huge_entrega(id_entrega: int) -> dict: + """Cria uma Entrega que ocupa bastante espaço de dados. + + Args: + id_entrega (int): o id da Entrega. + + Returns: + dict: os dados da Entrega. + """ new_entrega = input_pe["entregas"][0].copy() new_entrega["id_entrega"] = str(3 + id_entrega) new_entrega["nome_entrega"] = "x" * 300 # 300 caracteres From 2ba0b053057c96344ce453b47b8da1349d274a3b Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 16:31:14 -0300 Subject: [PATCH 18/27] Remove unused import --- tests/plano_entregas/core_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index c413b1b..4318472 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -9,7 +9,7 @@ import pytest -from util import over_a_year, assert_error_message +from util import assert_error_message # constantes From 44f59a41e00c5f74f82a4545b3cc934678137d50 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 16:42:46 -0300 Subject: [PATCH 19/27] Refactor basic dates tests into a new class --- tests/plano_entregas/date_validation_test.py | 202 +++++++++---------- 1 file changed, 92 insertions(+), 110 deletions(-) diff --git a/tests/plano_entregas/date_validation_test.py b/tests/plano_entregas/date_validation_test.py index ce990c5..bfdbbbd 100644 --- a/tests/plano_entregas/date_validation_test.py +++ b/tests/plano_entregas/date_validation_test.py @@ -16,129 +16,111 @@ # Datas básicas -@pytest.mark.parametrize( - "data_inicio, data_termino", - [ - ("2023-01-01", "2023-06-30"), # igual ao exemplo - ("2023-01-01", "2024-01-01"), # um ano - ("2023-01-01", "2024-01-02"), # mais que um ano - ], -) -def test_create_plano_entregas_date_interval_over_a_year( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - data_inicio: str, - data_termino: str, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Plano de Entregas não pode ter vigência superior a um ano.""" - input_pe["data_inicio"] = data_inicio - input_pe["data_termino"] = data_termino +class TestPlanoDeDatasBasicas(BasePETest): + """Testes de Plano de Entregas com datas básicas.""" - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, + @pytest.mark.parametrize( + "data_inicio, data_termino", + [ + ("2023-01-01", "2023-06-30"), # igual ao exemplo + ("2023-01-01", "2024-01-01"), # um ano + ("2023-01-01", "2024-01-02"), # mais que um ano + ], ) - - if ( - over_a_year( - date.fromisoformat(data_termino), - date.fromisoformat(data_inicio), - ) - == 1 + def test_create_plano_entregas_date_interval_over_a_year( + self, + truncate_pe, # pylint: disable=unused-argument + data_inicio: str, + data_termino: str, ): - assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - detail_message = "Plano de entregas não pode abranger período maior que 1 ano." - assert any( - f"Value error, {detail_message}" in error["msg"] - for error in response.json().get("detail") - ) - else: - assert response.status_code == http_status.HTTP_201_CREATED - BasePETest.assert_equal_plano_entregas(response.json(), input_pe) + """Plano de Entregas não pode ter vigência superior a um ano.""" + input_pe = self.input_pe.copy() + input_pe["data_inicio"] = data_inicio + input_pe["data_termino"] = data_termino -@pytest.mark.parametrize( - "data_inicio, data_termino", - [ - ("2020-06-04", "2020-04-01"), - ], -) -def test_create_pe_invalid_period( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - data_inicio: str, - data_termino: str, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um plano de entregas com datas trocadas""" + response = self.create_plano_entregas(input_pe) - input_pe["data_inicio"] = data_inicio - input_pe["data_termino"] = data_termino + if ( + over_a_year( + date.fromisoformat(data_termino), date.fromisoformat(data_inicio) + ) + == 1 + ): + assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY + detail_message = ( + "Plano de entregas não pode abranger período maior que 1 ano." + ) + assert any( + f"Value error, {detail_message}" in error["msg"] + for error in response.json().get("detail") + ) + else: + assert response.status_code == http_status.HTTP_201_CREATED + self.assert_equal_plano_entregas(response.json(), input_pe) - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, + @pytest.mark.parametrize( + "data_inicio, data_termino", + [ + ("2020-06-04", "2020-04-01"), + ], ) - if data_inicio > data_termino: - assert response.status_code == 422 - detail_message = "data_termino deve ser maior ou igual que data_inicio." - assert any( - f"Value error, {detail_message}" in error["msg"] - for error in response.json().get("detail") - ) - else: - assert response.status_code == http_status.HTTP_201_CREATED - + def test_create_pe_invalid_period( + self, + truncate_pe, # pylint: disable=unused-argument + data_inicio: str, + data_termino: str, + ): + """Tenta criar um plano de entregas com datas trocadas""" -@pytest.mark.parametrize( - "id_plano_entregas, data_inicio, data_avaliacao", - [ - ("77", "2020-06-04", "2020-04-01"), - ("78", "2020-06-04", "2020-06-11"), - ], -) -def test_create_pe_invalid_data_avaliacao( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - data_inicio: str, - data_avaliacao: str, - id_plano_entregas: str, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um Plano de Entregas com datas de avaliação inferior a - data de inicio do plano.""" + input_pe = self.input_pe.copy() + input_pe["data_inicio"] = data_inicio + input_pe["data_termino"] = data_termino - input_pe["data_inicio"] = data_inicio - input_pe["data_avaliacao"] = data_avaliacao - input_pe["id_plano_entregas"] = id_plano_entregas + response = self.create_plano_entregas(input_pe) + if data_inicio > data_termino: + assert response.status_code == 422 + detail_message = "data_termino deve ser maior ou igual que data_inicio." + assert any( + f"Value error, {detail_message}" in error["msg"] + for error in response.json().get("detail") + ) + else: + assert response.status_code == http_status.HTTP_201_CREATED - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{id_plano_entregas}", - json=input_pe, - headers=header_usr_1, + @pytest.mark.parametrize( + "id_plano_entregas, data_inicio, data_avaliacao", + [ + ("77", "2020-06-04", "2020-04-01"), + ("78", "2020-06-04", "2020-06-11"), + ], ) + def test_create_pe_invalid_data_avaliacao( + self, + truncate_pe, # pylint: disable=unused-argument + data_inicio: str, + data_avaliacao: str, + id_plano_entregas: str, + ): + """Tenta criar um Plano de Entregas com datas de avaliação inferior a + data de inicio do plano.""" - if data_avaliacao < data_inicio: - assert response.status_code == 422 - detail_message = "data_avaliacao deve ser maior ou igual à data_inicio." - assert any( - f"Value error, {detail_message}" in error["msg"] - for error in response.json().get("detail") - ) - else: - assert response.status_code == http_status.HTTP_201_CREATED + input_pe = self.input_pe.copy() + input_pe["data_inicio"] = data_inicio + input_pe["data_avaliacao"] = data_avaliacao + input_pe["id_plano_entregas"] = id_plano_entregas + + response = self.create_plano_entregas(input_pe) + + if data_avaliacao < data_inicio: + assert response.status_code == 422 + detail_message = "data_avaliacao deve ser maior ou igual à data_inicio." + assert any( + f"Value error, {detail_message}" in error["msg"] + for error in response.json().get("detail") + ) + else: + assert response.status_code == http_status.HTTP_201_CREATED # Entregas From 870394932f5e9bdf1bcfa21b807b79206cf82b37 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 16:58:21 -0300 Subject: [PATCH 20/27] Refactor into classes date tests for P.E. --- tests/plano_entregas/date_validation_test.py | 241 +++++++++---------- 1 file changed, 114 insertions(+), 127 deletions(-) diff --git a/tests/plano_entregas/date_validation_test.py b/tests/plano_entregas/date_validation_test.py index bfdbbbd..0562a44 100644 --- a/tests/plano_entregas/date_validation_test.py +++ b/tests/plano_entregas/date_validation_test.py @@ -126,139 +126,126 @@ def test_create_pe_invalid_data_avaliacao( # Entregas -@pytest.mark.parametrize( - "id_plano_entregas, data_inicio, data_termino, data_entrega", - [ - ("91", "2023-08-01", "2023-09-01", "2023-08-08"), # dentro - ("92", "2023-08-01", "2023-09-01", "2023-07-01"), # antes do início - ("93", "2023-08-01", "2023-09-01", "2023-10-01"), # depois do fim - ], -) -def test_create_data_entrega_out_of_bounds( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - id_plano_entregas: str, - data_inicio: str, - data_termino: str, - data_entrega: str, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar uma entrega com data de entrega dentro e fora do - intervalo do plano de entregas. Segundo as regras de negócio, essa - data pode ser qualquer data e não precisa estar dentro do período - entre o início e o fim do plano_entregas. - """ - input_pe["id_plano_entregas"] = id_plano_entregas - input_pe["data_inicio"] = data_inicio - input_pe["data_termino"] = data_termino - for entrega in input_pe["entregas"]: - entrega["data_entrega"] = data_entrega +class TestPlanoDeDatasEntregas(BasePETest): + """Testes de Plano de Entregas com datas de entregas.""" - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{id_plano_entregas}", - json=input_pe, - headers=header_usr_1, + @pytest.mark.parametrize( + "id_plano_entregas, data_inicio, data_termino, data_entrega", + [ + ("91", "2023-08-01", "2023-09-01", "2023-08-08"), # dentro + ("92", "2023-08-01", "2023-09-01", "2023-07-01"), # antes do início + ("93", "2023-08-01", "2023-09-01", "2023-10-01"), # depois do fim + ], ) - # Aceitar em todos os casos - assert response.status_code == http_status.HTTP_201_CREATED - - -@pytest.mark.parametrize( - "id_plano_entregas, cod_unidade_executora, data_inicio, data_termino, status", - [ - ("11", 99, "2023-01-01", "2023-06-30", 4), # igual ao exemplo - ("12", 99, "2024-01-01", "2024-06-30", 4), # sem sobreposição - ("13", 99, "2022-12-01", "2023-01-31", 4), # sobreposição no início - ("14", 99, "2023-12-01", "2024-01-31", 4), # sobreposição no fim - ("15", 99, "2023-02-01", "2023-05-31", 4), # contido no período - ("16", 99, "2022-12-01", "2024-01-31", 4), # contém o período - ("17", 100, "2023-02-01", "2023-05-31", 4), # outra unidade - # sobreposição porém um é cancelado - ("18", 99, "2022-12-01", "2023-01-31", 1), - ], -) -def test_create_plano_entregas_overlapping_date_interval( - truncate_pe, # pylint: disable=unused-argument - example_pe, # pylint: disable=unused-argument - input_pe: dict, - id_plano_entregas: str, - cod_unidade_executora: int, - data_inicio: str, - data_termino: str, - status: int, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um plano de entregas cujas entregas têm sobreposição - de intervalo de data na mesma unidade. + def test_create_data_entrega_out_of_bounds( + self, + truncate_pe, # pylint: disable=unused-argument + id_plano_entregas: str, + data_inicio: str, + data_termino: str, + data_entrega: str, + ): + """Tenta criar uma entrega com data de entrega dentro e fora do + intervalo do plano de entregas. Segundo as regras de negócio, essa + data pode ser qualquer data e não precisa estar dentro do período + entre o início e o fim do plano_entregas. + """ + input_pe = self.input_pe.copy() + input_pe["id_plano_entregas"] = id_plano_entregas + input_pe["data_inicio"] = data_inicio + input_pe["data_termino"] = data_termino + for entrega in input_pe["entregas"]: + entrega["data_entrega"] = data_entrega - O Plano de Entregas original é criado e então é testada a criação de - cada novo Plano de Entregas, com sobreposição ou não das datas, - conforme especificado nos parâmetros de teste. - """ - original_pe = input_pe.copy() - input_pe2 = original_pe.copy() - input_pe2["id_plano_entregas"] = "2" - input_pe2["data_inicio"] = "2023-07-01" - input_pe2["data_termino"] = "2023-12-31" - for entrega in input_pe2["entregas"]: - entrega["data_entrega"] = "2023-12-31" - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe2['id_plano_entregas']}", - json=input_pe2, - headers=header_usr_1, - ) - assert response.status_code == http_status.HTTP_201_CREATED + response = self.create_plano_entregas(input_pe) + # Aceitar em todos os casos + assert response.status_code == http_status.HTTP_201_CREATED - input_pe["id_plano_entregas"] = id_plano_entregas - input_pe["cod_unidade_executora"] = cod_unidade_executora - input_pe["data_inicio"] = data_inicio - input_pe["data_termino"] = data_termino - input_pe["status"] = status - for entrega in input_pe["entregas"]: - entrega["data_entrega"] = data_termino - input_pe["avaliacao"] = None - input_pe["data_avaliacao"] = None - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_usr_1, + @pytest.mark.parametrize( + "id_plano_entregas, cod_unidade_executora, data_inicio, data_termino, status", + [ + ("11", 99, "2023-01-01", "2023-06-30", 4), # igual ao exemplo + ("12", 99, "2024-01-01", "2024-06-30", 4), # sem sobreposição + ("13", 99, "2022-12-01", "2023-01-31", 4), # sobreposição no início + ("14", 99, "2023-12-01", "2024-01-31", 4), # sobreposição no fim + ("15", 99, "2023-02-01", "2023-05-31", 4), # contido no período + ("16", 99, "2022-12-01", "2024-01-31", 4), # contém o período + ("17", 100, "2023-02-01", "2023-05-31", 4), # outra unidade + # sobreposição porém um é cancelado + ("18", 99, "2022-12-01", "2023-01-31", 1), + ], ) - if ( - # se algum dos planos estiver cancelado, não há problema em haver - # sobreposição - input_pe["status"] == 1 - # se são unidades diferentes, não há problema em haver sobreposição - or input_pe["cod_unidade_executora"] != original_pe["cod_unidade_executora"] + def test_create_plano_entregas_overlapping_date_interval( + self, + truncate_pe, # pylint: disable=unused-argument + example_pe, # pylint: disable=unused-argument + id_plano_entregas: str, + cod_unidade_executora: int, + data_inicio: str, + data_termino: str, + status: int, ): - # um dos planos está cancelado, pode ser criado + """Tenta criar um plano de entregas cujas entregas têm sobreposição + de intervalo de data na mesma unidade. + + O Plano de Entregas original é criado e então é testada a criação de + cada novo Plano de Entregas, com sobreposição ou não das datas, + conforme especificado nos parâmetros de teste. + """ + original_pe = self.input_pe.copy() + input_pe2 = original_pe.copy() + input_pe2["id_plano_entregas"] = "2" + input_pe2["data_inicio"] = "2023-07-01" + input_pe2["data_termino"] = "2023-12-31" + for entrega in input_pe2["entregas"]: + entrega["data_entrega"] = "2023-12-31" + response = self.create_plano_entregas( + input_pe2, + cod_unidade_autorizadora=self.user1_credentials["cod_unidade_autorizadora"], + id_plano_entregas=input_pe2["id_plano_entregas"], + ) assert response.status_code == http_status.HTTP_201_CREATED - BasePETest.assert_equal_plano_entregas(response.json(), input_pe) - else: - if any( - ( - date.fromisoformat(input_pe["data_inicio"]) - < date.fromisoformat(existing_pe["data_termino"]) - ) - and ( - date.fromisoformat(input_pe["data_termino"]) - > date.fromisoformat(existing_pe["data_inicio"]) - ) - for existing_pe in (original_pe, input_pe2) + + input_pe = original_pe.copy() + input_pe["id_plano_entregas"] = id_plano_entregas + input_pe["cod_unidade_executora"] = cod_unidade_executora + input_pe["data_inicio"] = data_inicio + input_pe["data_termino"] = data_termino + input_pe["status"] = status + for entrega in input_pe["entregas"]: + entrega["data_entrega"] = data_termino + input_pe["avaliacao"] = None + input_pe["data_avaliacao"] = None + response = self.create_plano_entregas(input_pe) + if ( + # se algum dos planos estiver cancelado, não há problema em haver + # sobreposição + input_pe["status"] == 1 + # se são unidades diferentes, não há problema em haver sobreposição + or input_pe["cod_unidade_executora"] != original_pe["cod_unidade_executora"] ): - assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY - detail_msg = ( - "Já existe um plano de entregas para este " - "cod_unidade_executora no período informado." - ) - assert response.json().get("detail", None) == detail_msg - else: - # não há sobreposição de datas + # um dos planos está cancelado, pode ser criado assert response.status_code == http_status.HTTP_201_CREATED - BasePETest.assert_equal_plano_entregas(response.json(), input_pe) + self.assert_equal_plano_entregas(response.json(), input_pe) + else: + if any( + ( + date.fromisoformat(input_pe["data_inicio"]) + < date.fromisoformat(existing_pe["data_termino"]) + ) + and ( + date.fromisoformat(input_pe["data_termino"]) + > date.fromisoformat(existing_pe["data_inicio"]) + ) + for existing_pe in (original_pe, input_pe2) + ): + assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY + detail_msg = ( + "Já existe um plano de entregas para este " + "cod_unidade_executora no período informado." + ) + assert response.json().get("detail", None) == detail_msg + else: + # não há sobreposição de datas + assert response.status_code == http_status.HTTP_201_CREATED + self.assert_equal_plano_entregas(response.json(), input_pe) From 5bb0946a2867aa3a7974234fcfd655b299ab234c Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 17:02:32 -0300 Subject: [PATCH 21/27] Remove unused import --- tests/plano_entregas/date_validation_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/plano_entregas/date_validation_test.py b/tests/plano_entregas/date_validation_test.py index 0562a44..d3a1932 100644 --- a/tests/plano_entregas/date_validation_test.py +++ b/tests/plano_entregas/date_validation_test.py @@ -4,7 +4,6 @@ from datetime import date -from httpx import Client from fastapi import status as http_status import pytest From 803aa327478b1f590fdfe3d0e6c4edb489e4c8eb Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 17:16:53 -0300 Subject: [PATCH 22/27] Refactor into classes permissions tests for P.E. --- tests/plano_entregas/permissions_test.py | 99 ++++++++++++------------ 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/tests/plano_entregas/permissions_test.py b/tests/plano_entregas/permissions_test.py index 8e4dd3a..46e56ac 100644 --- a/tests/plano_entregas/permissions_test.py +++ b/tests/plano_entregas/permissions_test.py @@ -2,63 +2,64 @@ Entregas. """ -from httpx import Client from fastapi import status as http_status from .core_test import BasePETest -def test_get_plano_entregas_different_unit( - truncate_pe, # pylint: disable=unused-argument - example_pe_unidade_3, # pylint: disable=unused-argument - header_usr_2: dict, - input_pe, - client: Client, -): - """Tenta buscar um plano de entregas existente em uma unidade diferente, - à qual o usuário não tem acesso.""" +class TestPermissionsGetPE(BasePETest): + """Testes relacionados a permissões e acesso ao Plano de Entregas de diferentes unidades.""" - response = client.get( - f"/organizacao/SIAPE/3" # Sem autorização nesta unidade - f"/plano_entregas/{input_pe['id_plano_entregas']}", - headers=header_usr_2, - ) - assert response.status_code == http_status.HTTP_403_FORBIDDEN + def test_get_plano_entregas_different_unit( + self, + truncate_pe, # pylint: disable=unused-argument + example_pe_unidade_3, # pylint: disable=unused-argument + header_usr_2: dict, + ): + """Tenta buscar um plano de entregas existente em uma unidade diferente, + à qual o usuário não tem acesso. + """ + input_pe = self.input_pe.copy() + response = self.get_plano_entregas( + input_pe["id_plano_entregas"], + 3, # Sem autorização nesta unidade + header_usr=header_usr_2, + ) + assert response.status_code == http_status.HTTP_403_FORBIDDEN + def test_get_plano_entregas_different_unit_admin( + self, + truncate_pe, # pylint: disable=unused-argument + header_admin: dict, + admin_credentials: dict, + ): + """Tenta, como administrador, criar um novo Plano de Entregas + em uma organização diferente da sua própria organização. + """ + input_pe = self.input_pe.copy() + input_pe["cod_unidade_autorizadora"] = 3 # Unidade diferente -def test_get_plano_entregas_different_unit_admin( - truncate_pe, # pylint: disable=unused-argument - input_pe: dict, - header_admin: dict, - admin_credentials: dict, - client: Client, -): - """Tenta, como administrador, criar um novo Plano de Entregas em uma - organização diferente da sua própria organização. - """ - input_pe["cod_unidade_autorizadora"] = 3 # unidade diferente + response = self.client.get( + f"/user/{admin_credentials['username']}", + headers=header_admin, + ) - response = client.get( - f"/user/{admin_credentials['username']}", - headers=header_admin, - ) + # Verifica se o usuário é admin e se está em outra unidade + assert response.status_code == http_status.HTTP_200_OK + admin_data = response.json() + assert ( + admin_data.get("cod_unidade_autorizadora", None) + != input_pe["cod_unidade_autorizadora"] + ) + assert admin_data.get("is_admin", None) is True - # Verifica se o usuário é admin e se está em outra unidade - assert response.status_code == http_status.HTTP_200_OK - admin_data = response.json() - assert ( - admin_data.get("cod_unidade_autorizadora", None) - != input_pe["cod_unidade_autorizadora"] - ) - assert admin_data.get("is_admin", None) is True + response = self.create_plano_entregas( + input_pe, + cod_unidade_autorizadora=input_pe["cod_unidade_autorizadora"], + id_plano_entregas=input_pe["id_plano_entregas"], + header_usr=header_admin, + ) - response = client.put( - f"/organizacao/SIAPE/{input_pe['cod_unidade_autorizadora']}" - f"/plano_entregas/{input_pe['id_plano_entregas']}", - json=input_pe, - headers=header_admin, - ) - - assert response.status_code == http_status.HTTP_201_CREATED - assert response.json().get("detail", None) is None - BasePETest.assert_equal_plano_entregas(response.json(), input_pe) + assert response.status_code == http_status.HTTP_201_CREATED + assert response.json().get("detail", None) is None + self.assert_equal_plano_entregas(response.json(), input_pe) From 4978433226014e563119d5455c0608216e82da72 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 17:18:31 -0300 Subject: [PATCH 23/27] Fix method name --- tests/plano_entregas/permissions_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plano_entregas/permissions_test.py b/tests/plano_entregas/permissions_test.py index 46e56ac..48d9354 100644 --- a/tests/plano_entregas/permissions_test.py +++ b/tests/plano_entregas/permissions_test.py @@ -27,7 +27,7 @@ def test_get_plano_entregas_different_unit( ) assert response.status_code == http_status.HTTP_403_FORBIDDEN - def test_get_plano_entregas_different_unit_admin( + def test_put_plano_entregas_different_unit_admin( self, truncate_pe, # pylint: disable=unused-argument header_admin: dict, From 52b773955fb5e498e3f67b55b5da4b2c23902943 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 17:19:31 -0300 Subject: [PATCH 24/27] Rename class to reflect what it actually does --- tests/plano_entregas/permissions_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plano_entregas/permissions_test.py b/tests/plano_entregas/permissions_test.py index 48d9354..1820487 100644 --- a/tests/plano_entregas/permissions_test.py +++ b/tests/plano_entregas/permissions_test.py @@ -7,7 +7,7 @@ from .core_test import BasePETest -class TestPermissionsGetPE(BasePETest): +class TestPermissionsPE(BasePETest): """Testes relacionados a permissões e acesso ao Plano de Entregas de diferentes unidades.""" def test_get_plano_entregas_different_unit( From d0140a4ea9332d44d3267994d85064a3134ac0e7 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Tue, 13 Aug 2024 17:29:41 -0300 Subject: [PATCH 25/27] Add test for reading a P.E. from a different unit as admin --- tests/plano_entregas/permissions_test.py | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/plano_entregas/permissions_test.py b/tests/plano_entregas/permissions_test.py index 1820487..95813f3 100644 --- a/tests/plano_entregas/permissions_test.py +++ b/tests/plano_entregas/permissions_test.py @@ -27,6 +27,41 @@ def test_get_plano_entregas_different_unit( ) assert response.status_code == http_status.HTTP_403_FORBIDDEN + def test_get_plano_entregas_different_unit_admin( + self, + truncate_pe, # pylint: disable=unused-argument + example_pe_unidade_3, # pylint: disable=unused-argument + header_admin: dict, + admin_credentials: dict, + ): + """Tenta, como administrador, buscar um Plano de Entregas + em uma organização diferente da sua própria organização. + """ + input_pe = self.input_pe.copy() + input_pe["cod_unidade_autorizadora"] = 3 + + response = self.client.get( + f"/user/{admin_credentials['username']}", + headers=header_admin, + ) + + # Verifica se o usuário é admin e se está em outra unidade + assert response.status_code == http_status.HTTP_200_OK + admin_data = response.json() + assert ( + admin_data.get("cod_unidade_autorizadora", None) + != input_pe["cod_unidade_autorizadora"] + ) + assert admin_data.get("is_admin", None) is True + + response = self.get_plano_entregas( + input_pe["id_plano_entregas"], + input_pe["cod_unidade_autorizadora"], + header_usr=header_admin, + ) + + assert response.status_code == http_status.HTTP_200_OK + def test_put_plano_entregas_different_unit_admin( self, truncate_pe, # pylint: disable=unused-argument From b2594b789cacf2969361731c11cd0bbbb6ca04a6 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Fri, 16 Aug 2024 16:59:39 -0300 Subject: [PATCH 26/27] Refactor tests for Participante to use test classes --- tests/participantes_test.py | 1064 +++++++++++++++++------------------ 1 file changed, 528 insertions(+), 536 deletions(-) diff --git a/tests/participantes_test.py b/tests/participantes_test.py index cb396c2..33fe7bf 100644 --- a/tests/participantes_test.py +++ b/tests/participantes_test.py @@ -6,7 +6,7 @@ from typing import Optional from fastapi import status -from httpx import Client +from httpx import Client, Response import pytest @@ -26,579 +26,571 @@ ), } +# Classe base de testes -# Helper functions +class BaseParticipanteTest: + """Classe base para testes de Participantes.""" -def remove_null_optional_fields(data: dict) -> dict: - """Remove fields that are None from the data.""" - if not isinstance(data, dict): - print(f"data: {data}") - print(f"type: {type(data)}") - raise ValueError("Data must be a dict") - for fields in FIELDS_PARTICIPANTES["optional"]: - for field in fields: - if field in data and data[field] is None: - del data[field] - return data + # pylint: disable=too-many-arguments + @pytest.fixture(autouse=True) + def setup( + self, + truncate_participantes, # pylint: disable=unused-argument + input_part: dict, + user1_credentials: dict, + header_usr_1: dict, + header_usr_2: dict, + header_admin: dict, + admin_credentials: dict, + client: Client, + ): + """Configurar o ambiente de teste. + + Args: + Participantes. + input_part (dict): Dados usados para criar um Participante. + user1_credentials (dict): Credenciais do usuário 1. + header_usr_2 (dict): Cabeçalhos HTTP para o usuário 2. + header_admin (dict): Cabeçalhos HTTP para o usuário admin. + admin_credentials (dict): Credenciais do usuário admin. + client (Client): Uma instância do cliente HTTPX. + """ + # pylint: disable=attribute-defined-outside-init + self.input_part = input_part + self.user1_credentials = user1_credentials + self.header_usr_1 = header_usr_1 + self.header_usr_2 = header_usr_2 + self.header_admin = header_admin + self.admin_credentials = admin_credentials + self.client = client + + @staticmethod + def parse_datetimes(data: dict) -> dict: + """Parse datetimes from the data.""" + if isinstance(data["data_assinatura_tcr"], str): + data["data_assinatura_tcr"] = datetime.fromisoformat( + data["data_assinatura_tcr"] + ) + return data + + @staticmethod + def remove_null_optional_fields(data: dict) -> dict: + """Remove fields that are None from the data.""" + if not isinstance(data, dict): + print(f"data: {data}") + print(f"type: {type(data)}") + raise ValueError("Data must be a dict") + for fields in FIELDS_PARTICIPANTES["optional"]: + for field in fields: + if field in data and data[field] is None: + del data[field] + return data + + @staticmethod + def assert_equal_participante(participante_1: dict, participante_2: dict): + """Verifica a igualdade de dois participantes, considerando + apenas os campos obrigatórios. + """ + assert BaseParticipanteTest.parse_datetimes( + BaseParticipanteTest.remove_null_optional_fields(participante_1.copy()) + ) == BaseParticipanteTest.parse_datetimes( + BaseParticipanteTest.remove_null_optional_fields(participante_2.copy()) + ) + + def create_participante( + self, + input_part: dict, + cod_unidade_autorizadora: Optional[int] = None, + cod_unidade_lotacao: Optional[int] = None, + matricula_siape: Optional[str] = None, + header_usr: Optional[dict] = None, + ) -> Response: + """Criar um Participante. + + Args: + input_part (dict): O dicionário de entrada do Participante. + cod_unidade_autorizadora (int): O ID da unidade autorizadora. + cod_unidade_lotacao (int): O ID da unidade de lotação. + matricula_siape (str): A matrícula SIAPE do Participante. + header_usr (dict): Cabeçalhos HTTP para o usuário. + + Returns: + httpx.Response: A resposta da API. + """ + if cod_unidade_autorizadora is None: + cod_unidade_autorizadora = input_part["cod_unidade_autorizadora"] + if cod_unidade_lotacao is None: + cod_unidade_lotacao = input_part["cod_unidade_lotacao"] + if matricula_siape is None: + matricula_siape = input_part["matricula_siape"] + if header_usr is None: + header_usr = self.header_usr_1 + + response = self.client.put( + ( + f"/organizacao/SIAPE/{cod_unidade_autorizadora}" + f"/{cod_unidade_lotacao}/participante/{matricula_siape}" + ), + json=input_part, + headers=header_usr, + ) + return response + + def get_participante( + self, + matricula_siape: str, + cod_unidade_autorizadora: int, + cod_unidade_lotacao: int, + header_usr: Optional[dict] = None, + ) -> Response: + """Obter um Participante. + + Args: + matricula_siape (str): A matrícula SIAPE do Participante. + cod_unidade_autorizadora (int): O ID da unidade autorizadora. + cod_unidade_lotacao (int): O ID da unidade de lotação. + header_usr (dict): Cabeçalhos HTTP para o usuário. + + Returns: + httpx.Response: A resposta da API. + """ + if header_usr is None: + header_usr = self.header_usr_1 + response = self.client.get( + f"/organizacao/SIAPE/{cod_unidade_autorizadora}" + f"/{cod_unidade_lotacao}" + f"/participante/{matricula_siape}", + headers=header_usr, + ) + return response -def parse_datetimes(data: dict) -> dict: - """Parse datetimes from the data.""" - if isinstance(data["data_assinatura_tcr"], str): - data["data_assinatura_tcr"] = datetime.fromisoformat( - data["data_assinatura_tcr"] +class TestCreateParticipante(BaseParticipanteTest): + """Testes para criação de Participante.""" + + def test_create_participante_complete(self): + """Cria um novo Participante, em uma unidade na qual o usuário + está autorizado, contendo todos os dados necessários. + """ + response = self.create_participante( + self.input_part, ) - return data - - -def assert_equal_participante(participante_1: dict, participante_2: dict): - """Verifica a igualdade de dois participantes, considerando - apenas os campos obrigatórios. - """ - assert parse_datetimes( - remove_null_optional_fields(participante_1.copy()) - ) == parse_datetimes(remove_null_optional_fields(participante_2.copy())) - - -# Os testes usam muitas fixtures, então necessariamente precisam de -# muitos argumentos. Além disso, algumas fixtures não retornam um valor -# para ser usado no teste, mas mesmo assim são executadas quando estão -# presentes como um argumento da função. -# A linha abaixo desabilita os warnings do Pylint sobre isso. -# pylint: disable=too-many-arguments - - -def test_put_participante( - truncate_participantes, # pylint: disable=unused-argument - input_part: dict, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Testa a submissão de um participante a partir do template""" - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{input_part['matricula_siape']}", - json=input_part, - headers=header_usr_1, - ) - assert response.status_code == status.HTTP_201_CREATED - assert response.json().get("detail", None) is None - assert_equal_participante(response.json(), input_part) - - -def test_put_participante_unidade_nao_permitida( - truncate_participantes, # pylint: disable=unused-argument - input_part: dict, - header_usr_2: dict, - client: Client, -): - """ - Testa a submissão de um participante em outra unidade autorizadora - (user não é admin) - """ - response = client.put( - f"/organizacao/SIAPE/3/3/participante/{input_part['cpf']}", - json=input_part, - headers=header_usr_2, - ) + assert response.status_code == status.HTTP_201_CREATED + assert response.json().get("detail", None) is None + self.assert_equal_participante(response.json(), self.input_part) + + def test_create_participante_in_unauthorized_unit(self): + """Tenta submeter um participante em outra unidade autorizadora + (user não é admin) + """ + response = self.create_participante( + self.input_part, + cod_unidade_autorizadora=3, # unidade diferente + header_usr=self.header_usr_2, + ) - assert response.status_code == status.HTTP_403_FORBIDDEN - detail_msg = "Usuário não tem permissão na cod_unidade_autorizadora informada" - assert response.json().get("detail", None) == detail_msg - - -def test_put_participante_outra_unidade_admin( - truncate_participantes, # pylint: disable=unused-argument - input_part: dict, - header_admin: dict, - admin_credentials: dict, - client: Client, -): - """Testa, usando usuário admin, a submissão de um participante em outra - unidade autorizadora - """ - input_part["cod_unidade_autorizadora"] = 3 # unidade diferente - input_part["cod_unidade_lotacao"] = 30 # unidade diferente - - response = client.get( - f"/user/{admin_credentials['username']}", - headers=header_admin, - ) + assert response.status_code == status.HTTP_403_FORBIDDEN + detail_msg = "Usuário não tem permissão na cod_unidade_autorizadora informada" + assert response.json().get("detail", None) == detail_msg - # Verifica se o usuário é admin e se está em outra unidade - assert response.status_code == status.HTTP_200_OK - admin_data = response.json() - assert ( - admin_data.get("cod_unidade_autorizadora", None) - != input_part["cod_unidade_autorizadora"] - ) - assert admin_data.get("is_admin", None) is True - - response = client.put( - f"/organizacao/SIAPE/{input_part['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{input_part['matricula_siape']}", - json=input_part, - headers=header_admin, - ) + def test_create_participante_in_other_unit_as_admin(self): + """Testa, usando usuário admin, a submissão de um participante em outra + unidade autorizadora + """ + self.input_part["cod_unidade_autorizadora"] = 3 # unidade diferente + self.input_part["cod_unidade_lotacao"] = 30 # unidade diferente - assert response.status_code == status.HTTP_201_CREATED - assert response.json().get("detail", None) is None - assert_equal_participante(response.json(), input_part) + response = self.client.get( + f"/user/{self.admin_credentials['username']}", + headers=self.header_admin, + ) + # Verifica se o usuário é admin e se está em outra unidade + assert response.status_code == status.HTTP_200_OK + admin_data = response.json() + assert ( + admin_data.get("cod_unidade_autorizadora", None) + != self.input_part["cod_unidade_autorizadora"] + ) + assert admin_data.get("is_admin", None) is True + + response = self.create_participante( + self.input_part, + header_usr=self.header_admin, + ) + + assert response.status_code == status.HTTP_201_CREATED + assert response.json().get("detail", None) is None + self.assert_equal_participante(response.json(), self.input_part) -@pytest.mark.parametrize( - ( - "cod_unidade_autorizadora_1, cod_unidade_autorizadora_2, " - "cod_unidade_lotacao_1, cod_unidade_lotacao_2, " - "matricula_siape_1, matricula_siape_2" - ), - [ - # mesmas unidades, mesma matrícula SIAPE - (1, 1, 10, 10, "1237654", "1237654"), - # unidades autorizadoras diferentes, mesma matrícula SIAPE - (1, 2, 10, 20, "1237654", "1237654"), - # unidades de lotação diferentes, mesma matrícula SIAPE - (1, 1, 10, 11, "1237654", "1237654"), - # mesma unidade, matrículas diferentes - (1, 1, 10, 10, "1237654", "1230054"), - # unidades diferentes, matrículas diferentes - (1, 2, 10, 20, "1237654", "1230054"), - ], -) -def test_put_duplicate_participante( - truncate_participantes, # pylint: disable=unused-argument - input_part: dict, - cod_unidade_autorizadora_1: int, - cod_unidade_autorizadora_2: int, - cod_unidade_lotacao_1: int, - cod_unidade_lotacao_2: int, - matricula_siape_1: str, - matricula_siape_2: str, - user1_credentials: dict, - header_usr_1: dict, - header_usr_2: dict, - client: Client, -): - """ - Testa o envio de um mesmo participantes com a mesma matrícula SIAPE. - O comportamento do segundo envio será testado conforme o caso. - - Sendo a mesma matrícula na mesma unidade autorizadora e de lotação, - o registro será atualizado e retornará o código HTTP 200 Ok. - Se a unidade e/ou a matrícula forem diferentes, entende-se que será - criado um novo registro e será retornado o código HTTP 201 Created. - """ - input_part["cod_unidade_autorizadora"] = cod_unidade_autorizadora_1 - input_part["cod_unidade_lotacao"] = cod_unidade_lotacao_1 - input_part["matricula_siape"] = matricula_siape_1 - response = client.put( - f"/organizacao/SIAPE/{cod_unidade_autorizadora_1}" - f"/{cod_unidade_lotacao_1}" - f"/participante/{input_part['matricula_siape']}", - json=input_part, - headers=header_usr_1, - ) - assert response.status_code == status.HTTP_201_CREATED - assert response.json().get("detail", None) is None - assert_equal_participante(response.json(), input_part) - - if cod_unidade_autorizadora_2 == user1_credentials["cod_unidade_autorizadora"]: - header_usr = header_usr_1 - else: - header_usr = header_usr_2 - input_part["cod_unidade_autorizadora"] = cod_unidade_autorizadora_2 - input_part["cod_unidade_lotacao"] = cod_unidade_lotacao_2 - input_part["matricula_siape"] = matricula_siape_2 - response = client.put( - f"/organizacao/SIAPE/{cod_unidade_autorizadora_2}" - f"/{cod_unidade_lotacao_2}" - f"/participante/{input_part['matricula_siape']}", - json=input_part, - headers=header_usr, - ) - if ( - (cod_unidade_autorizadora_1 == cod_unidade_autorizadora_2) - and (cod_unidade_lotacao_1 == cod_unidade_lotacao_2) - and (matricula_siape_1 == matricula_siape_2) +class TestUpdateParticipante(BaseParticipanteTest): + """Testes para atualização de um Participante.""" + + def test_update_participante_with_existing_pt( + self, + # pylint: disable=unused-argument + example_part: dict, + example_pt: dict, ): + """Atualiza um participante existente, sendo que o participante já + possui um Plano de Trabalho a ele associado. + """ + input_part = self.input_part.copy() + response = self.create_participante(input_part) assert response.status_code == status.HTTP_200_OK - else: + + def test_update_participante( + self, + ): + """Atualiza um participante existente.""" + input_part = self.input_part.copy() + response = self.create_participante(input_part) assert response.status_code == status.HTTP_201_CREATED - assert response.json().get("detail", None) is None - assert_equal_participante(response.json(), input_part) - - -def test_update_participante_with_existing_pt( - truncate_participantes, # pylint: disable=unused-argument - example_part, # pylint: disable=unused-argument - example_pt, # pylint: disable=unused-argument - input_part: dict, - header_usr_1: dict, - client: Client, -): - """Atualiza um participante existente, sendo que o participante já - possui um Plano de Trabalho a ele associado. - """ - response = client.put( - f"/organizacao/{input_part['origem_unidade']}" - f"/{input_part['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{input_part['matricula_siape']}", - json=input_part, - headers=header_usr_1, - ) - assert response.status_code == status.HTTP_200_OK - - -def test_create_participante_inconsistent( - truncate_participantes, # pylint: disable=unused-argument - input_part: dict, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta submeter participante inconsistente (URL difere do JSON)""" - nova_matricula = "3311776" - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{nova_matricula}", - json=input_part, - headers=header_usr_1, - ) - assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY - detail_msg = "Parâmetro matricula_siape na URL e no JSON devem ser iguais" - assert response.json().get("detail", None) == detail_msg - - -@pytest.mark.parametrize("missing_fields", enumerate(FIELDS_PARTICIPANTES["mandatory"])) -def test_put_participante_missing_mandatory_fields( - truncate_participantes, # pylint: disable=unused-argument - input_part: dict, - missing_fields: list, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta submeter participantes faltando campos obrigatórios""" - matricula_siape = input_part["matricula_siape"] - cod_unidade_lotacao = input_part["cod_unidade_lotacao"] - offset, field_list = missing_fields - for field in field_list: - del input_part[field] - - input_part["matricula_siape"] = ( - f"{1800000 + offset}" # precisa ser um novo participante - ) - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/{cod_unidade_lotacao}" - f"/participante/{matricula_siape}", - json=input_part, - headers=header_usr_1, - ) - assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY - - -def test_get_participante( - truncate_participantes, # pylint: disable=unused-argument - example_part, # pylint: disable=unused-argument - header_usr_1: dict, - input_part: dict, - client: Client, -): - """Tenta ler os dados de um participante pelo cpf.""" - response = client.get( - f"/organizacao/SIAPE/{input_part['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{input_part['matricula_siape']}", - headers=header_usr_1, - ) - assert response.status_code == status.HTTP_200_OK - assert_equal_participante(response.json(), input_part) - - -def test_get_participante_inexistente( - user1_credentials: dict, header_usr_1: dict, client: Client -): - """Tenta consultar um participante que não existe na base de dados.""" - response = client.get( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - "/1" # cod_unidade_lotacao - "/participante/3311776", - headers=header_usr_1, - ) - assert response.status_code == status.HTTP_404_NOT_FOUND - assert response.json().get("detail", None) == "Participante não encontrado" - - -def test_get_participante_different_unit( - truncate_participantes, # pylint: disable=unused-argument - example_part_unidade_3, # pylint: disable=unused-argument - input_part: dict, - header_usr_2: dict, - client: Client, -): - """ - Testa ler um participante em outra unidade autorizadora - (user não é admin) - """ - - input_part["cod_unidade_autorizadora"] = 3 - - response = client.get( - f"/organizacao/SIAPE/{input_part['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{input_part['matricula_siape']}", - headers=header_usr_2, + input_part["modalidade_execucao"] = 2 + response = self.create_participante(input_part) + assert response.status_code == status.HTTP_200_OK + assert response.json()["modalidade_execucao"] == 2 + + @pytest.mark.parametrize( + ( + "cod_unidade_autorizadora_1, cod_unidade_autorizadora_2, " + "cod_unidade_lotacao_1, cod_unidade_lotacao_2, " + "matricula_siape_1, matricula_siape_2" + ), + [ + # mesmas unidades, mesma matrícula SIAPE + (1, 1, 10, 10, "1237654", "1237654"), + # unidades autorizadoras diferentes, mesma matrícula SIAPE + (1, 2, 10, 20, "1237654", "1237654"), + # unidades de lotação diferentes, mesma matrícula SIAPE + (1, 1, 10, 11, "1237654", "1237654"), + # mesma unidade, matrículas diferentes + (1, 1, 10, 10, "1237654", "1230054"), + # unidades diferentes, matrículas diferentes + (1, 2, 10, 20, "1237654", "1230054"), + ], ) + def test_update_participante_duplicate_matricula( + self, + cod_unidade_autorizadora_1: int, + cod_unidade_autorizadora_2: int, + cod_unidade_lotacao_1: int, + cod_unidade_lotacao_2: int, + matricula_siape_1: str, + matricula_siape_2: str, + ): + """ + Testa o envio de um mesmo participante com a mesma matrícula SIAPE. + O comportamento do segundo envio será testado conforme o caso. + + Sendo a mesma matrícula na mesma unidade autorizadora e de lotação, + o registro será atualizado e retornará o código HTTP 200 Ok. + Se a unidade e/ou a matrícula forem diferentes, entende-se que será + criado um novo registro e será retornado o código HTTP 201 Created. + """ + input_part = self.input_part.copy() + input_part["cod_unidade_autorizadora"] = cod_unidade_autorizadora_1 + input_part["cod_unidade_lotacao"] = cod_unidade_lotacao_1 + input_part["matricula_siape"] = matricula_siape_1 + response = self.create_participante( + input_part, + cod_unidade_autorizadora=cod_unidade_autorizadora_1, + cod_unidade_lotacao=cod_unidade_lotacao_1, + matricula_siape=matricula_siape_1, + ) + assert response.status_code == status.HTTP_201_CREATED + assert response.json().get("detail", None) is None + self.assert_equal_participante(response.json(), input_part) + + # ajusta o header para que tenha permissão de escrever naquele + # cod_unidade_autorizadora + if ( + cod_unidade_autorizadora_2 + == self.user1_credentials["cod_unidade_autorizadora"] + ): + header_usr = self.header_usr_1 + else: + header_usr = self.header_usr_2 + input_part["cod_unidade_autorizadora"] = cod_unidade_autorizadora_2 + input_part["cod_unidade_lotacao"] = cod_unidade_lotacao_2 + input_part["matricula_siape"] = matricula_siape_2 + response = self.create_participante( + input_part, + cod_unidade_autorizadora=cod_unidade_autorizadora_2, + cod_unidade_lotacao=cod_unidade_lotacao_2, + matricula_siape=matricula_siape_2, + header_usr=header_usr, + ) - assert response.status_code == status.HTTP_403_FORBIDDEN - detail_msg = "Usuário não tem permissão na cod_unidade_autorizadora informada" - assert response.json().get("detail", None) == detail_msg - - -def test_get_participante_different_unit_admin( - truncate_participantes, # pylint: disable=unused-argument - example_part_unidade_3, # pylint: disable=unused-argument - header_admin: dict, - input_part: dict, - client: Client, -): - """Testa ler um participante em outra unidade autorizadora - (user é admin)""" - - input_part["cod_unidade_autorizadora"] = 3 - - response = client.get( - f"/organizacao/{input_part['origem_unidade']}" - f"/{input_part['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{input_part['matricula_siape']}", - headers=header_admin, + if ( + (cod_unidade_autorizadora_1 == cod_unidade_autorizadora_2) + and (cod_unidade_lotacao_1 == cod_unidade_lotacao_2) + and (matricula_siape_1 == matricula_siape_2) + ): + # tudo é igual, está atualizando o mesmo participante + assert response.status_code == status.HTTP_200_OK + else: + # algo é diferente, está criando um novo participante + assert response.status_code == status.HTTP_201_CREATED + assert response.json().get("detail", None) is None + self.assert_equal_participante(response.json(), input_part) + + +class TestCreateParticipanteInconsistentURLData(BaseParticipanteTest): + """Testa situações em que os dados da URL diferem do informado no JSON.""" + + def test_create_participante_inconsistent( + self, + ): + """Tenta submeter participante inconsistente (URL difere do JSON)""" + nova_matricula = "3311776" + response = self.create_participante( + input_part=self.input_part, + matricula_siape=nova_matricula, + ) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + detail_msg = "Parâmetro matricula_siape na URL e no JSON devem ser iguais" + assert response.json().get("detail", None) == detail_msg + + +class TestCreateParticipanteFieldValidation(BaseParticipanteTest): + """Testes para verificar as validações de campos do Participante.""" + + @pytest.mark.parametrize( + "matricula_siape", + [ + ("12345678"), + ("0000000"), + ("9999999"), + ("123456"), + ("-123456"), + ("abcdefg"), + ], ) - assert response.status_code == status.HTTP_200_OK - assert_equal_participante(response.json(), input_part) - - -@pytest.mark.parametrize( - "matricula_siape", - [ - ("12345678"), - ("0000000"), - ("9999999"), - ("123456"), - ("-123456"), - ("abcdefg"), - ], -) -def test_put_participante_invalid_matricula_siape( - truncate_participantes, # pylint: disable=unused-argument - input_part: dict, - matricula_siape: str, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta submeter um participante com matricula_siape inválida.""" - - input_part["matricula_siape"] = matricula_siape - - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{input_part['matricula_siape']}", - json=input_part, - headers=header_usr_1, + def test_create_participante_invalid_matricula_siape(self, matricula_siape: str): + """Tenta submeter um participante com matricula_siape inválida.""" + input_part = self.input_part.copy() + input_part["matricula_siape"] = matricula_siape + response = self.create_participante( + input_part, + matricula_siape=input_part["matricula_siape"], + ) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + detail_messages = [ + "Matricula SIAPE deve ser numérica.", + "Matrícula SIAPE deve ter 7 dígitos.", + "Matricula SIAPE inválida.", + ] + received_error = response.json().get("detail") + if isinstance(received_error, str): + assert any(message in received_error for message in detail_messages) + else: + assert any( + f"Value error, {message}" in error["msg"] + for message in detail_messages + for error in received_error + ) + + @pytest.mark.parametrize( + "cpf_participante", + [ + ("11111111111"), + ("22222222222"), + ("33333333333"), + ("44444444444"), + ("04811556435"), + ("444444444"), + ("4811556437"), + ], ) - assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY - detail_messages = [ - "Matricula SIAPE deve ser numérica.", - "Matrícula SIAPE deve ter 7 dígitos.", - "Matricula SIAPE inválida.", - ] - received_error = response.json().get("detail") - if isinstance(received_error, str): - assert any(message in received_error for message in detail_messages) - else: + def test_create_participante_invalid_cpf(self, cpf_participante: str): + """Tenta submeter um participante com cpf inválido.""" + input_part = self.input_part.copy() + input_part["cpf"] = cpf_participante + response = self.create_participante(input_part) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + detail_messages = [ + "Dígitos verificadores do CPF inválidos.", + "CPF inválido.", + "CPF precisa ter 11 dígitos.", + "CPF deve conter apenas dígitos.", + ] assert any( f"Value error, {message}" in error["msg"] for message in detail_messages - for error in received_error + for error in response.json().get("detail") ) - -@pytest.mark.parametrize( - "cpf_participante", - [ - ("11111111111"), - ("22222222222"), - ("33333333333"), - ("44444444444"), - ("04811556435"), - ("444444444"), - ("4811556437"), - ], -) -def test_put_participante_invalid_cpf( - truncate_participantes, # pylint: disable=unused-argument - input_part: dict, - cpf_participante: str, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta submeter um participante com cpf inválido.""" - input_part["cpf"] = cpf_participante - - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{input_part['matricula_siape']}", - json=input_part, - headers=header_usr_1, + @pytest.mark.parametrize( + "missing_fields", enumerate(FIELDS_PARTICIPANTES["mandatory"]) ) - assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY - detail_messages = [ - "Dígitos verificadores do CPF inválidos.", - "CPF inválido.", - "CPF precisa ter 11 dígitos.", - "CPF deve conter apenas dígitos.", - ] - assert any( - f"Value error, {message}" in error["msg"] - for message in detail_messages - for error in response.json().get("detail") + def test_create_participante_missing_mandatory_fields(self, missing_fields: list): + """Tenta submeter participantes faltando campos obrigatórios""" + input_part = self.input_part.copy() + cod_unidade_lotacao = input_part["cod_unidade_lotacao"] + matricula_siape = input_part["matricula_siape"] + offset, field_list = missing_fields + for field in field_list: + del input_part[field] + + input_part["matricula_siape"] = ( + f"{1800000 + offset}" # precisa ser um novo participante + ) + response = self.create_participante( + input_part, + cod_unidade_autorizadora=self.user1_credentials["cod_unidade_autorizadora"], + cod_unidade_lotacao=cod_unidade_lotacao, + matricula_siape=matricula_siape, + ) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + + @pytest.mark.parametrize( + "situacao", + [ + (3), + (-1), + ], ) + def test_create_participante_invalid_status(self, situacao: int): + """Tenta criar um participante com flag participante + com valor inválido.""" + input_part = self.input_part.copy() + input_part["situacao"] = situacao + response = self.create_participante(input_part) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + detail_messages = "Valor do campo 'situacao' inválido; permitido: 0, 1" + assert any( + f"Value error, {message}" in error["msg"] + for message in detail_messages + for error in response.json().get("detail") + ) + @pytest.mark.parametrize("modalidade_execucao", [(0), (-1), (6)]) + def test_create_participante_invalid_modalidade_execucao( + self, modalidade_execucao: int + ): + """Tenta submeter um participante com modalidade de execução inválida""" + input_part = self.input_part.copy() + input_part["modalidade_execucao"] = modalidade_execucao + response = self.create_participante(input_part) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + detail_messages = "Modalidade de execução inválida; permitido: 1, 2, 3, 4, 5" + assert any( + f"Value error, {message}" in error["msg"] + for message in detail_messages + for error in response.json().get("detail") + ) -@pytest.mark.parametrize( - "situacao", - [ - (3), - (-1), - ], -) -def test_put_part_invalid_ativo( - truncate_participantes, # pylint: disable=unused-argument - input_part: dict, - situacao: int, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um participante com flag participante - com valor inválido.""" - input_part["situacao"] = situacao - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{input_part['matricula_siape']}", - json=input_part, - headers=header_usr_1, - ) - - assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY - detail_messages = "Valor do campo 'situacao' inválido; permitido: 0, 1" - assert any( - f"Value error, {message}" in error["msg"] - for message in detail_messages - for error in response.json().get("detail") - ) +class TestGetParticipante(BaseParticipanteTest): + """Testes para a leitura de Participantes.""" -@pytest.mark.parametrize("modalidade_execucao", [(0), (-1), (6)]) -def test_put_part_invalid_modalidade_execucao( - truncate_participantes, # pylint: disable=unused-argument - input_part: dict, - modalidade_execucao: int, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta submeter um participante com modalidade de execução inválida""" - input_part["modalidade_execucao"] = modalidade_execucao - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{input_part['matricula_siape']}", - json=input_part, - headers=header_usr_1, - ) + def test_get_participante(self, example_part): # pylint: disable=unused-argument + """Tenta ler os dados de um participante pelo cpf.""" + response = self.get_participante( + matricula_siape=self.input_part["matricula_siape"], + cod_unidade_autorizadora=self.input_part["cod_unidade_autorizadora"], + cod_unidade_lotacao=self.input_part["cod_unidade_lotacao"], + ) + assert response.status_code == status.HTTP_200_OK + self.assert_equal_participante(response.json(), self.input_part) + + def test_get_participante_not_found(self): + """Tenta consultar um participante que não existe na base de dados.""" + response = self.get_participante( + matricula_siape=3311776, + cod_unidade_autorizadora=self.user1_credentials["cod_unidade_autorizadora"], + cod_unidade_lotacao=1, + ) + assert response.status_code == status.HTTP_404_NOT_FOUND + assert response.json().get("detail", None) == "Participante não encontrado" - assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY - detail_messages = "Modalidade de execução inválida; permitido: 1, 2, 3, 4, 5" - assert any( - f"Value error, {message}" in error["msg"] - for message in detail_messages - for error in response.json().get("detail") - ) + def test_get_participante_in_different_unit( + self, example_part_unidade_3: dict # pylint: disable=unused-argument + ): + """Testa ler um participante em outra unidade autorizadora + (usuário não é admin)""" + input_part = self.input_part.copy() + input_part["cod_unidade_autorizadora"] = 3 + + response = self.get_participante( + matricula_siape=input_part["matricula_siape"], + cod_unidade_autorizadora=input_part["cod_unidade_autorizadora"], + cod_unidade_lotacao=input_part["cod_unidade_lotacao"], + header_usr=self.header_usr_2, + ) + assert response.status_code == status.HTTP_403_FORBIDDEN + detail_msg = "Usuário não tem permissão na cod_unidade_autorizadora informada" + assert response.json().get("detail", None) == detail_msg + def test_get_participante_in_different_unit_as_admin( + self, example_part_unidade_3: dict # pylint: disable=unused-argument + ): + """Testa ler um participante em outra unidade autorizadora + (usuário é admin)""" + input_part = self.input_part.copy() + input_part["cod_unidade_autorizadora"] = 3 + + response = self.get_participante( + matricula_siape=input_part["matricula_siape"], + cod_unidade_autorizadora=input_part["cod_unidade_autorizadora"], + cod_unidade_lotacao=input_part["cod_unidade_lotacao"], + header_usr=self.header_admin, + ) + assert response.status_code == status.HTTP_200_OK + self.assert_equal_participante(response.json(), input_part) -def test_put_invalid_data_assinatura_tcr( - truncate_participantes, # pylint: disable=unused-argument - input_part: dict, - user1_credentials: dict, - header_usr_1: dict, - client: Client, -): - """Tenta criar um participante com data futura do TCR.""" - # data de amanhã - input_part["data_assinatura_tcr"] = (date.today() + timedelta(days=1)).isoformat() - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{input_part['matricula_siape']}", - json=input_part, - headers=header_usr_1, - ) - assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY - detail_messages = "Input should be in the past" - assert any( - message in error["msg"] - for message in detail_messages - for error in response.json().get("detail") - ) +class TestCreateParticipanteDateValidation(BaseParticipanteTest): + """Testes de validação de data durante a criação de um Participante.""" + def test_create_participante_invalid_data_assinatura_tcr(self): + """Tenta criar um participante com data futura de assinatura do TCR.""" + input_part = self.input_part.copy() + # data de amanhã + input_part["data_assinatura_tcr"] = ( + date.today() + timedelta(days=1) + ).isoformat() + response = self.create_participante(input_part) -@pytest.mark.parametrize( - "timezone_utc", - [ - -3, # hora de Brasília - -5, # horário de Rio Branco - None, # sem fuso horário (timezone-naïve) - ], -) -def test_put_data_assinatura_tcr_timezone( - truncate_participantes, # pylint: disable=unused-argument - input_part: dict, - user1_credentials: dict, - timezone_utc: Optional[int], - header_usr_1: dict, - client: Client, -): - """Tenta criar um participante com data de assinatura do TCR em - diversos fuso-horários.""" - input_part["data_assinatura_tcr"] = ( - datetime.now( - **({"tz": timezone(timedelta(hours=timezone_utc))} if timezone_utc else {}) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + detail_messages = "Input should be in the past" + assert any( + message in error["msg"] + for message in detail_messages + for error in response.json().get("detail") ) - - timedelta(days=1) - ).isoformat() - response = client.put( - f"/organizacao/SIAPE/{user1_credentials['cod_unidade_autorizadora']}" - f"/{input_part['cod_unidade_lotacao']}" - f"/participante/{input_part['matricula_siape']}", - json=input_part, - headers=header_usr_1, + + @pytest.mark.parametrize( + "timezone_utc", + [ + None, # sem fuso horário (timezone-naïve) + 0, # horário de Greenwich + -3, # hora de Brasília + -5, # horário de Rio Branco + ], ) + def test_create_participante_data_assinatura_tcr_timezone( + self, timezone_utc: Optional[int] + ): + """Tenta criar um participante com data de assinatura do TCR em + diversos fuso-horários (chamado "timezone-aware"), ou sem + definição de fuso-horário (chamado "timezone-naïve").""" + input_part = self.input_part.copy() + input_part["data_assinatura_tcr"] = ( + datetime.now( # horário de agora + **( + {"tz": timezone(timedelta(hours=timezone_utc))} # com tz + if timezone_utc is not None + else {} # sem tz + ) + ) + - timedelta(days=1) + ).isoformat() + response = self.create_participante(input_part) - assert response.status_code == status.HTTP_201_CREATED + assert response.status_code == status.HTTP_201_CREATED From ea2ce991dbe12388adb297eb6b34a4e32c237f21 Mon Sep 17 00:00:00 2001 From: Augusto Herrmann Date: Fri, 16 Aug 2024 17:06:19 -0300 Subject: [PATCH 27/27] Rename methods and improve docstrings --- tests/participantes_test.py | 38 ++++++++-------- tests/plano_entregas/core_test.py | 45 ++++++++++--------- tests/plano_entregas/date_validation_test.py | 12 ++--- tests/plano_entregas/permissions_test.py | 2 +- .../avaliacao_registros_execucao_test.py | 6 +-- tests/plano_trabalho/contribuicoes_test.py | 14 +++--- tests/plano_trabalho/core_test.py | 18 ++++---- tests/plano_trabalho/date_validation_test.py | 14 +++--- tests/plano_trabalho/permissions_test.py | 4 +- 9 files changed, 77 insertions(+), 76 deletions(-) diff --git a/tests/participantes_test.py b/tests/participantes_test.py index 33fe7bf..fca6e05 100644 --- a/tests/participantes_test.py +++ b/tests/participantes_test.py @@ -98,7 +98,7 @@ def assert_equal_participante(participante_1: dict, participante_2: dict): BaseParticipanteTest.remove_null_optional_fields(participante_2.copy()) ) - def create_participante( + def put_participante( self, input_part: dict, cod_unidade_autorizadora: Optional[int] = None, @@ -106,7 +106,7 @@ def create_participante( matricula_siape: Optional[str] = None, header_usr: Optional[dict] = None, ) -> Response: - """Criar um Participante. + """Cria ou atualiza um Participante pela API, usando o verbo PUT. Args: input_part (dict): O dicionário de entrada do Participante. @@ -144,7 +144,7 @@ def get_participante( cod_unidade_lotacao: int, header_usr: Optional[dict] = None, ) -> Response: - """Obter um Participante. + """Obtém um Participante pela API, usando o verbo GET. Args: matricula_siape (str): A matrícula SIAPE do Participante. @@ -173,7 +173,7 @@ def test_create_participante_complete(self): """Cria um novo Participante, em uma unidade na qual o usuário está autorizado, contendo todos os dados necessários. """ - response = self.create_participante( + response = self.put_participante( self.input_part, ) @@ -185,7 +185,7 @@ def test_create_participante_in_unauthorized_unit(self): """Tenta submeter um participante em outra unidade autorizadora (user não é admin) """ - response = self.create_participante( + response = self.put_participante( self.input_part, cod_unidade_autorizadora=3, # unidade diferente header_usr=self.header_usr_2, @@ -216,7 +216,7 @@ def test_create_participante_in_other_unit_as_admin(self): ) assert admin_data.get("is_admin", None) is True - response = self.create_participante( + response = self.put_participante( self.input_part, header_usr=self.header_admin, ) @@ -239,7 +239,7 @@ def test_update_participante_with_existing_pt( possui um Plano de Trabalho a ele associado. """ input_part = self.input_part.copy() - response = self.create_participante(input_part) + response = self.put_participante(input_part) assert response.status_code == status.HTTP_200_OK def test_update_participante( @@ -247,11 +247,11 @@ def test_update_participante( ): """Atualiza um participante existente.""" input_part = self.input_part.copy() - response = self.create_participante(input_part) + response = self.put_participante(input_part) assert response.status_code == status.HTTP_201_CREATED input_part["modalidade_execucao"] = 2 - response = self.create_participante(input_part) + response = self.put_participante(input_part) assert response.status_code == status.HTTP_200_OK assert response.json()["modalidade_execucao"] == 2 @@ -296,7 +296,7 @@ def test_update_participante_duplicate_matricula( input_part["cod_unidade_autorizadora"] = cod_unidade_autorizadora_1 input_part["cod_unidade_lotacao"] = cod_unidade_lotacao_1 input_part["matricula_siape"] = matricula_siape_1 - response = self.create_participante( + response = self.put_participante( input_part, cod_unidade_autorizadora=cod_unidade_autorizadora_1, cod_unidade_lotacao=cod_unidade_lotacao_1, @@ -318,7 +318,7 @@ def test_update_participante_duplicate_matricula( input_part["cod_unidade_autorizadora"] = cod_unidade_autorizadora_2 input_part["cod_unidade_lotacao"] = cod_unidade_lotacao_2 input_part["matricula_siape"] = matricula_siape_2 - response = self.create_participante( + response = self.put_participante( input_part, cod_unidade_autorizadora=cod_unidade_autorizadora_2, cod_unidade_lotacao=cod_unidade_lotacao_2, @@ -348,7 +348,7 @@ def test_create_participante_inconsistent( ): """Tenta submeter participante inconsistente (URL difere do JSON)""" nova_matricula = "3311776" - response = self.create_participante( + response = self.put_participante( input_part=self.input_part, matricula_siape=nova_matricula, ) @@ -375,7 +375,7 @@ def test_create_participante_invalid_matricula_siape(self, matricula_siape: str) """Tenta submeter um participante com matricula_siape inválida.""" input_part = self.input_part.copy() input_part["matricula_siape"] = matricula_siape - response = self.create_participante( + response = self.put_participante( input_part, matricula_siape=input_part["matricula_siape"], ) @@ -411,7 +411,7 @@ def test_create_participante_invalid_cpf(self, cpf_participante: str): """Tenta submeter um participante com cpf inválido.""" input_part = self.input_part.copy() input_part["cpf"] = cpf_participante - response = self.create_participante(input_part) + response = self.put_participante(input_part) assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY detail_messages = [ "Dígitos verificadores do CPF inválidos.", @@ -440,7 +440,7 @@ def test_create_participante_missing_mandatory_fields(self, missing_fields: list input_part["matricula_siape"] = ( f"{1800000 + offset}" # precisa ser um novo participante ) - response = self.create_participante( + response = self.put_participante( input_part, cod_unidade_autorizadora=self.user1_credentials["cod_unidade_autorizadora"], cod_unidade_lotacao=cod_unidade_lotacao, @@ -460,7 +460,7 @@ def test_create_participante_invalid_status(self, situacao: int): com valor inválido.""" input_part = self.input_part.copy() input_part["situacao"] = situacao - response = self.create_participante(input_part) + response = self.put_participante(input_part) assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY detail_messages = "Valor do campo 'situacao' inválido; permitido: 0, 1" assert any( @@ -476,7 +476,7 @@ def test_create_participante_invalid_modalidade_execucao( """Tenta submeter um participante com modalidade de execução inválida""" input_part = self.input_part.copy() input_part["modalidade_execucao"] = modalidade_execucao - response = self.create_participante(input_part) + response = self.put_participante(input_part) assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY detail_messages = "Modalidade de execução inválida; permitido: 1, 2, 3, 4, 5" assert any( @@ -555,7 +555,7 @@ def test_create_participante_invalid_data_assinatura_tcr(self): input_part["data_assinatura_tcr"] = ( date.today() + timedelta(days=1) ).isoformat() - response = self.create_participante(input_part) + response = self.put_participante(input_part) assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY detail_messages = "Input should be in the past" @@ -591,6 +591,6 @@ def test_create_participante_data_assinatura_tcr_timezone( ) - timedelta(days=1) ).isoformat() - response = self.create_participante(input_part) + response = self.put_participante(input_part) assert response.status_code == status.HTTP_201_CREATED diff --git a/tests/plano_entregas/core_test.py b/tests/plano_entregas/core_test.py index 4318472..eb8e4ae 100644 --- a/tests/plano_entregas/core_test.py +++ b/tests/plano_entregas/core_test.py @@ -109,7 +109,7 @@ def assert_equal_plano_entregas(plano_entregas_1: dict, plano_entregas_2: dict): for id_entrega, entrega in second_plan_by_entrega.items() ) - def create_plano_entregas( + def put_plano_entregas( self, input_pe: dict, id_plano_entregas: Optional[str] = None, @@ -117,7 +117,8 @@ def create_plano_entregas( cod_unidade_autorizadora: Optional[int] = None, header_usr: Optional[dict] = None, ) -> Response: - """Criar um Plano de Entregas. + """Cria ou atualiza um Plano de Entregas pela API, usando o método + PUT. Args: input_pe (dict): O dicionário de entrada do Plano de Entregas. @@ -157,7 +158,7 @@ def get_plano_entregas( origem_unidade: Optional[str] = "SIAPE", header_usr: Optional[dict] = None, ) -> Response: - """Obter um Plano de Entregas. + """Obtém um Plano de Entregas pela API, usando o verbo GET. Args: id_plano_entregas (str): O ID do Plano de Entregas. @@ -199,7 +200,7 @@ def test_create_plano_entregas_completo(self): Plano de Entregas criado é igual ao Plano de Entregas enviado na requisição. """ - response = self.create_plano_entregas(self.input_pe) + response = self.put_plano_entregas(self.input_pe) assert response.status_code == http_status.HTTP_201_CREATED assert response.json().get("detail", None) is None self.assert_equal_plano_entregas(response.json(), self.input_pe) @@ -213,7 +214,7 @@ def test_update_plano_entregas(self, example_pe): # pylint: disable=unused-argu input_pe = self.input_pe.copy() input_pe["avaliacao"] = 3 input_pe["data_avaliacao"] = "2023-08-15" - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_200_OK assert response.json()["avaliacao"] == 3 assert response.json()["data_avaliacao"] == "2023-08-15" @@ -243,7 +244,7 @@ def test_create_plano_entregas_entrega_omit_optional_fields(self, omitted_fields del entrega[field] input_pe["id_plano_entregas"] = str(557 + offset) - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_201_CREATED self.assert_equal_plano_entregas(response.json(), input_pe) @@ -263,7 +264,7 @@ def test_create_plano_entregas_entrega_null_optional_fields(self, nulled_fields) entrega[field] = None input_pe["id_plano_entregas"] = str(557 + offset) - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_201_CREATED self.assert_equal_plano_entregas(response.json(), input_pe) @@ -297,7 +298,7 @@ def test_create_plano_entregas_missing_mandatory_fields(self, missing_fields): del input_pe[field] # Act - response = self.create_plano_entregas(input_pe, **placeholder_fields) + response = self.put_plano_entregas(input_pe, **placeholder_fields) # Assert assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY @@ -329,7 +330,7 @@ def create_huge_entrega(id_entrega: int) -> dict: for id_entrega in range(200): input_pe["entregas"].append(create_huge_entrega(id_entrega)) - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_201_CREATED self.assert_equal_plano_entregas(response.json(), input_pe) @@ -380,7 +381,7 @@ def test_create_pe_exceed_string_max_size( "nome_unidade_destinataria" ] = nome_unidade_destinataria # 300 caracteres - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) if any( len(campo) > STR_MAX_SIZE @@ -404,7 +405,7 @@ def test_create_pe_cod_plano_inconsistent( input_pe = self.input_pe.copy() input_pe["id_plano_entregas"] = "110" - response = self.create_plano_entregas( + response = self.put_plano_entregas( input_pe, id_plano_entregas="111" # diferente de 110 ) assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY @@ -420,7 +421,7 @@ def test_create_pe_cod_unidade_inconsistent( input_pe = self.input_pe.copy() original_input_pe = input_pe.copy() input_pe["cod_unidade_autorizadora"] = 999 # era 1 - response = self.create_plano_entregas( + response = self.put_plano_entregas( input_pe, cod_unidade_autorizadora=original_input_pe["cod_unidade_autorizadora"], id_plano_entregas=original_input_pe["id_plano_entregas"], @@ -445,7 +446,7 @@ def test_create_invalid_cod_unidade( input_pe = self.input_pe.copy() input_pe["cod_unidade_executora"] = cod_unidade_executora - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) if cod_unidade_executora > 0: assert response.status_code == http_status.HTTP_201_CREATED @@ -482,7 +483,7 @@ def test_create_entrega_invalid_percent( input_pe["entregas"][1]["meta_entrega"] = meta_entrega input_pe["entregas"][1]["tipo_meta"] = tipo_meta - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) if tipo_meta == "percentual" and (meta_entrega < 0 or meta_entrega > 100): assert response.status_code == http_status.HTTP_422_UNPROCESSABLE_ENTITY @@ -515,7 +516,7 @@ def test_create_entrega_invalid_tipo_meta( input_pe = self.input_pe.copy() input_pe["entregas"][0]["tipo_meta"] = tipo_meta - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) if tipo_meta in ("unidade", "percentual"): assert response.status_code == http_status.HTTP_201_CREATED @@ -537,7 +538,7 @@ def test_create_pe_invalid_avaliacao( input_pe = self.input_pe.copy() input_pe["avaliacao"] = avaliacao - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) if avaliacao in range(1, 6): assert response.status_code == http_status.HTTP_201_CREATED @@ -580,7 +581,7 @@ def test_create_pe_status_avaliado( input_pe["data_avaliacao"] = data_avaliacao input_pe["id_plano_entregas"] = id_plano_entregas - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) if status == 5 and not (avaliacao and data_avaliacao): assert response.status_code == 422 @@ -663,7 +664,7 @@ def test_create_pe_duplicate_entrega( input_pe["entregas"][0]["id_entrega"] = id_entrega_1 input_pe["entregas"][1]["id_entrega"] = id_entrega_2 - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) if id_entrega_1 == id_entrega_2: assert response.status_code == 422 detail_message = "Entregas devem possuir id_entrega diferentes" @@ -689,10 +690,10 @@ def test_create_pe_duplicate_id_plano( """ input_pe = self.input_pe.copy() - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_201_CREATED - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_200_OK assert response.json().get("detail", None) is None self.assert_equal_plano_entregas(response.json(), input_pe) @@ -712,13 +713,13 @@ def test_create_pe_same_id_plano_different_instituidora( """ input_pe = self.input_pe.copy() - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) assert response.status_code == http_status.HTTP_201_CREATED input_pe["cod_unidade_autorizadora"] = user2_credentials[ "cod_unidade_autorizadora" ] - response = self.create_plano_entregas( + response = self.put_plano_entregas( input_pe, cod_unidade_autorizadora=user2_credentials["cod_unidade_autorizadora"], header_usr=header_usr_2, diff --git a/tests/plano_entregas/date_validation_test.py b/tests/plano_entregas/date_validation_test.py index d3a1932..f5b7e9a 100644 --- a/tests/plano_entregas/date_validation_test.py +++ b/tests/plano_entregas/date_validation_test.py @@ -38,7 +38,7 @@ def test_create_plano_entregas_date_interval_over_a_year( input_pe["data_inicio"] = data_inicio input_pe["data_termino"] = data_termino - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) if ( over_a_year( @@ -76,7 +76,7 @@ def test_create_pe_invalid_period( input_pe["data_inicio"] = data_inicio input_pe["data_termino"] = data_termino - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) if data_inicio > data_termino: assert response.status_code == 422 detail_message = "data_termino deve ser maior ou igual que data_inicio." @@ -109,7 +109,7 @@ def test_create_pe_invalid_data_avaliacao( input_pe["data_avaliacao"] = data_avaliacao input_pe["id_plano_entregas"] = id_plano_entregas - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) if data_avaliacao < data_inicio: assert response.status_code == 422 @@ -156,7 +156,7 @@ def test_create_data_entrega_out_of_bounds( for entrega in input_pe["entregas"]: entrega["data_entrega"] = data_entrega - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) # Aceitar em todos os casos assert response.status_code == http_status.HTTP_201_CREATED @@ -198,7 +198,7 @@ def test_create_plano_entregas_overlapping_date_interval( input_pe2["data_termino"] = "2023-12-31" for entrega in input_pe2["entregas"]: entrega["data_entrega"] = "2023-12-31" - response = self.create_plano_entregas( + response = self.put_plano_entregas( input_pe2, cod_unidade_autorizadora=self.user1_credentials["cod_unidade_autorizadora"], id_plano_entregas=input_pe2["id_plano_entregas"], @@ -215,7 +215,7 @@ def test_create_plano_entregas_overlapping_date_interval( entrega["data_entrega"] = data_termino input_pe["avaliacao"] = None input_pe["data_avaliacao"] = None - response = self.create_plano_entregas(input_pe) + response = self.put_plano_entregas(input_pe) if ( # se algum dos planos estiver cancelado, não há problema em haver # sobreposição diff --git a/tests/plano_entregas/permissions_test.py b/tests/plano_entregas/permissions_test.py index 95813f3..af58e75 100644 --- a/tests/plano_entregas/permissions_test.py +++ b/tests/plano_entregas/permissions_test.py @@ -88,7 +88,7 @@ def test_put_plano_entregas_different_unit_admin( ) assert admin_data.get("is_admin", None) is True - response = self.create_plano_entregas( + response = self.put_plano_entregas( input_pe, cod_unidade_autorizadora=input_pe["cod_unidade_autorizadora"], id_plano_entregas=input_pe["id_plano_entregas"], diff --git a/tests/plano_trabalho/avaliacao_registros_execucao_test.py b/tests/plano_trabalho/avaliacao_registros_execucao_test.py index 936e40c..8718e6f 100644 --- a/tests/plano_trabalho/avaliacao_registros_execucao_test.py +++ b/tests/plano_trabalho/avaliacao_registros_execucao_test.py @@ -36,7 +36,7 @@ def test_create_pt_missing_mandatory_fields_avaliacao_registros_execucao( input_pt["avaliacoes_registros_execucao"][0][field] = None input_pt["id_plano_trabalho"] = "111222333" - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY @@ -70,7 +70,7 @@ def test_create_pt_invalid_avaliacao_registros_execucao( "avaliacao_registros_execucao" ] = avaliacao_registros_execucao - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) if avaliacao_registros_execucao in range(1, 6): assert response.status_code == status.HTTP_201_CREATED @@ -208,7 +208,7 @@ def test_create_pt_invalid_avaliacao_registros_execucao_date( "data_avaliacao_registros_execucao" ] = data_avaliacao_registros_execucao - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) if date.fromisoformat(data_avaliacao_registros_execucao) > date.fromisoformat( data_inicio_periodo_avaliativo diff --git a/tests/plano_trabalho/contribuicoes_test.py b/tests/plano_trabalho/contribuicoes_test.py index 24d473b..d3af6c3 100644 --- a/tests/plano_trabalho/contribuicoes_test.py +++ b/tests/plano_trabalho/contribuicoes_test.py @@ -45,7 +45,7 @@ def test_create_pt_missing_mandatory_fields_contribuicoes( "percentual_contribuicao" ] = percentual_contribuicao - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY @@ -70,7 +70,7 @@ def test_create_pt_invalid_tipo_contribuicao( input_pt = self.input_pt.copy() input_pt["contribuicoes"][0]["tipo_contribuicao"] = tipo_contribuicao - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) if tipo_contribuicao in [1, 2, 3]: assert response.status_code == status.HTTP_201_CREATED @@ -105,7 +105,7 @@ def test_create_plano_trabalho_percentual_contribuicao( "percentual_contribuicao" ] = percentual_contribuicao - response = self.create_plano_trabalho(input_pt, header_usr=self.header_usr_1) + response = self.put_plano_trabalho(input_pt, header_usr=self.header_usr_1) if 0 <= percentual_contribuicao <= 100: assert response.status_code == status.HTTP_201_CREATED @@ -142,7 +142,7 @@ def test_create_plano_trabalho_contribuicao_omit_optional_fields( del contribuicao[field] partial_input_pt["id_plano_trabalho"] = str(557 + offset) - response = self.create_plano_trabalho(partial_input_pt) + response = self.put_plano_trabalho(partial_input_pt) assert response.status_code == status.HTTP_201_CREATED @@ -173,7 +173,7 @@ def test_create_plano_trabalho_contribuicao_null_optional_fields( contribuicao[field] = None partial_input_pt["id_plano_trabalho"] = str(557 + offset) - response = self.create_plano_trabalho(partial_input_pt) + response = self.put_plano_trabalho(partial_input_pt) assert response.status_code == status.HTTP_201_CREATED @@ -223,7 +223,7 @@ def test_tipo_contribuicao( contribuicao["tipo_contribuicao"] = tipo_contribuicao contribuicao["id_plano_entregas"] = id_plano_entregas contribuicao["id_entrega"] = id_entrega - response = self.create_plano_trabalho(input_pt, header_usr=self.header_usr_1) + response = self.put_plano_trabalho(input_pt, header_usr=self.header_usr_1) error_messages = [] if tipo_contribuicao == 1: @@ -263,7 +263,7 @@ def test_referencia_entrega_inexistente( contribuicao["id_plano_entregas"] = id_plano_entregas contribuicao["id_entrega"] = id_entrega - response = self.create_plano_trabalho(input_pt, header_usr=self.header_usr_1) + response = self.put_plano_trabalho(input_pt, header_usr=self.header_usr_1) if id_plano_entregas == input_pe["id_plano_entregas"] and \ id_entrega in [entrega["id_entrega"] for entrega in input_pe["entregas"]]: diff --git a/tests/plano_trabalho/core_test.py b/tests/plano_trabalho/core_test.py index a83e5ac..1eb870c 100644 --- a/tests/plano_trabalho/core_test.py +++ b/tests/plano_trabalho/core_test.py @@ -150,7 +150,7 @@ def assert_equal_plano_trabalho(plano_trabalho_1: dict, plano_trabalho_2: dict): ) assert avaliacao_registros_execucao_1 == avaliacao_registros_execucao_2 - def create_plano_trabalho( + def put_plano_trabalho( self, input_pt: dict, id_plano_trabalho: Optional[str] = None, @@ -158,7 +158,7 @@ def create_plano_trabalho( cod_unidade_autorizadora: Optional[int] = None, header_usr: Optional[dict] = None, ) -> Response: - """Criar um Plano de Trabalho. + """Cria ou atualiza um Plano de Trabalho pela API, usando o verbo PUT. Args: input_pt (dict): O dicionário de entrada do Plano de Trabalho. @@ -197,7 +197,7 @@ def get_plano_trabalho( origem_unidade: Optional[str] = "SIAPE", header_usr: Optional[dict] = None, ) -> Response: - """Obter um Plano de Trabalho. + """Obtém um Plano de Trabalho pela API, usando o verbo GET. Args: id_plano_trabalho (str): O ID do Plano de Trabalho. @@ -227,7 +227,7 @@ def test_completo(self): """Cria um novo Plano de Trabalho do Participante, em uma unidade na qual ele está autorizado, contendo todos os dados necessários. """ - response = self.create_plano_trabalho(self.input_pt) + response = self.put_plano_trabalho(self.input_pt) assert response.status_code == status.HTTP_201_CREATED self.assert_equal_plano_trabalho(response.json(), self.input_pt) @@ -270,7 +270,7 @@ def test_create_plano_trabalho_missing_mandatory_fields(self, missing_fields): input_pt["id_plano_trabalho"] = f"{1800 + offset}" # precisa ser um novo plano # Act - response = self.create_plano_trabalho(input_pt, **placeholder_fields) + response = self.put_plano_trabalho(input_pt, **placeholder_fields) # Assert assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY @@ -284,7 +284,7 @@ def test_create_pt_cod_plano_inconsistent(self): input_pt["id_plano_trabalho"] = "110" # Act - response = self.create_plano_trabalho( + response = self.put_plano_trabalho( input_pt, id_plano_trabalho="111", header_usr=self.header_usr_1 ) @@ -310,7 +310,7 @@ def test_create_pt_invalid_carga_horaria_disponivel(self, carga_horaria_disponiv input_pt["carga_horaria_disponivel"] = carga_horaria_disponivel # Act - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) # Assert assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY @@ -356,7 +356,7 @@ def test_put_plano_trabalho_invalid_cpf(self, cpf_participante): input_pt["cpf_participante"] = cpf_participante # Act - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) # Assert assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY @@ -408,7 +408,7 @@ def test_update_plano_trabalho(self): input_pt = self.input_pt.copy() input_pt["status"] = 4 # Valor era 3 input_pt["data_termino"] = "2023-01-31" # Valor era "2023-01-15" - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) assert response.status_code == status.HTTP_200_OK self.assert_equal_plano_trabalho(response.json(), input_pt) diff --git a/tests/plano_trabalho/date_validation_test.py b/tests/plano_trabalho/date_validation_test.py index 93b6201..74cfe04 100644 --- a/tests/plano_trabalho/date_validation_test.py +++ b/tests/plano_trabalho/date_validation_test.py @@ -68,7 +68,7 @@ def test_create_pt_invalid_dates( assert response.status_code in (status.HTTP_200_OK, status.HTTP_201_CREATED) # cria o plano_trabalho com a data_inicio informada - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) if data_inicio > data_termino: assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY detail_message = ( @@ -100,7 +100,7 @@ def test_create_plano_trabalho_date_interval_over_a_year( input_pt["data_inicio"] = data_inicio input_pt["data_termino"] = data_termino - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) if ( over_a_year( @@ -210,7 +210,7 @@ def test_create_plano_trabalho_overlapping_date_interval( "carga_horaria_disponivel": 80, } ] - response = self.create_plano_trabalho(input_pt2) + response = self.put_plano_trabalho(input_pt2) assert response.status_code == status.HTTP_201_CREATED input_pt["id_plano_trabalho"] = id_plano_trabalho @@ -220,7 +220,7 @@ def test_create_plano_trabalho_overlapping_date_interval( input_pt["data_termino"] = data_termino input_pt["status"] = status_pt input_pt["avaliacoes_registros_execucao"] = [] - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) if ( # se algum dos planos estiver cancelado, não há problema em haver @@ -303,7 +303,7 @@ def test_create_pt_invalid_periodo_avaliativo( "data_fim_periodo_avaliativo" ] = data_fim_periodo_avaliativo - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) if date.fromisoformat(data_fim_periodo_avaliativo) < date.fromisoformat( data_inicio_periodo_avaliativo @@ -357,7 +357,7 @@ def test_create_pt_data_avaliacao_out_of_bounds( "data_avaliacao_registros_execucao" ] = data_avaliacao_registros_execucao - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) if date.fromisoformat(data_avaliacao_registros_execucao) < date.fromisoformat( data_inicio_periodo_avaliativo ): @@ -442,7 +442,7 @@ def test_create_plano_trabalho_avaliacao_overlapping_date_interval( avaliacao_template["data_avaliacao_registros_execucao"] = "2024-01-01" input_pt["avaliacoes_registros_execucao"].append(avaliacao_template) - response = self.create_plano_trabalho(input_pt) + response = self.put_plano_trabalho(input_pt) periodo_avaliativo.sort(key=lambda avaliacao: avaliacao[0]) for avaliacao_1, avaliacao_2 in zip( diff --git a/tests/plano_trabalho/permissions_test.py b/tests/plano_trabalho/permissions_test.py index 4e4c271..cfc8f41 100644 --- a/tests/plano_trabalho/permissions_test.py +++ b/tests/plano_trabalho/permissions_test.py @@ -83,7 +83,7 @@ def test_create_plano_trabalho_unidade_nao_permitida(self, header_usr_2: dict): header_usr_2 (dict): Cabeçalho do usuário na unidade diferente. """ # Criar o Plano de Trabalho em uma unidade diferente - response = self.create_plano_trabalho( + response = self.put_plano_trabalho( self.input_pt, cod_unidade_autorizadora=3, header_usr=header_usr_2 ) @@ -128,7 +128,7 @@ def test_create_plano_trabalho_outra_unidade_admin( assert admin_data.get("is_admin", None) is True # Criar o Plano de Trabalho em uma unidade diferente - response = self.create_plano_trabalho( + response = self.put_plano_trabalho( input_pt, cod_unidade_autorizadora=3, header_usr=header_admin )