Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/test-cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
10 changes: 10 additions & 0 deletions features/create_booking.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
25 changes: 25 additions & 0 deletions steps/test_booking_steps.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import pytest
from pydantic import ValidationError
from pytest_bdd import given, parsers, scenarios, then, when

from conftest import Context
Expand Down Expand Up @@ -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:
Expand Down
Loading