diff --git a/docs/test-cases.md b/docs/test-cases.md index eb9d67c..58a8faf 100644 --- a/docs/test-cases.md +++ b/docs/test-cases.md @@ -27,6 +27,7 @@ Legenda: | TC-013 | Atualização | Tentar atualizar booking com token inválido (PUT) | Negativo | Alta | Automatizado | [update_booking.feature:17](../features/update_booking.feature#L17) | | TC-014 | Remoção | Tentar remover um booking que não existe | Negativo | Baixa | Automatizado | [delete_booking.feature:16](../features/delete_booking.feature#L16) | | TC-015 | Criação | Tentar criar booking sem um campo obrigatório (bug) | Negativo | Média | Automatizado | [create_booking.feature:13](../features/create_booking.feature#L13) | +| TC-016 | Criação | Criar booking com totalprice em formato inválido | Negativo | Média | Automatizado | [create_booking.feature:24](../features/create_booking.feature#L24) | `BookingApiClient.get_booking_ids` também aceita filtro por `checkin`/`checkout`, mas o TC-006 cobre só `firstname`/`lastname`: o filtro por data na API pública de demonstração é conhecido por ser instável, e testá-lo arriscaria um teste flaky em vez de validar um comportamento real. diff --git a/features/create_booking.feature b/features/create_booking.feature index ef89562..b89fee7 100644 --- a/features/create_booking.feature +++ b/features/create_booking.feature @@ -21,3 +21,13 @@ Feature: Criação de booking Scenario: Tentar criar booking sem um campo obrigatório When ele tenta criar um booking sem informar o firstname Then a resposta deve indicar um erro interno do servidor + + # A API aceita um totalprice em formato errado (texto em vez de número) e + # devolve 200, gravando null no lugar em silêncio, em vez de rejeitar o + # payload. Esse cenário prova que a validação de schema do projeto pega + # essa corrupção: a resposta não bate com o modelo Booking, e o teste + # acusa o problema em vez de aceitar o dado corrompido como válido. + @TC-016 + Scenario: Criar booking com totalprice em formato inválido + When ele cria um booking com totalprice em formato inválido + Then a resposta da API não deve corresponder ao schema esperado diff --git a/pyproject.toml b/pyproject.toml index 6edc503..8fa31a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ markers = [ "TC-013: id do test case, ver docs/test-cases.md", "TC-014: id do test case, ver docs/test-cases.md", "TC-015: id do test case, ver docs/test-cases.md", + "TC-016: id do test case, ver docs/test-cases.md", ] [tool.ruff] diff --git a/steps/test_booking_steps.py b/steps/test_booking_steps.py index 921e1c3..58db32e 100644 --- a/steps/test_booking_steps.py +++ b/steps/test_booking_steps.py @@ -1,3 +1,5 @@ +import pytest +from pydantic import ValidationError from pytest_bdd import given, parsers, scenarios, then, when from conftest import Context @@ -99,6 +101,29 @@ def resposta_indica_erro_interno_do_servidor(context: Context) -> None: assert context.last_response.status_code == 500 +@when("ele cria um booking com totalprice em formato inválido") +def cria_booking_com_totalprice_invalido(context: Context) -> None: + payload = { + "firstname": "Fulano", + "lastname": "Ciclano", + "totalprice": "nao-e-numero", + "depositpaid": True, + "bookingdates": {"checkin": "2026-01-01", "checkout": "2026-01-05"}, + } + context.last_response = context.booking_client.create_booking_raw(payload) + # A resposta não bate com o schema, mas o id criado é válido e precisa + # ser limpo no final do teste como qualquer outro booking. + context.booking_id = context.last_response.json().get("bookingid") + + +@then("a resposta da API não deve corresponder ao schema esperado") +def resposta_nao_corresponde_ao_schema(context: Context) -> None: + assert context.last_response is not None + assert context.last_response.status_code == 200 + with pytest.raises(ValidationError): + CreateBookingResponse.model_validate(context.last_response.json()) + + # CONSULTA @when("ele busca o booking pelo id") def busca_o_booking_pelo_id(context: Context) -> None: