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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ Autenticação: `POST /auth` com `{ "username": "admin", "password": "password12
- Cobertura de autenticação, CRUD completo, PUT vs. PATCH, e casos de acesso não autorizado (403).
- Relatório HTML automatizado a cada execução (`reports/report.html`, via `pytest-html`), com a versão da `master` publicada em [thomastds.github.io/qa-api-python](https://thomastds.github.io/qa-api-python/) via GitHub Pages.
- Cobertura de código (`pytest-cov`) de `api/` e `models/` em cada execução, acompanhada no [Codecov](https://codecov.io/gh/ThomasTDS/qa-api-python).
- Limpeza automática: a fixture `context` remove o booking criado no cenário (via token próprio de limpeza) ao final de cada teste, evitando acúmulo de dados na API pública.
- Limpeza automática: a fixture `context` remove o booking criado no cenário (via token próprio de limpeza) ao final de cada teste, evitando acúmulo de dados na API pública. Se a remoção falhar por erro de rede ou de autenticação, o pytest mostra um aviso com o id do booking que ficou para trás, sem mudar o resultado do teste.
- Dados de teste únicos: cada booking criado leva um sufixo aleatório no sobrenome (ex: `Ciclano-3f9a1c`). Como a API pública é compartilhada, inclusive pelas execuções paralelas do CI, a busca por nome encontra só o booking do próprio teste.
- Retry automático só para falhas de rede (`pytest-rerunfailures`, com `--reruns 1` e `only_rerun` no `pyproject.toml`): um teste que falha por erro de conexão ou timeout roda uma segunda vez, amortecendo a instabilidade da API pública de demonstração. Falhas de asserção ou de schema nunca são repetidas, para que um bug intermitente não passe na segunda tentativa.
- Integração contínua via GitHub Actions, em dois jobs: `unit` roda as checagens estáticas e os testes unitários, sem rede, e `integration` só começa se o `unit` passar, rodando a suíte completa contra a API pública. Assim, uma falha no `integration` com o `unit` verde aponta para a API ou para um cenário, e não para o código dos clients. Os dois rodam a cada push e pull request para `master`, em Python 3.12 e 3.13, e também diariamente às 06:00 UTC (ver [.github/workflows/tests.yml](.github/workflows/tests.yml)) para detectar quebras causadas pela própria API pública, com o relatório HTML publicado como artifact do workflow.
- Dependências atualizadas automaticamente pelo Dependabot (pip e GitHub Actions, semanal — ver [.github/dependabot.yml](.github/dependabot.yml)). PRs de patch/minor com CI verde são mergeados automaticamente ([.github/workflows/dependabot-auto-merge.yml](.github/workflows/dependabot-auto-merge.yml)); bumps de major exigem revisão manual.
Expand Down
11 changes: 9 additions & 2 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import json
import os
import warnings
from collections.abc import Generator
from typing import Any

import pytest
import requests
from pydantic import ValidationError

from api.auth_api_client import AuthApiClient
from api.booking_api_client import BookingApiClient
Expand Down Expand Up @@ -53,8 +55,13 @@ def context() -> Generator[Context, None, None]:
try:
cleanup_token = ctx.auth_client.get_valid_token()
ctx.booking_client.delete_booking(ctx.booking_id, cleanup_token)
except Exception:
pass # booking já pode ter sido removido pelo próprio cenário; ignora falha de limpeza
except (requests.RequestException, ValidationError) as error:
# Falha de rede ou de autenticação na limpeza não muda o resultado
# do teste, que já verificou o que precisava, mas deixa o booking
# para trás na API pública. O aviso aparece no resumo do pytest.
# (Se o próprio cenário já removeu o booking, a API só devolve um
# status de erro, sem exceção, e nada é avisado.)
warnings.warn(f"booking {ctx.booking_id} não foi removido na limpeza: {error}", stacklevel=1)

session.close()

Expand Down
6 changes: 5 additions & 1 deletion steps/booking_data.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
from datetime import date
from typing import Any
from uuid import uuid4

from models.booking import Booking, BookingDates


# O sufixo aleatório no sobrenome deixa cada booking identificável na API
# pública, que é compartilhada: a busca por nome encontra só o booking do
# próprio teste, mesmo com outras execuções rodando ao mesmo tempo.
def default_booking() -> Booking:
return Booking(
firstname="Fulano",
lastname="Ciclano",
lastname=f"Ciclano-{uuid4().hex[:6]}",
totalprice=150,
depositpaid=True,
bookingdates=BookingDates(checkin=date(2026, 1, 1), checkout=date(2026, 1, 5)),
Expand Down
Loading