
Passo 1 de 8
Tornar a falha reproduzível
Crie um caso pequeno e determinístico, confirme a divergência pelo programa e pelo teste e registre uma hipótese inicial sem tratá-la como causa comprovada.
Trilha de aprendizado · Nível 8 · Tutorial 6
Usar o depurador para acompanhar uma execução reproduzível, localizar a origem de valores incorretos e proteger a correção com um teste de regressão.
Tornar a falha reproduzível
Crie um caso pequeno e determinístico, confirme a divergência pelo programa e pelo teste e registre uma hipótese inicial sem tratá-la como causa comprovada. 2 min
Pausar a execução com breakpoint()
Insira uma pausa temporária antes da região suspeita e identifique a próxima linha que será executada. 3 min
Inspecionar valores sem interferir
Use o comando p para consultar o estado da execução pausada e diferencie observações seguras de expressões que podem alterar os dados investigados. 2 min
Controlar o avanço da execução
Escolha entre avançar no quadro atual, entrar em uma chamada e continuar a execução, alternando esses comandos com a inspeção de valores. 3 min
Navegar pelos quadros da pilha
Relacione os valores locais de funções encadeadas navegando pela pilha sem executar novas linhas. 2 min
Inspecionar uma falha de teste com --pdb
Entrar no depurador após a falha de um teste, relacionar o assert aos valores disponíveis e reconhecer quando uma nova execução é necessária. 3 min
Localizar a primeira divergência
Reposicione a pausa antes das funções suspeitas e compare o estoque antes e depois de cada operação para identificar onde o valor se desvia pela primeira vez. 3 min
Aplicação final: corrigir e proteger o comportamento
Aplique a correção mínima, preserve o caso como teste de regressão e verifique a suíte completa. 3 min

Passo 1 de 8
Crie um caso pequeno e determinístico, confirme a divergência pelo programa e pelo teste e registre uma hipótese inicial sem tratá-la como causa comprovada.
Uma reserva parte de 10 unidades e solicita 3 unidades. Pelo contrato da operação, o saldo deveria ser 7, independentemente de como o código foi implementado.
Porém, o programa informa 4. Esse é o sintoma observado — ainda não é uma explicação da causa. Para investigá-lo, manteremos apenas um produto, uma quantidade fixa e uma chamada que preserve a falha.

A mesma entrada produz uma diferença objetiva entre o contrato esperado e o resultado observado.
Dica
Reduzir o cenário não significa reescrever a implementação suspeita. Remova apenas dados e chamadas que não sejam necessários para reproduzir a divergência, preservando a entrada e o comportamento esperado.
Na mesma pasta, crie estoque.py e test_estoque.py com os conteúdos completos abaixo. Não corrija nem simplifique as funções internas neste momento: primeiro precisamos observar a falha de maneira consistente.
Programa curto de reserva de estoque com uma entrada fixa.
def separar_itens(estoque, produto, quantidade):
estoque[produto] -= quantidade
def confirmar_reserva(estoque, produto, quantidade):
estoque[produto] -= quantidade
def reservar(estoque, produto, quantidade):
separar_itens(estoque, produto, quantidade)
confirmar_reserva(estoque, produto, quantidade)
return estoque[produto]
if __name__ == "__main__":
estoque = {"caderno": 10}
saldo = reservar(estoque, "caderno", 3)
print(f"Saldo final: {saldo}")O resultado esperado vem da regra: reservar 3 das 10 unidades deve deixar 7.
from estoque import reservar
def test_reserva_reduz_saldo_uma_vez():
estoque = {"caderno": 10}
saldo = reservar(estoque, "caderno", 3)
assert saldo == 7
assert estoque == {"caderno": 7}No terminal, a partir da pasta que contém os dois arquivos, execute primeiro:
python estoque.py
Depois selecione somente o caso condutor:
python -m pytest test_estoque.py::test_reserva_reduz_saldo_uma_vez
As duas execuções devem partir do mesmo estoque inicial e expor a mesma divergência.
Exemplo
O programa apresenta Saldo final: 4. O pytest informa que a expectativa saldo == 7 falhou porque o valor obtido foi 4.
Agora há três fatos separados:
A saída exata do relatório do pytest pode variar entre versões, mas a diferença entre 7 e 4 deve permanecer.
Descreva a entrada mínima, o resultado esperado, o resultado obtido e uma hipótese que possa ser confrontada durante a execução. Evite corrigir o código ou afirmar que já encontrou a causa.
Escreva pelo menos 80 caracteres (0/80).

