Trilha de aprendizado · Nível 8 · Tutorial 2

Selecionar casos de teste e verificar exceções

Derivar casos de sucesso, limites e falhas a partir do comportamento esperado de uma operação, verificando também as exceções que ela deve produzir.

  • Nível: Intermediário
  • Duração: 18 min
  • 8 passos
Selecionar casos de teste e verificar exceções

O que você vai percorrer

  1. Transformar o contrato em cenários Identifique comportamentos verificáveis diretamente no contrato público de uma operação, sem consultar sua implementação nem acrescentar requisitos. 2 min
  2. Escolher entradas representativas Agrupe entradas pelo comportamento esperado e escolha casos que verifiquem regras distintas sem repetição desnecessária. 2 min
  3. Explorar os valores de fronteira Selecione os limites inclusivos e seus vizinhos imediatos para detectar erros de inclusão ou exclusão na faixa válida. 2 min
  4. Distinguir vazio, unitário e ausente Reconheça diferenças estruturais entre ausência, coleção vazia e listas com diferentes quantidades de elementos, escolhendo casos coerentes com o contrato. 2 min
  5. Definir expectativas independentes do código Transforme cenários de sucesso em testes legíveis, usando resultados literais derivados do contrato da operação. 2 min
  6. Exigir a exceção esperada com pytest.raises Use pytest.raises para fazer um teste passar somente quando a operação produzir o tipo de exceção previsto no contrato. 3 min
  7. Verificar o contexto da exceção Capture a exceção produzida e verifique os atributos públicos que explicam a falha, sem depender de detalhes irrelevantes da mensagem. 2 min
  8. Aplicar e revisar a seleção de testes Revise uma seleção de casos, complete uma pequena suíte local e justifique as verificações acrescentadas. 4 min

O que você vai aprender

  • Selecionar entradas representativas sem repetir casos que exercitam a mesma regra.
  • Incluir valores de fronteira, entradas vazias e valores inválidos quando forem pertinentes.
  • Definir resultados esperados a partir das regras da operação, sem reproduzir seu algoritmo no teste.
  • Verificar o tipo de uma exceção e, quando necessário, seus atributos de contexto com pytest.raises.

Antes de começar

  • Escrever e executar testes de funções com pytest
  • Documentar funções com docstrings e tipos simples
  • Tratar exceções com try, except, else e finally
  • Criar exceções para erros do domínio

Passo 1 de 8

Transformar o contrato em cenários

Identifique comportamentos verificáveis diretamente no contrato público de uma operação, sem consultar sua implementação nem acrescentar requisitos.

Comece pelo contrato público

O que deve orientar os testes?

Antes de escolher entradas ou consultar a implementação, leia o contrato público da operação. Ele informa quais entradas são aceitas, qual resultado é prometido e quais falhas são esperadas.

Cada regra explícita pode ser convertida em um cenário verificável. Já uma preferência pessoal ou uma possibilidade não documentada não deve virar exigência do teste.

Exemplo

Contrato do caso-guia

A função calcular_media é pura: recebe uma lista não vazia de pontuações inteiras entre 0 e 100, com os dois limites aceitos, e devolve a média.

Rejeições documentadas:

  • lista vazia → ValueError;
  • None → TypeError;
  • pontuação fora da faixa → PontuacaoInvalida, com os atributos públicos valor, minimo e maximo.

Dica

Primeiro identifique; depois escolha

Neste momento, registre os comportamentos que precisam ser verificados. A escolha das entradas representativas será feita nos próximos steps.

Monte uma matriz de cenários

Regra, condição e expectativa

Uma matriz de cenários liga três elementos: a regra pública, a condição da entrada e o comportamento esperado. Para o caso-guia, ela deve incluir o cálculo bem-sucedido e cada forma de rejeição documentada.

Não acrescente, por exemplo, uma regra de arredondamento ou uma ordem específica entre validações se o contrato não garante esses comportamentos.

Do contrato aos cenários verificáveis

O contrato é a origem comum dos cenários de sucesso e de falha. Cada ramificação representa uma promessa pública diferente, não um caminho interno do código.

Diagrama em que um documento de contrato se ramifica para um resultado de média e para três falhas esperadas: lista vazia, valor None e pontuação fora da faixa.

Uma regra documentada sustenta cada cenário; suposições ficam fora da matriz.

Exemplo

Matriz inicial

  • Lista não vazia com pontuações inteiras de 0 a 100 → devolve a média.
  • Lista vazia → produz ValueError.
  • Entrada None → produz TypeError.
  • Alguma pontuação fora de 0 a 100 → produz PontuacaoInvalida com contexto público.

“Devolve sempre duas casas decimais” não entra na matriz, pois essa promessa não aparece no contrato.

Relacione regras e comportamentos

Complete a matriz

Associe cada condição de entrada ao comportamento público esperado.

Toque em um item e depois no par correspondente.

Contrato ou suposição?

Como a função calcula uma média, o teste deve exigir duas casas decimais mesmo que o contrato não mencione formatação ou arredondamento.

Passo 2 de 8

Escolher entradas representativas

Agrupe entradas pelo comportamento esperado e escolha casos que verifiquem regras distintas sem repetição desnecessária.

Partições de equivalência

Agrupe antes de escolher

Uma partição de equivalência reúne entradas que devem seguir a mesma regra do contrato. No caso da média, uma separação inicial é:

  • listas com pontuações válidas;
  • listas com alguma pontuação abaixo do mínimo;
  • listas com alguma pontuação acima do máximo.

Ao investigar uma partição, mantenha as demais condições válidas. Assim, fica claro qual regra o caso realmente verifica.

Três grupos de comportamento

Cada grupo reúne várias entradas possíveis, mas apenas alguns representantes precisam entrar na suíte.

Diagrama com três grupos: entradas abaixo da faixa, entradas aceitas e entradas acima da faixa. Um caso está destacado como representante em cada grupo.

Primeiro agrupe pelo comportamento esperado; depois escolha um representante relevante de cada grupo.

Representantes com justificativa

O caso deve acrescentar uma verificação

Um representante é escolhido pela regra pública que exercita, não por caminhos internos imaginados no código. Por exemplo, [20, 80] pode representar entradas válidas, [-10, 50] a rejeição por valor abaixo da faixa e [50, 120] a rejeição por valor acima da faixa.

Entradas válidas pertencem à mesma partição de aceitação, mas não precisam produzir a mesma média. “Comportamento semelhante” significa seguir a mesma regra geral, e não retornar sempre o mesmo valor.

Exemplo

Evite repetição sem propósito

Se a suíte já verifica [20, 80] e inclui [30, 70] apenas para confirmar novamente uma lista válida com média 50, um dos casos pode ser redundante. Mantenha ambos somente se cada um demonstrar uma regra pública diferente. A quantidade de caminhos internos percorridos não é uma justificativa baseada no contrato.

Dica

Pergunta útil para revisar um caso

Complete: “Este caso permanece na suíte porque demonstra que…”. Se a resposta repetir exatamente a justificativa de outro caso, verifique se um deles pode ser retirado.

Classifique pelas regras

Associe entrada e partição

Relacione cada lista à partição de equivalência pertinente.

Toque em um item e depois no par correspondente.

Retire a redundância

Justifique sua seleção

Considere a seleção [20, 80], [30, 70], [-10, 50] e [50, 120]. Retire um caso redundante e justifique por que as três partições continuam representadas.

Escreva pelo menos 60 caracteres (0/60).

Passo 3 de 8

Explorar os valores de fronteira

Selecione os limites inclusivos e seus vizinhos imediatos para detectar erros de inclusão ou exclusão na faixa válida.

Onde o comportamento muda

Fronteiras merecem casos próprios

Uma fronteira é um ponto em que o comportamento esperado pode mudar. No contrato do caso-guia, pontuações de 0 a 100 são válidas, inclusive.

Como o domínio é formado por inteiros, os vizinhos imediatos do limite inferior são -1, 0 e 1. No limite superior, são 99, 100 e 101.

Esses valores ajudam a revelar erros como rejeitar acidentalmente o próprio limite ou aceitar um valor logo fora da faixa.

Os dois limites na reta numérica

A região central representa a faixa aceita. Os pontos imediatamente externos devem seguir o comportamento de rejeição.

Reta numérica destacando menos um, zero e um perto do limite inferior, além de noventa e nove, cem e cento e um perto do limite superior.

Em cada extremidade, verifique o vizinho externo, o limite e o vizinho interno.

Aplicar ao cálculo da média

Exemplo

Isole a pontuação investigada

Mantenha a outra pontuação válida e varie somente o valor próximo à fronteira:

  • [20, -1] → PontuacaoInvalida
  • [20, 0] → média 10
  • [20, 1] → média 10.5
  • [20, 99] → média 59.5
  • [20, 100] → média 60
  • [20, 101] → PontuacaoInvalida

Os resultados literais vêm da regra pública da média. Os casos externos seguem a regra pública de rejeição.

Dica

Partições e fronteiras se complementam

Um representante comum, como 50, confirma o comportamento geral da faixa válida, mas não demonstra que 0 e 100 são aceitos. Os casos de fronteira têm uma justificativa adicional: verificar exatamente onde o comportamento muda.

Selecione a vizinhança completa

Quais valores exercitam as duas fronteiras?

Qual conjunto verifica completamente as vizinhanças dos limites inclusivos de 0 e 100?

Justifique os resultados esperados

Classifique os seis casos

Considere novamente [20, valor], usando valor igual a -1, 0, 1, 99, 100 e 101. Explique quais entradas devem retornar uma média e quais devem produzir PontuacaoInvalida. Relacione sua resposta aos limites inclusivos.

Escreva pelo menos 60 caracteres (0/60).

Passo 4 de 8

Distinguir vazio, unitário e ausente

Reconheça diferenças estruturais entre ausência, coleção vazia e listas com diferentes quantidades de elementos, escolhendo casos coerentes com o contrato.

Entradas parecidas, situações diferentes

Observe a estrutura antes do valor

No caso-guia, None, [], [0] e uma lista com vários elementos representam situações diferentes:

  • None: não há uma lista.
  • []: há uma lista, mas ela está vazia.
  • [0]: há uma lista com um elemento, e zero é uma pontuação válida.
  • [20, 40, 60]: há uma lista com vários elementos válidos.

A quantidade de elementos pode mudar o comportamento esperado, mas somente o contrato determina se cada situação deve produzir um resultado ou uma exceção.

Quatro estados da entrada

Comparação visual entre valor ausente, recipiente vazio, recipiente com um elemento e recipiente com vários elementos.

Da esquerda para a direita: ausência (None), lista vazia ([]), lista com o valor zero ([0]) e lista com vários valores.

O contrato decide o resultado

Exemplo

Cenários do caso-guia

Para a operação de média deste tutorial, a matriz pode conter:

| Entrada | Situação | Comportamento esperado |
|---|---|---|
| None | valor ausente | TypeError |
| [] | lista vazia | ValueError |
| [0] | lista unitária válida | resultado 0 |
| [20, 40, 60] | vários valores válidos | resultado 40 |

Essas expectativas vêm das regras públicas da operação. Em outra função, uma coleção vazia ou None poderia ter um significado diferente.

Dica

Vazio não é sinônimo de inválido

Não transforme uma convenção comum em requisito. Antes de esperar uma exceção para [] ou None, confirme que o contrato realmente define esse comportamento.

Isole a condição investigada

Mude uma característica por vez

Ao investigar a quantidade de elementos, mantenha as pontuações válidas. Assim, [40] representa claramente uma lista unitária, enquanto [20, 40, 60] representa uma lista com vários elementos.

Uma entrada como [101] mistura duas características: é unitária e contém uma pontuação fora da faixa. Se ela for rejeitada, o cenário demonstra a regra da faixa, não o funcionamento normal de uma lista unitária.

Exemplo

Seleção com justificativa

Para distinguir estruturas, uma seleção enxuta pode usar [], [0] e [20, 40, 60], além de None para representar ausência. Cada caso acrescenta uma situação pública diferente.

Adicionar [40] pode ser redundante se [0] já demonstrar adequadamente a lista unitária. Ele só se justifica se houver outra regra específica que você queira evidenciar.

Atenção

Não combine falhas sem necessidade

Evite entradas que reúnam várias condições inválidas, como uma coleção com diferentes valores fora da faixa, quando a ordem das validações não faz parte do contrato. O resultado pode depender de qual problema a implementação encontra primeiro, sem revelar uma regra pública relevante.

Revise uma seleção de cenários

Monte uma seleção enxuta

Considere estas entradas: None, [], [0], [40], [20, 40, 60], [101] e [101, -1].

Escolha apenas os casos necessários para distinguir ausência, vazio, lista unitária válida e lista com vários elementos válidos. Para cada escolha, informe o comportamento esperado e justifique qual regra ela demonstra. Aponte também quais casos você descartaria por redundância ou por misturarem outra condição.

Escreva pelo menos 80 caracteres (0/80).

Passo 5 de 8

Definir expectativas independentes do código

Transforme cenários de sucesso em testes legíveis, usando resultados literais derivados do contrato da operação.

O contrato determina a expectativa

Calcule antes de consultar o código

Em um bom teste, o resultado esperado vem da regra pública da operação — não da forma como ela foi implementada.

Para a entrada [20, 40, 60], a regra da média permite estabelecer diretamente o resultado literal 40.0. Dados pequenos tornam essa conferência simples.

Evite repetir no teste o cálculo feito pela implementação. Se o mesmo erro estiver nos dois lugares, o teste poderá passar sem revelar o defeito.

Duas fontes possíveis para a expectativa

O caminho seguro deriva a expectativa do contrato e mantém o teste independente do código testado.

Comparação entre um teste que recebe a expectativa de uma regra independente e outro que copia o cálculo da implementação.

À esquerda, a regra produz um resultado literal usado pelo teste. À direita, o teste espelha a implementação e pode repetir o mesmo defeito.

Exemplo

Expectativa literal e verificável

Prefira assert calcular_media([20, 40, 60]) == 40.0.

Evite calcular a expectativa com outro laço, com sum(valores) / len(valores) ou chamando novamente calcular_media. O teste deve declarar o comportamento esperado, não reconstruir o algoritmo.

Prepare o módulo local

Crie o arquivo da operação

Em uma pasta de projeto no seu computador, crie pontuacoes.py com o conteúdo completo abaixo. A exceção de domínio também fica nesse módulo. Neste step, a prática se concentra apenas nos cenários de sucesso.

pontuacoes.py

Operação completa usada na prática local.

python
class PontuacaoInvalida(Exception):
    def __init__(self, valor: int, minimo: int, maximo: int):
        self.valor = valor
        self.minimo = minimo
        self.maximo = maximo
        super().__init__(
            f"Pontuação {valor} fora da faixa de {minimo} a {maximo}"
        )


def calcular_media(pontuacoes: list[int]) -> float:
    """Calcula a média de uma lista não vazia de pontuações de 0 a 100."""
    if pontuacoes is None:
        raise TypeError("pontuacoes não pode ser None")

    if not pontuacoes:
        raise ValueError("pontuacoes não pode ser vazia")

    for pontuacao in pontuacoes:
        if pontuacao < 0 or pontuacao > 100:
            raise PontuacaoInvalida(pontuacao, 0, 100)

    return sum(pontuacoes) / len(pontuacoes)

Escreva testes de sucesso legíveis

Um cenário claro por função

Crie a pasta tests e, dentro dela, o arquivo test_pontuacoes.py. Cada nome descreve a condição e o comportamento esperado. As verificações de uma mesma função podem ser complementares, desde que demonstrem o mesmo cenário.

tests/test_pontuacoes.py

Testes-base com expectativas literais derivadas da regra.

python
from pontuacoes import calcular_media


def test_calcula_media_de_varias_pontuacoes_validas():
    resultado = calcular_media([20, 40, 60])

    assert resultado == 40.0


def test_devolve_a_propria_pontuacao_para_lista_unitaria():
    resultado = calcular_media([75])

    assert resultado == 75.0

Dica

Execute no diretório do projeto

Rode python -m pytest na pasta que contém pontuacoes.py e tests. Os valores 40.0 e 75.0 foram definidos diretamente a partir do contrato, antes de depender do cálculo interno da função.

Escolha e formule uma expectativa

Expectativa independente

Qual verificação testa a média de [0, 100] com uma expectativa independente da implementação?

Escreva um teste de sucesso

Escreva uma função de teste para a entrada válida [0, 100]. Use um nome descritivo e uma expectativa literal derivada da regra.

Escreva pelo menos 60 caracteres (0/60).

Passo 6 de 8

Exigir a exceção esperada com pytest.raises

Use pytest.raises para fazer um teste passar somente quando a operação produzir o tipo de exceção previsto no contrato.

Transforme a falha esperada em requisito

Exija o tipo definido no contrato

Para testar uma entrada inválida, envolva a chamada com pytest.raises e informe a exceção prevista. O teste passa quando a chamada levanta esse tipo ou uma subclasse dele.

Prefira sempre o tipo específico do contrato. Usar Exception é amplo demais: falhas diferentes, inclusive defeitos inesperados, poderiam ser aceitas pelo teste.

Estrutura básica

Neste cenário, uma lista vazia deve produzir ValueError.

python
import pytest

from notas import calcular_media


def test_rejeita_lista_vazia():
    with pytest.raises(ValueError):
        calcular_media([])

Os três resultados possíveis

O resultado da chamada determina se a exigência foi atendida.

Diagrama com uma chamada de função seguindo para três saídas: exceção compatível aceita, ausência de exceção rejeitada e exceção incompatível rejeitada.

Somente uma exceção compatível com o tipo informado satisfaz pytest.raises.

Mantenha o bloco restrito à ação

Prepare antes, chame dentro

Faça a preparação antes do with e deixe dentro dele apenas a chamada que deve falhar. Assim, uma exceção ocorrida durante a preparação não será confundida com o comportamento que o teste pretende verificar.

Quando a exceção esperada ocorre, o pytest encerra o bloco e o teste continua depois dele. Linhas colocadas após a chamada dentro do bloco não são executadas.

Limite claro do cenário

O bloco destaca exatamente qual operação deve levantar PontuacaoInvalida.

python
import pytest

from notas import PontuacaoInvalida, calcular_media


def test_rejeita_pontuacao_acima_do_maximo():
    pontuacoes = [50, 101]  # preparação fora do bloco

    with pytest.raises(PontuacaoInvalida):
        calcular_media(pontuacoes)  # única chamada que deve falhar

    # A execução do teste continua a partir daqui.

Dica

Evite verificações inalcançáveis

Não coloque um assert depois da chamada que levanta a exceção, ainda dentro do with: essa linha nunca será alcançada. Verificações posteriores pertencem depois do bloco.

Preveja o resultado do teste

Três execuções

Três testes usam with pytest.raises(ValueError). No primeiro, a chamada levanta ValueError; no segundo, não levanta exceção; no terceiro, levanta TypeError. Qual alternativa descreve os resultados?

Complete a exigência específica

Tipo esperado

Complete o teste:

with pytest.raises(_____):
calcular_media([101])

Passo 7 de 8

Verificar o contexto da exceção

Capture a exceção produzida e verifique os atributos públicos que explicam a falha, sem depender de detalhes irrelevantes da mensagem.

Do tipo da falha aos dados da falha

Capture a instância da exceção

pytest.raises(PontuacaoInvalida) verifica o tipo da falha. Quando o contrato também garante dados sobre ela, use as exc_info para capturar as informações da exceção.

Depois que o bloco with termina, exc_info.value fornece a instância que foi levantada. Nela, você pode consultar os atributos públicos previstos pelo contrato, como valor, minimo e maximo.

Caminho até os atributos

O objeto de captura e a exceção não são a mesma coisa: primeiro acesse exc_info.value; depois, consulte os atributos da instância.

Diagrama mostrando uma chamada que produz uma exceção, um objeto de captura intermediário e, por fim, a instância da exceção com os valores 101, 0 e 100.

A captura leva à instância da exceção; os atributos públicos ficam nessa instância.

Verifique somente o contexto necessário

Tipo e atributos públicos

As verificações ficam depois do bloco porque a chamada dentro dele interrompe o fluxo ao levantar a exceção.

python
import pytest

from pontuacoes import PontuacaoInvalida, calcular_media


def test_rejeita_pontuacao_acima_do_maximo_com_contexto():
    with pytest.raises(PontuacaoInvalida) as exc_info:
        calcular_media([40, 101])

    erro = exc_info.value
    assert erro.valor == 101
    assert erro.minimo == 0
    assert erro.maximo == 100

Exemplo

O que cada parte demonstra

O pytest.raises demonstra que ocorreu PontuacaoInvalida. Já os três asserts demonstram que a exceção identifica o valor rejeitado e os limites inclusivos do contrato.

Nem toda situação exige conferir todos os atributos. Se um teste precisa demonstrar apenas qual entrada foi rejeitada, assert erro.valor == 101 pode ser suficiente.

Dica

Evite depender da redação

Não compare a mensagem completa se seu texto não fizer parte do contrato público. Uma alteração de pontuação ou redação poderia quebrar o teste sem mudar o comportamento relevante. Prefira atributos públicos estáveis que representem o contexto da falha.

Organize a captura e as verificações

Coloque as etapas na ordem correta

Ordene as ações de um teste que verifica o contexto de uma pontuação acima do máximo.

  1. Abra `with pytest.raises(PontuacaoInvalida) as exc_info:`.
  2. Compare os atributos necessários, como `erro.valor`, `erro.minimo` e `erro.maximo`.
  3. Chame `calcular_media([40, 101])` dentro do bloco.
  4. Após sair do bloco, obtenha `erro = exc_info.value`.

Passo 8 de 8

Aplicar e revisar a seleção de testes

Revise uma seleção de casos, complete uma pequena suíte local e justifique as verificações acrescentadas.

Revise a cobertura da suíte

Da regra ao representante

Considere esta síntese do contrato de calcular_media:

  • pontuações válidas comuns: [20, 40] → 30;
  • limite superior e caso unitário: [100] → 100;
  • lista vazia: ValueError;
  • ausência representada por None: TypeError;
  • valor acima do máximo: [101] → PontuacaoInvalida.

Uma seleção proposta também contém [40, 60] → 50. Esse caso repete a regra das listas válidas comuns, enquanto o limite inferior 0 ainda não está representado. Além disso, a falha abaixo do mínimo pode verificar o contexto público da exceção: valor, minimo e maximo.

Mapa dos casos relevantes

Reta numérica com menos um e cento e um na região inválida, zero e cem nos limites válidos e um ponto no interior da faixa; ao lado, símbolos distintos para lista vazia e ausência.

As fronteiras 0 e 100 pertencem à faixa válida; seus vizinhos externos pertencem a partições de falha.

Prepare os arquivos locais

Estrutura da prática

Crie uma pasta para a prática com os arquivos media.py e tests/test_media.py. Os códigos abaixo são completos e podem ser copiados para esses caminhos.

media.py

Operação e exceção de domínio usadas na prática.

python
class PontuacaoInvalida(ValueError):
    def __init__(self, valor: int, minimo: int, maximo: int):
        self.valor = valor
        self.minimo = minimo
        self.maximo = maximo
        super().__init__(
            f"Pontuação {valor} fora da faixa de {minimo} a {maximo}"
        )


def calcular_media(pontuacoes: list[int]) -> float:
    """Calcula a média de uma lista não vazia de pontuações de 0 a 100."""
    if pontuacoes is None:
        raise TypeError("pontuacoes não pode ser None")

    if not pontuacoes:
        raise ValueError("a lista de pontuações não pode estar vazia")

    for valor in pontuacoes:
        if valor < 0 or valor > 100:
            raise PontuacaoInvalida(valor, 0, 100)

    return sum(pontuacoes) / len(pontuacoes)

tests/test_media.py

Suíte-base que será revisada e complementada.

python
import pytest

from media import PontuacaoInvalida, calcular_media


def test_calcula_media_de_pontuacoes_validas():
    assert calcular_media([20, 40]) == 30


def test_calcula_media_de_outra_lista_valida():
    assert calcular_media([40, 60]) == 50


def test_aceita_lista_unitaria_no_limite_superior():
    assert calcular_media([100]) == 100


def test_rejeita_lista_vazia():
    with pytest.raises(ValueError):
        calcular_media([])


def test_rejeita_ausencia_de_lista():
    with pytest.raises(TypeError):
        calcular_media(None)


def test_rejeita_pontuacao_acima_do_maximo():
    with pytest.raises(PontuacaoInvalida):
        calcular_media([101])

Dica

Comando de execução

No terminal, a partir da pasta que contém media.py, execute python -m pytest. Antes de alterar a suíte, confirme que os seis testes-base passam.

Complete, execute e relate

Sua tarefa

  1. Identifique o teste que apenas repete a partição das listas válidas comuns e remova-o.
  2. Acrescente um teste que aceite o limite inferior 0 e compare o resultado com o literal esperado.
  3. Acrescente um teste para [-1] que exija PontuacaoInvalida e, depois do bloco with, verifique valor == -1, minimo == 0 e maximo == 100 por meio de exc_info.value.
  4. Execute novamente python -m pytest.

Mantenha somente a chamada que deve falhar dentro do bloco with pytest.raises.

Registre sua revisão

Qual foi o resultado observado na sua execução? Explique qual caso você removeu, quais dois casos acrescentou e qual regra cada alteração demonstra.

Escreva pelo menos 80 caracteres (0/80).

Confira a solução e conclua

Testes de referência

Após remover test_calcula_media_de_outra_lista_valida, estes são os dois testes que completam a seleção:

python
def test_aceita_limite_inferior():
    assert calcular_media([0]) == 0


def test_informa_contexto_da_pontuacao_abaixo_do_minimo():
    with pytest.raises(PontuacaoInvalida) as exc_info:
        calcular_media([-1])

    erro = exc_info.value
    assert erro.valor == -1
    assert erro.minimo == 0
    assert erro.maximo == 100

Resumo

Checklist final de qualidade

Use esta revisão em novas seleções de testes.

  • Cada caso representa uma regra ou fronteira relevante, sem repetir desnecessariamente o mesmo comportamento.
  • Sucesso, limites, lista vazia, caso unitário, ausência e entradas inválidas aparecem quando são pertinentes ao contrato.
  • Os resultados esperados são literais derivados da regra, sem repetir o algoritmo da operação.
  • Os nomes dos testes descrevem a condição e o comportamento esperado.
  • Cada falha exige uma exceção específica; Exception não substitui o tipo definido pelo contrato.
  • Atributos da exceção são verificados somente quando fornecem contexto público necessário, sem depender da redação completa da mensagem.

Tutorial concluído

Parabéns! Você concluiu: Selecionar casos de teste e verificar exceções

Prática concluída: você já pode selecionar casos de sucesso e falha com justificativas claras.

100 XP

Baixe o Aplicativo agora para ter acesso a + de 5000 cursos gratuitos, exercícios, certificado e muito conteúdo sem pagar nada!

  • Cursos online 100% gratuitos do início ao fim

    Milhares de cursos online em vídeo, ebooks e áudiobooks.

  • Mais de 60 mil exercícios gratuitos

    Para testar seus conhecimentos no decorrer dos cursos online

  • Certificado Digital gratuito válido em todo o Brasil

    Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail

Aplicativo Cursa na tela de ebook, na tela de curso em vídeo e na tela de exercícios do curso, mais o certificado de conclusão de curso