🌗 ← Índice
Data: 14/08/2026
Nível: Intermediário (Mês 2 — POO)
pip install pytest
def somar(a, b):
return a + b
assert somar(2, 3) == 5 # passa silenciosamente
assert somar(2, 3) == 6 # AssertionError
Arquivo test_calculadora.py:
def somar(a, b):
return a + b
def test_somar_positivos():
assert somar(2, 3) == 5
def test_somar_negativos():
assert somar(-1, -1) == -2
pytest # descobre test_*.py e test_*()
pytest -v # verboso
pytest test_calculadora.py # arquivo específico
Regras de descoberta: arquivos `test_*.py` (ou `*_test.py`), funções `test_*`.
import pytest
def dividir(a, b):
if b == 0:
raise ValueError("Divisão por zero não permitida")
return a / b
def test_dividir_por_zero():
with pytest.raises(ValueError, match="Divisão por zero"):
dividir(10, 0)
import pytest
@pytest.fixture
def cliente():
"""Cria um cliente de teste reutilizável."""
return {"nome": "Hugo", "saldo": 1000.0}
def test_saldo_inicial(cliente):
assert cliente["saldo"] == 1000.0
def test_deposito(cliente):
cliente["saldo"] += 500
assert cliente["saldo"] == 1500.0
💡 Cada teste recebe uma **cópia nova** da fixture (isolamento entre testes).
import pytest
def classificar(nota):
if nota >= 7:
return "aprovado"
return "reprovado"
@pytest.mark.parametrize("nota,esperado", [
(10, "aprovado"),
(7, "aprovado"),
(6.9, "reprovado"),
(0, "reprovado"),
])
def test_classificar(nota, esperado):
assert classificar(nota) == esperado
Roda 4 testes a partir de 1 definição — ótimo para tabelas de casos.
projeto/
├── calculadora.py # código
└── test_calculadora.py # testes (mesma pasta, ou tests/)
Separação maior: `src/` + `tests/` com `conftest.py` para fixtures globais.
import pytest
from unittest.mock import patch
def buscar_usuario(cliente_http, id):
resposta = cliente_http.get(f"/usuarios/{id}")
return resposta.json()
def test_buscar_usuario():
classe_fake = type("Resp", (), {"json": lambda self: {"id": 1, "nome": "Ana"}})
cliente_fake = type("Cli", (), {"get": lambda self, url: classe_fake()})
resultado = buscar_usuario(cliente_fake, 1)
assert resultado == {"id": 1, "nome": "Ana"}
💡 `unittest.mock.patch` permite "congelar" funções externas (ex: `requests.get`) — assunto da próxima profundidade.
Escreva testes completos para a classe ClienteGitHub da Aula P15:
Dica: use unittest.mock.patch("requests.Session.get") com MagicMock.
# test_cliente_github.py
import pytest
from unittest.mock import patch, MagicMock
class ClienteGitHub:
def __init__(self, token=None):
import requests
self.sessao = requests.Session()
def buscar_repos(self, query, limite=5):
try:
resposta = self.sessao.get(
"https://api.github.com/search/repositories",
params={"q": query, "per_page": limite},
timeout=10,
)
resposta.raise_for_status()
except Exception:
return []
return resposta.json().get("items", [])
def test_buscar_repos_sucesso():
resposta_fake = MagicMock()
resposta_fake.raise_for_status.return_value = None
resposta_fake.json.return_value = {"items": [{"full_name": "teste/repo"}]}
with patch("requests.Session.get", return_value=resposta_fake):
cliente = ClienteGitHub()
resultado = cliente.buscar_repos("python")
assert len(resultado) == 1
assert resultado[0]["full_name"] == "teste/repo"
def test_buscar_repos_erro_rede():
import requests
with patch("requests.Session.get", side_effect=requests.exceptions.ConnectionError):
cliente = ClienteGitHub()
resultado = cliente.buscar_repos("python")
assert resultado == []
def test_repo_info_campos():
resposta_fake = MagicMock()
resposta_fake.raise_for_status.return_value = None
resposta_fake.json.return_value = {
"full_name": "dono/repo", "description": "desc",
"stargazers_count": 10, "language": "Python", "html_url": "http://x",
}
with patch("requests.Session.get", return_value=resposta_fake):
cliente = ClienteGitHub()
info = cliente.repo_info("dono", "repo")
assert set(info.keys()) == {"nome", "descricao", "estrelas", "linguagem", "url"}
💡 Resultado esperado: 3 passed in 0.1s — testes rápidos, sem rede, sem chave de API.
HB Estudos · ← Voltar ao índice de Python