Passo 2 de 8
Insira uma pausa temporária antes da região suspeita e identifique a próxima linha que será executada.
Um ponto de interrupção pausa uma execução específica para que você examine o que está acontecendo. Ele não corrige o programa nem muda o resultado esperado.
No estoque.py do caso anterior, insira temporariamente breakpoint() imediatamente antes da chamada que inicia a região suspeita. Assim, a pausa acontece antes que essa chamada produza seus efeitos.
Preserve o código e os nomes do arquivo anterior. Acrescente somente a linha destacada pela posição mostrada neste trecho:
# Preparação da entrada fixa do caso anterior
breakpoint()
saldo_obtido = processar_reserva(estoque, produto, quantidade)
# Apresentação do resultadoDica
Trate breakpoint() como um instrumento de investigação. Depois de concluir o diagnóstico, você deverá remover essa chamada do programa.
Salve o arquivo e execute python estoque.py. Na configuração padrão do Python, breakpoint() abre o depurador pdb no terminal.
A parada terá uma forma semelhante a esta:
> .../estoque.py(XX)<module>()-> saldo_obtido = processar_reserva(...)(Pdb)
A primeira linha identifica o arquivo, o número da linha e o contexto atual. A seta aponta para a linha que ainda será executada. Portanto, os efeitos da chamada indicada ainda não ocorreram nessa parada.
A pausa ocorre entre a preparação da entrada e a chamada suspeita.

O marcador fica antes da chamada; a seta do depurador indica a próxima linha, não uma operação já concluída.
Dica
No prompt (Pdb), digite q e pressione Enter para sair do depurador e interromper essa execução. Execute python estoque.py novamente quando precisar começar uma investigação nova a partir da entrada fixa.
Você suspeita que processar_reserva(...) introduz o saldo incorreto. Qual opção permite examinar o estado anterior à chamada e interpreta corretamente a seta exibida pelo depurador?

Passo 3 de 8
Use o comando p para consultar o estado da execução pausada e diferencie observações seguras de expressões que podem alterar os dados investigados.
No prompt (Pdb), use p expressão para avaliar e apresentar uma expressão no quadro atual. Comece por consultas simples: parâmetros, variáveis locais, entradas de dicionários e comparações. Isso permite confrontar o estado observado com o que sua hipótese previa.
Com a execução pausada antes da chamada suspeita, consulte os dados sem modificá-los:
(Pdb) p estoque
{'caderno': 10}
(Pdb) p produto
'caderno'
(Pdb) p quantidade
3
(Pdb) p estoque[produto]
10
(Pdb) p estoque[produto] == 10
True
À esquerda, a lupa representa uma consulta ao estado. À direita, uma mão retirando um elemento representa uma expressão que interfere na execução investigada.
O comando p não é um visualizador passivo: ele executa a expressão fornecida. Consultar estoque[produto] ou comparar valores é adequado. Já chamar métodos que alteram coleções ou funções que executam ações do programa pode mudar justamente o estado que você pretende investigar.
Compare expressões de observação com expressões que modificam o dicionário:
# Consultas simples
(Pdb) p estoque[produto]
(Pdb) p quantidade > 0
(Pdb) p estoque[produto] - quantidade
# Evite durante a inspeção
(Pdb) p estoque.pop(produto)
(Pdb) p estoque.update({produto: 999})Atenção
Encerre a sessão com q e inicie novamente com python estoque.py. A entrada fixa reproduzível devolve um estado confiável para a investigação. Não use o valor já contaminado como evidência.
Qual comando consulta o saldo de caderno sem alterar deliberadamente o dicionário estoque?
Na execução local, consulte com p os valores de produto, quantidade e estoque[produto]. Compare-os com o que você previa para esse ponto da execução e registre sua conclusão provisória.
Escreva pelo menos 60 caracteres (0/60).

Passo 4 de 8
Escolha entre avançar no quadro atual, entrar em uma chamada e continuar a execução, alternando esses comandos com a inspeção de valores.
Depois de pausar, use o comando que responde à sua pergunta:
n (next): executa a linha indicada e para na próxima linha do quadro atual. Se a linha chama uma função, a função inteira é executada sem pausas internas.s (step): executa o próximo passo e entra em uma função Python chamada pela linha.c (continue): retoma a execução até outro ponto de interrupção ou até o programa terminar.Use n quando importa o efeito da chamada e s quando importa como ela produz esse efeito.

Na linha de chamada, n retorna ao chamador após executar a função; s entra na função auxiliar; c segue até outra interrupção ou o término.
Uma chamada ultrapassada com n continua sendo executada. Seus retornos e alterações em objetos permanecem no programa; apenas não acompanhamos suas linhas internas.
No caso de estoque, pause na linha que chama uma função auxiliar. Inspecione o saldo com p, avance com n e consulte o mesmo valor novamente:
Digite um comando por vez. Substitua os nomes apenas se sua versão do caso usar outros nomes.
(Pdb) p estoque[produto]
(Pdb) n
(Pdb) p estoque[produto]Observe onde a execução para depois de cada comando.
n permanece no chamador, s entra na função e c segue sem parar em cada linha.
Dica
Alterne p com n ou s. Compare o valor imediatamente antes e depois da operação relevante, em vez de avançar muitas linhas e perder o primeiro momento da mudança.
Relacione cada comando do pdb ao objetivo de investigação.
Toque em um item e depois no par correspondente.
Execute novamente python estoque.py com o breakpoint() antes da chamada auxiliar investigada. Na pausa:
p estoque[produto].n para executar a chamada inteira.s na mesma chamada para entrar nela.n e p estoque[produto] até observar a operação que muda o valor.c para prosseguir ou q para encerrar a investigação.Não faça atribuições nem chame operações mutadoras durante a inspeção.
Em qual operação o saldo mudou? Relate os valores observados antes e depois e explique como n, s e p ajudaram a localizar essa mudança.
Escreva pelo menos 40 caracteres (0/40).

Passo 5 de 8
Relacione os valores locais de funções encadeadas navegando pela pilha sem executar novas linhas.
Quando uma função chama outra, cada chamada ativa possui um quadro: o contexto que reúne sua posição no código e seus nomes locais.
No pdb, use w para exibir a pilha. O marcador > identifica o quadro selecionado, no qual comandos como p quantidade serão avaliados.

u seleciona um quadro mais antigo, em direção aos chamadores; d retorna a um quadro mais recente, em direção à chamada interna.
A pilha está pausada dentro da função auxiliar. Observe como o nome disponível para p muda com o quadro selecionado.
(Pdb) w
estoque.py(...)reservar()
> estoque.py(...)aplicar_reserva()
(Pdb) p quantidade
2
(Pdb) u
> estoque.py(...)reservar()
(Pdb) p quantidade_solicitada
2
(Pdb) d
> estoque.py(...)aplicar_reserva()
(Pdb) p quantidade
2Dica
Os comandos u e d apenas mudam o contexto selecionado para inspeção. Eles não executam linhas, não desfazem operações e não fazem o programa voltar no tempo. Use w novamente quando precisar confirmar sua posição na pilha.
Você está no quadro da função auxiliar e quer consultar uma variável local existente apenas na função que a chamou. Qual comando deve usar primeiro?
Após usar u, as operações realizadas pela função interna são desfeitas e podem ser executadas novamente.

Passo 6 de 8
Entrar no depurador após a falha de um teste, relacionar o assert aos valores disponíveis e reconhecer quando uma nova execução é necessária.
Remova do arquivo estoque.py o breakpoint() temporário usado anteriormente. Agora a pausa deve acontecer por causa da falha do teste, não durante a execução normal do programa.
No terminal, dentro da pasta do projeto, execute o arquivo de teste com --pdb. A entrada continua sendo a mesma do caso reproduzível.
Se test_estoque.py contém o caso reproduzível deste tutorial, execute:
python -m pytest test_estoque.py --pdbDica
O pytest primeiro apresenta a diferença do assert e o rastreamento. Em seguida, abre o prompt (Pdb) no contexto da falha. A aparência exata da saída pode variar um pouco entre versões do pytest.
A diferença do assert informa que o teste obteve um saldo diferente do esperado. O rastreamento mostra onde a verificação falhou. No prompt do depurador, p permite consultar os nomes disponíveis no quadro selecionado e confirmar o valor incorreto.
Essa confirmação localiza o sintoma no teste, mas ainda não prova qual operação produziu o saldo incorreto.
A inspeção começa no quadro em que o assert falhou. Funções que já retornaram normalmente não permanecem disponíveis nessa pilha.

O depurador mostra os quadros preservados pelo rastreamento da falha, não um histórico completo da execução.
Atenção
O assert é o lugar onde a divergência foi percebida. Se a função testada retornou normalmente antes da verificação, seus quadros já foram encerrados e não podem ser recuperados por essa sessão do depurador.
No prompt (Pdb), use os comandos já praticados. w mostra a pilha e marca o quadro selecionado. u seleciona um quadro mais antigo, na direção dos chamadores; d volta para um quadro mais recente. Depois de mudar de quadro, use p para consultar os nomes disponíveis naquele contexto.
A pilha pode incluir quadros internos do pytest. Priorize o quadro de test_estoque.py, pois ele contém os dados do caso. Navegar entre quadros não executa linhas nem recupera chamadas encerradas.
Substitua os nomes do exemplo pelos nomes exibidos no seu teste quando necessário.
(Pdb) w
(Pdb) p estoque
(Pdb) p saldo_obtido
(Pdb) u
(Pdb) d
(Pdb) cDica
O comando c deixa essa inspeção e permite que o pytest prossiga. Ele não retorna ao interior de uma função que já terminou. Para observar um momento anterior, será preciso iniciar outra execução e posicionar um breakpoint() antes desse momento.
Depois que a função testada retorna normalmente e o assert falha, o comando u permite reabrir o quadro encerrado dessa função e acompanhar suas linhas anteriores.
No prompt aberto pela falha, p saldo_obtido apresenta 4, enquanto o teste esperava 7. O comando w mostra o quadro do teste e quadros internos do pytest, mas não mostra o quadro da função de reserva. O que essa observação confirma e qual deve ser o próximo passo para descobrir onde o valor se desviou?
Escreva pelo menos 80 caracteres (0/80).

Passo 7 de 8
Reposicione a pausa antes das funções suspeitas e compare o estoque antes e depois de cada operação para identificar onde o valor se desvia pela primeira vez.
O teste percebe o problema no assert: esperava saldo 7, mas recebeu 4. Esse é o sintoma, não necessariamente a origem.
Combine o rastreamento com os valores já observados para escolher uma pausa anterior ao retorno incorreto. No caso de estoque, a região suspeita é a fronteira entre reservar() e baixar_estoque(), onde duas funções encadeadas podem alterar o mesmo dicionário.
Acompanhe o mesmo estoque em três momentos. A investigação deve localizar a transição que transforma um estado ainda correto no primeiro estado incompatível com o resultado esperado.

O saldo 4 é percebido no teste, mas nasce na segunda retirada: a primeira redução, de 10 para 7, ainda está de acordo com o esperado.
No seu estoque.py, remova a pausa temporária anterior e deixe breakpoint() imediatamente antes da chamada a baixar_estoque(). Mantenha o defeito por enquanto: o objetivo desta execução é coletar evidências, não corrigir o código.
Use este código para manter o mesmo caso reproduzível durante a investigação.
def baixar_estoque(estoque, produto, quantidade):
estoque[produto] -= quantidade
def reservar(estoque, produto, quantidade):
breakpoint()
baixar_estoque(estoque, produto, quantidade)
estoque[produto] -= quantidade
return estoque[produto]
def main():
estoque = {"caderno": 10}
saldo = reservar(estoque, "caderno", 3)
print(f"Saldo esperado: 7; saldo obtido: {saldo}")
if __name__ == "__main__":
main()
Execute python estoque.py e informe estes comandos, um de cada vez. As linhas iniciadas por # descrevem o resultado esperado e não precisam ser digitadas.
p estoque[produto]
# 10
n
p estoque[produto]
# 7
n
p estoque[produto]
# 4
qExemplo
Hipótese: a quantidade reservada pode estar sendo abatida mais de uma vez nas funções encadeadas.
Observação decisiva: antes da chamada, o saldo é 10. Depois de baixar_estoque(), passa a 7, que já corresponde ao resultado esperado. Após estoque[produto] -= quantidade em reservar(), passa a 4.
Conclusão: a segunda subtração introduz a primeira divergência. O teste apenas percebe o saldo incorreto depois que reservar() retorna.
Atenção
Não atribua 7 ao saldo nem modifique o dicionário para fazer o teste passar. Isso esconderia a origem do defeito e contaminaria a execução. Se alterar o estado acidentalmente, encerre com q e repita o caso desde o início.
Com base na sessão do depurador, identifique a operação que introduz o saldo incorreto. Apresente os valores observados antes e depois dela e explique por que essa evidência confirma um abatimento duplicado, em vez de apenas repetir a mensagem do teste.
Escreva pelo menos 100 caracteres (0/100).

Passo 8 de 8
Aplique a correção mínima, preserve o caso como teste de regressão e verifique a suíte completa.
A investigação confirmou que a quantidade reservada era abatida duas vezes: uma na função auxiliar e outra na função chamadora. Em estoque.py, mantenha o abatimento na função responsável por alterar o estoque e remova somente a segunda instrução estoque[produto] -= quantidade da função chamadora.
Não altere o saldo esperado para aceitar o defeito. Para estoque inicial 10 e reserva 3, o contrato continua exigindo saldo 7.
Confirme que test_estoque.py preserva a entrada que revelou o defeito e verifica o comportamento público esperado.
from estoque import reservar
def test_reserva_abate_quantidade_uma_vez():
estoque = {"caderno": 10}
reservar(estoque, "caderno", 3)
assert estoque["caderno"] == 7Dica
Mude apenas a operação responsável pelo abatimento duplicado. O teste deve permanecer com a expectativa definida antes da correção: saldo 7.
O mesmo teste forneceu duas evidências: na versão defeituosa, ele falhou porque encontrou saldo 4 em vez de 7; depois da correção, deve passar sem mudar a expectativa.
Remova todos os breakpoint() temporários de estoque.py. Em seguida, execute primeiro o arquivo de teste que reproduz a falha e depois todos os testes do projeto.
No terminal, a partir da pasta que contém os arquivos do projeto, execute:
python -m pytest test_estoque.py -q
python -m pytestA correção só encerra a investigação depois que o caso reproduzível passa e os demais testes são executados.

Reproduzir → formular hipótese → pausar → inspecionar → localizar a origem → corrigir → verificar.
Coloque as etapas da investigação na ordem adequada.
Com base na sua execução local, relate: a causa do defeito, a observação decisiva, como o teste falhava antes, o resultado após a correção e o resultado dos demais testes.
Escreva pelo menos 120 caracteres (0/120).
Resumo
Você concluiu uma investigação sem ajustar artificialmente o estado nem enfraquecer a expectativa do teste.
Parabéns! Você concluiu: Investigar falhas com pontos de interrupção
100 XP
Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks