• Home
  • Chat IA
  • Guru IA
  • Tutores
  • Central de ajuda
Home
Chat IA
Guru IA
Tutores

·

Engenharia de Computação ·

Linguagens de Programação

Envie sua pergunta para a IA e receba a resposta na hora

Recomendado para você

Playlist YouTube Marketing Digital - Estrategias e Conteudo

1

Playlist YouTube Marketing Digital - Estrategias e Conteudo

Linguagens de Programação

FIT

Links de Vídeos Educacionais

1

Links de Vídeos Educacionais

Linguagens de Programação

FIT

Persistência de Dados em Arquivos com Python

21

Persistência de Dados em Arquivos com Python

Linguagens de Programação

FIT

Características Funcionais do Python: Decoradores e Classes Abstratas

15

Características Funcionais do Python: Decoradores e Classes Abstratas

Linguagens de Programação

FIT

Introdução ao HTML: Tópicos e Objetivos de Aprendizagem

32

Introdução ao HTML: Tópicos e Objetivos de Aprendizagem

Linguagens de Programação

FIT

Introdução a Padrões de Projeto e Princípios do SOLID

14

Introdução a Padrões de Projeto e Princípios do SOLID

Linguagens de Programação

FIT

AC1-Programacao-Orientada-a-Objetos-Python-Questoes-e-Respostas

18

AC1-Programacao-Orientada-a-Objetos-Python-Questoes-e-Respostas

Linguagens de Programação

FIT

AC1 Desenvolvimento Web - Tecnologias Server-Side, Códigos de Erro e Estrutura HTML

5

AC1 Desenvolvimento Web - Tecnologias Server-Side, Códigos de Erro e Estrutura HTML

Linguagens de Programação

FIT

AC3-POO-TDD-Excecoes-e-Padroes-de-Projeto-Questoes-para-Estudo

10

AC3-POO-TDD-Excecoes-e-Padroes-de-Projeto-Questoes-para-Estudo

Linguagens de Programação

FIT

Texto de pré-visualização

9 TEXTO BASE PROGRAMAÇÃO ORIENTADA A OBJETOS Faculdade IMPACTA PROGRAMAÇÃO ORIENTADA A OBJETOS Texto base 9 Testes unitários e tratamento de erros Prof MSc Rafael Maximo Carreira Ribeiro Resumo Neste capítulo iremos aprender sobre dois conceitos muito importantes na programação de todo tipo de aplicação ou software o tratamento de exceções e a criação e execução de testes unitários automatizados Faremos também uma breve introdução a metodologia TDD que é o Desenvolvimento Guiado por Testes em português 91 Introdução Vimos em LP que linguagens de programação fazem parte do que chamamos de linguagens formais pois possuem um conjunto definido de regras e não permitem nenhuma margem para ambiguidades Portanto um computador irá executar exatamente aquilo que lhe é instruído e pode nos dizer facilmente quando há uma instrução que não segue as regras da linguagem ou que tenta realizar uma operação não permitida erros de sintaxe e execução respectivamente Já com relação a erros de lógica somos nós os responsáveis por garantir que nosso código esteja fazendo a coisa certa Por exemplo imagine que ao fazer um depósito na sua conta o programa do banco tente adicionar um valor que não seja um número Isso configuraria um erro de execução pois não é possível somar um número a um nãonúmero em Python e o computador nos informaria desse erro Imagine agora outro erro em que o programa subtraia o valor depositado do seu saldo ao invés de somálo Isso caracteriza um erro de lógica também chamado de erro de semântica pois há uma divergência entre o que o código faz e o que esperávamos que fosse feito Neste caso computador não tem como saber que isso está errado já que ele executa fielmente suas instruções então se há um erro de lógica somos nós os responsáveis por encontrálo e corrigilo Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS 92 Desenvolvimento Guiado por Testes TDD O desenvolvimento guiado por testes é uma técnica para o desenvolvimento de software em que os requisitos são convertidos em testes antes de começarmos a programar o software propriamente dito Ou seja primeiro escrevemos os testes e só depois escrevemos o código que deverá cumprir as tarefas para as quais os testes foram escritos Essa metodologia foi apresentada por Kent Beck 2002 no começo dos anos 2000 Segundo o próprio autor BECK K 2012 ele apenas redescobriu essa técnica que já era usada por programadores desde a época dos cartões perfurados 921 Ciclos do TDD O TDD é constituído por ciclos de desenvolvimento e cada ciclo possui 3 fases Red Green Refactor A última fase é também conhecida como a fase azul Blue Na fase vermelha escrevemos os testes para a nova funcionalidade que não existe ainda na fase verde escrevemos o código que implementa a funcionalidade sendo testada e na fase azul refatoramos o código aprimorando a solução inicial da fase verde Podemos descrever mais detalhadamente cada fase como RED Adicionamos um novo teste para a nova funcionalidade e rodamos todo o conjunto de testes Nessa fase o teste deverá obrigatoriamente falhar pois a funcionalidade ainda não foi implementada Se o teste passar há algo errado com ele e precisamos refatorálo até que ele falhe GREEN Implementamos a nova funcionalidade e executamos os testes até que o novo teste passe sem quebrar nenhum outro teste O objetivo aqui é escrever a solução mais simples possível que faça o teste passar sem precisar se preocupar com padrões de projeto com os princípios do SOLID com deixar o código elegante ou com a eficiência do nosso algoritmo tudo isso ficará para a etapa de refatoração do código BLUE Com o teste passando sabemos duas coisas 1 a nova funcionalidade está implementada 2 não introduzimos nenhuma modificação que quebre outras funcionalidades O objetivo nesta fase é melhorar desempenho legibilidade e manutenabilidade do código e com os testes agora temos segurança para fazer melhorias na implementação que podem envolver entre outros renomear as variáveis e melhorar a legibilidade do código aplicar os princípios do SOLID que sejam relevantes reorganizar o código de acordo com a responsabilidade de cada classe aplicar um ou mais padrões de projeto que sejam pertinentes Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS remover código duplicado e valores hardcoded 1 subdividir os métodos e funções se necessário 922 Principais vantagens do TDD O ciclo do TDD é então repetido para cada nova funcionalidade que precisamos implementar No começo pode parecer contraintuitivo programar primeiro o teste mas com o tempo irá se tornar natural e no médio e longo prazo traz muitos benefícios como por exemplo Código mais simples e fácil de ler e dar manutenção Código mais flexível e adaptável com menos acoplamentos e interfaces mais claras e classes mais direcionadas De certa forma podemos dizer que a prática correta do TDD automaticamente leva à aplicação do princípio da responsabilidade única o S do SOLID Maior atendimento dos requisitos uma vez que precisamos pensar nos testes antes de escrever o código acabamos fazendo um exercício maior de interpretação dos requisitos e melhoramos o nosso entendimento sobre o comportamento da nova funcionalidade Segurança ao desenvolver pois sabemos que caso nossa implementação quebre alguma outra funcionalidade seremos avisados pelos testes ainda durante o desenvolvimento e poderemos corrigir o problema antes de introduzir bugs silenciosamente na aplicação 923 Limitações do TDD Assim como qualquer outra metodologia de desenvolvimento o TDD também apresenta algumas limitações como por exemplo O TDD por usar principalmente testes unitários não é capaz de testar completamente as partes da aplicação que exigem outros tipos de testes como por exemplo conexões com um banco de dados configurações de rede no ambiente interfaces de usuário etc Nestes casos devemos testar a parte lógica interna da nossa aplicação usando um mock para representar as partes externas 2 às quais não temos controle Para que as vantagens do TDD possam ser aproveitadas toda a equipe envolvida no projeto precisa ter conhecimento da metodologia caso contrário é possível que parte da equipe encare os testes como perda de tempo 2 mock é um objeto que simula o objeto real por exemplo uma conexão com um banco de dados No objeto de mock podemos definir o comportamento esperado daquela conexão se vai dar erro ou não qual o erro qual o retorno etc E assim podemos testar a nossa lógica interna em cada uma dessas situações 1 Hardcoded ou codificação rígida é quando colocamos um valor fixo no próprio código fonte por exemplo quando colocamos a url para uma api como uma string no próprio código ao invés de ler este valor de um arquivo de configurações ou variável de ambiente Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Projetos com um grande número de testes podem passar uma falsa sensação de segurança e isso pode levar a equipe a negligenciar outros tipos de testes O conjunto de testes precisa de manutenção assim como o restante do código então testes mal escritos podem acabar aumentando o custo de manutenção da aplicação pois será necessário mais tempo de desenvolvimento para corrigilos Um exemplo é o uso de testes com mensagens de erro escritas como strings literais no código que poderão eventualmente falhar após uma atualização de algum módulo na qual as mensagens de erro sejam alteradas O desenvolvedor irá escrever tanto os testes quanto o código então caso haja um erro de interpretação dos requisitos do projeto é provável que tanto o código quanto os testes compartilhem esse mesmo erro e isso passe sem ser percebido Portanto é necessário estar atento a esse tipo de problema sendo que ter o códigotestes revisados por outros desenvolvedores ajuda a mitigálo 93 Testes Unitários e Testes Automatizados O exemplo dado na introdução é simples e pode parecer besta mas em situações reais as aplicações e programas são mais complexos com diversos módulos diferentes que interagem entre si de maneira muitas vezes não linear e interdependente Sendo assim nem sempre conseguimos garantir que uma alteração em um trecho de código não irá afetar outras áreas da aplicação de maneira inesperada Para resolver isso após alterarmos alguma coisa no código podemos testar nossa aplicação para garantir que tudo esteja funcionando como antes mas conforme a aplicação cresce fazer tais testes manualmente demandará cada vez mais tempo e eventualmente se tornará inviável A resposta óbvia é portanto a utilização de testes automatizados Existem diversos tipos de testes mas agora vamos estudar os testes unitários ou testes de unidade Testes unitários servem para testar uma unidade isolada de código para garantir que ela faz aquilo a que se propõe isso pode ser o teste de uma função de um método da criação de um objeto com as propriedades corretas etc Vamos criar uma função que recebe um valor inteiro e nos retorna esse valor mais 2 Para isso crie o arquivo meumodulopy na pasta aula09 e digite o código da Codificação 91 Codificação 91 Exemplo de função que retorna número recebido mais dois def soma2numero return numero 2 Fonte do autor 2021 Talvez você tenha percebido que há um erro na função Esse erro é proposital e vamos supor que tenha passado despercebido por hora Como sabemos o que a função Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS deve fazer podemos pensar em alguns casos de teste para verificar seu funcionamento como mostra a Tabela 91 Tabela 91 Casos de teste para a função soma2 Caso de teste Entrada Saída esperada 1 2 4 2 5 7 Fonte do autor 2021 Agora adicione o trecho de código da Codificação 92 ao arquivo anterior para testar nossa função Codificação 92 Código de teste inicial test1 soma22 4 test2 soma25 7 msg1 sucesso if test1 else falha msg2 sucesso if test2 else falha printfResultado do teste 1 msg1 printfResultado do teste 2 msg2 Fonte do autor 2021 Neste código estamos guardando o resultado das verificações em uma flag booleana uma variável que guarda um valor booleano True ou False referente ao status de algo em nosso código Em seguida usamos o operador ternário para decidir 3 qual mensagem deve ser exibida na tela e por fim exibimos as mensagens do resultado de cada teste A Figura 91 mostra o resultado da execução deste código no terminal 3 Este operador foi introduzido com a PEP 0308 e funciona assim na expressão x if C else y primeiro a condição C é avaliada se resultar em True x é avaliado e o valor retornado caso contrário y será avaliado e retornado PSF 2021a Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 91 Execução da primeira versão dos testes automatizados Fonte do autor 2021 Codificação 93 Comando utilizado na Figura 91 e respectiva saída no terminal python aula04meumodulopy Resultado do teste 1 sucesso Resultado do teste 2 falha Fonte do autor 2021 A primeira coisa que podemos fazer para melhorar nossos testes é criálos em um arquivo separado pois não é uma boa prática deixar nossas funções e nossos testes em um mesmo arquivo Portanto crie na mesma pasta um arquivo chamado testmeumodulopy e copie para lá o código dos testes Para executálos precisamos acessar a nossa função que continua no arquivo original então para isso vamos importála colocando na primeira linha do arquivo a instrução da Codificação 94 Codificação 94 Instrução para importação da função soma2 no arquivo de teste from meumodulo import soma2 Fonte do autor 2021 A criação e importação de módulos em Python é um assunto já visto em outra aula mas da forma acima não precisamos alterar o código do teste pois estamos importando a partir de meumodulopy a função soma2 O resultado pode ser visto na Figura 92 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 92 Execução da segunda versão dos testes automatizados Fonte do autor 2021 Conseguimos separar as responsabilidades de cada arquivo então agora poderíamos tentar melhorar as mensagens exibidas incluindo informações dos valores esperados e obtidos entre outras No entanto fazer isso para todos os testes nos daria muito trabalho extra com configuração e formatação tirando o foco do desenvolvimento dos testes que verificam a lógica da aplicação em si Para nos ajudar nisso vamos usar o pytest uma ferramenta de testes automatizados que simplifica a construção e execução dos testes 931 Instalando o Pytest A instalação do pytest é feita através do gerenciador de pacotes do Python que já usamos em aulas passadas o PIP Execute no terminal o comando da Codificação 95 referente ao sistema operacional que estiver utilizando Codificação 95 Comando para instalação do pytest py m pip install U pytest Windows python3 m pip install U pytest Linux e Mac Fonte do autor 2021 Caso ao final da instalação o pip mostre um aviso warning informando que o caminho para a pasta de pacotes do Python não está na PATH do sistema adicione tal Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS pasta a variável de ambiente PATH do seu usuário Em seguida verifique se a 4 instalação foi bem sucedida conferindo a versão instalada como na Codificação 96 Codificação 96 Verificação da instalação correta do módulo pytest pytest version pytest 622 Fonte do autor 2021 Caso o comando da Codificação 96 não funcione corretamente tente executar o comando da codificação 97 Se isso tampouco funcionar é possível que sua instalação do Python esteja com algum erro ou que não tenha sido adicionado à PATH do sistema para Windows Às vezes reinstalar o Python pode resolver o problema Codificação 97 Verificação da instalação correta do módulo pytest py m pytest version Windows python3 m pytest version Linux e Mac pytest 622 Fonte do autor 2021 Ao executar o pytest ele irá automaticamente buscar na pasta atual e em todas as subpastas por arquivos da forma testpy ou testpy ou seja que comecem ou terminem com a palavra test seguida ou precedida respectivamente de um sublinhado 5 Após encontrar os arquivos que correspondem ao padrão de nome o pytest busca os testes em si que podem ser funções ou classes Vamos começar vendo a criação de testes usando funções O pytest irá executar todas as funções que começarem com test caso a função execute até o final sem levantar nenhum erro o teste passa se ocorrer qualquer erro durante a execução da função o teste falha e a informação do erro é exibida junto com os resultados do teste 932 Escrevendo funções de teste com o Pytest Para escrever nossos testes usamos o comando assert para verificar se a condição que queremos é atendida ou não ele nos permite avaliar qualquer expressão lógica e levanta um erro do tipo AssertionError caso ela seja avaliada para falso É possível gerar erros personalizados como veremos mais adiante na seção 94 Abra uma Shell do Python e pratique o uso do assert Siga os exemplos da Codificação 98 5 O asterisco indica que o resto do nome do arquivo não importa podem ser quaisquer caracteres válidos para nomes de arquivos 4 Caso não saiba adicionar um caminho à variável de ambiente PATH uma rápida pesquisa no google irá te trazer diversos tutoriais sobre como editar esta variável de ambiente do seu sistema operacional Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Codificação 98 Exemplos de uso do comando assert do Python assert True assert 3 2 1 assert False Fonte do autor 2021 As duas primeiras expressões avaliam para True portanto não há nenhum retorno do comando assert já a última avalia para False e levanta o erro mostrado na Codificação 99 Codificação 99 Exemplo do erro levantado pelo comando assert Traceback most recent call last File stdin line 1 in module AssertionError Fonte do autor 2021 O pytest captura o erro e faz uma introspecção para avaliar o motivo que o gerou mostrando o resultado na tela para nós Vamos então alterar nosso código criando duas funções de teste Altere o código do arquivo testmeumodulopy para corresponder à Codificação 910 Codificação 910 Funções de teste do arquivo testmeumodulopy from meumodulo import soma2 def test1numero2 assert soma22 4 def test2numero5 assert soma25 7 Fonte do autor 2021 A Figura 93 mostra ambos os arquivos no VSCode lembrando que para o teste funcionar da forma que fizemos eles precisam estar na mesma pasta Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 93 Visualização do código no VSCode Fonte do autor 2021 933 Executando os testes com o Pytest O VSCode nos traz alguns atalhos e consegue gerenciar a execução dos testes de modo que podemos escolher executar um por um ou todos de uma vez mas é importante aprender o funcionamento usando a linha de comando assim não ficamos dependentes de uma ferramenta específica Para executar o pytest no terminal há pelo menos três maneiras diferentes 1 pytest Digitando apenas o comando no terminal o pytest irá buscar e executar todos os testes da pasta atual e suas subpastas 2 pytest caminhoparaarquivotestpy Digitando o comando no terminal seguido do nome do arquivo que queremos executar o pytest irá executar apenas os testes contidos neste arquivo sem fazer a busca por arquivos de teste e portanto nesse caso o nome do arquivo não importa 3 py m pytest Windows python3 m pytest Linux e Mac Precedendo qualquer uma das opções anteriores por python m fará com que o pytest seja executado a partir do interpretador do python como um módulo Dependendo da forma como o pytest tenha sido instalado pode ser que o seu comando como mostrado nos itens 1 e 2 não seja reconhecido no terminal então a forma do item 3 pode ser uma solução mais rápida que atualizar a PATH ou reinstalar o Python Um guia completo da utilização do pytest no terminal de comandos pode ser visto na documentação oficial KREGEL 2020 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS 934 Interpretando os resultados do Pytest Após a execução do pytest será exibido no terminal um resumo sobre os testes encontrados e executados uma saída com detalhes do erro para cada teste que falhou e por fim uma versão resumida dos erros nos testes que falharam Vejamos a saída para o exemplo dado acima 9341 Resumo dos testes coletados Codificação 911 Resumo dos testes do arquivo testmeumodulopy PS EPOO pytest test session starts platform win32 Python 391 pytest622 py1100 pluggy0131 rootdir EPOO collected 2 items aula09 estmeumodulopy F 100 Fonte do autor 2021 Podemos ver as informações da plataforma sistema operacional e versões do interpretador do Python e do pytest diretório raiz a partir do qual o comando de testes foi executado a quantidade de testes encontrados e coletados pela busca automática e por fim na última linha temos os arquivos de teste executados um ponto para testes bem sucedidos e uma letra F para testes com falha a porcentagem de testes executados independente de terem passado ou não Caso sejam encontrados mais de um arquivo de testes haverá uma linha para cada um 9342 Saída detalhada dos testes Codificação 912 Saída detalhada dos testes do arquivo testmeumodulopy FAILURES test2numero5 def test2numero5 assert soma25 7 E assert 10 7 E where 10 soma25 aula09 estmeumodulopy9 AssertionError Fonte do autor 2021 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Podemos ver aqui uma seção com o nome do teste que falhou em seguida a linha de definição deste teste e a introspecção do assert que levantou o erro indicando tanto o código da linha que levantou o erro quanto os valores que foram avaliados durante a execução do teste Por fim temos novamente o nome do arquivo mas dessa vez seguido de um número que representa a linha do código em que houve o erro durante o teste e o tipo do erro Nesse caso podemos concluir que a chamada à função soma2 com o valor 5 retornou o valor 10 que quando comparado com o valor esperado 7 resultou em False e por isso o erro no assert 9343 Saída resumida dos testes Codificação 913 Saída resumida dos testes do arquivo testmeumodulopy short test summary info FAILED aula09testmeumodulopytest2numero5 assert 10 7 1 failed 1 passed in 029s Fonte do autor 2021 Na saída resumida vemos uma lista de testes que falharam que inclui o nome do arquivo o nome do teste e a comparação que falhou e em seguida um resumo geral da execução indicando quantos testes falharam e passaram e o tempo de execução A Figura 94 mostra a saída vista no terminal do VSCode Figura 94 Visualização da saída dos testes no terminal do VSCode Fonte do autor 2021 Após analisar o resultado dos nossos testes vemos que a função soma2 está incorreta pois ao receber o valor 5 não retornou o valor esperado que era 5 2 7 Portanto vamos corrigir o código e executar novamente os testes Veja a Figura 95 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 95 Visualização da saída dos testes no terminal do VSCode após correção do código original Fonte Elaborado pelo autor No momento de criar um teste não nos importa a implementação da função apenas o que ela faz isto é o que ela precisa receber e o que irá retornar Com isso podemos ver um pouco da importância de se construir casos de teste adequados e de estudar o motivo que fez os testes não passarem Um outro ponto muito importante é que os testes são uma ferramenta para nos auxiliar mas não são absolutos e não estão acima do nosso discernimento como programadores ao avaliar o código pois mesmo estando incorreta a primeira versão da função passou em um teste Devemos pensar nos casos de testes de maneira a cobrir o maior número de situações diferentes que seja viável Tente pensar em outros testes para a função acima Há outros valores que podem gerar situações semelhantes à do primeiro teste 94 Erros e exceções Vimos em LP que podemos agrupar os erros em programação em três categorias de acordo com sua origem quando eles ocorrem 1 Erros de sintaxe são erros em que o interpretador não é capaz de entender as instruções pois elas não seguem as regras da linguagem Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS 2 Erros de execução ocorrem quando as regras estão corretas mas por algum motivo não é possível executar a ação pedida 3 Erros de semântica são erros na lógica implementada Do ponto de vista do interpretador nada está errado e a execução é bem sucedida mas a ação realizada não condiz com o comportamento esperado No primeiro tipo de erro os de sintaxe o interpretador indica o arquivo e a linha na qual ele encontrou o erro e inclui também um marcador na região em que o erro foi detectado Os erros de sintaxe devem ser corrigidos para que o código possa ser executado e como é um erro que está escrito diretamente no código fonte é possível garantir que todos eles sejam eliminados Veja no exemplo da Figura 96 que nenhum código é executado pois o interpretador não é capaz de começar a execução já que estamos quebrando uma das regras de sintaxe do Python no caso estamos tentando atribuir um valor a uma palavra reservada da linguagem o comando return Figura 96 Exemplo de erro de sintaxe ao executar um arquivo py Fonte do autor 2021 Já com erros de execução o segundo tipo não é possível eliminálos pois muitas vezes eles ocorrem em virtude de elementos que fogem ao controle do programador como por exemplo uma falha na conexão com o banco de dados uma entrada incorreta do usuário uma falha de comunicação com uma API etc A estes erros normalmente damos o nome de exceções e para evitar que eles façam a nossa aplicação parar de funcionar existe o tratamento de exceções que veremos em seguida na seção 943 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS E por fim em relação ao terceiro tipo de erro os de semântica a melhor forma de lidar com eles é a criação de testes automatizados como começamos a ver neste capítulo e que irão testar o funcionamento correto de uma aplicação ou software com base no comportamento esperado definido no teste Neste caso é preciso que o programador escreva os testes manualmente pois o interpretador não tem como saber o que está errado dado que a execução é finalizada com sucesso independentemente de produzir ou não o resultado esperado Em relação aos erros de execução o segundo tipo podemos distinguir duas situações o lançamento ou levantamento de uma exceção e o seu respectivo tratamento Ambas as partes não precisam acontecer sempre por exemplo em um trecho da aplicação podemos apenas levantar exceções que serão tratadas ou não pelo código cliente e em outra podemos apenas tratar exceções que são levantadas por algum 6 módulo que estamos usando aqui nós seríamos o cliente Ou podemos ter as duas coisas acontecendo na mesma aplicação uma parte do código levanta uma exceção que será tratada em outra parte da mesma aplicação 941 Lançamento de exceções Para lançar uma exceção em Python usamos a palavra reservada raise e 7 podemos lançar qualquer exceção da lista de exceções integradas à linguagem que pode ser vista na documentação PSF 2021b Veja o exemplo da Codificação 914 Codificação 914 Lançamento de uma exceção do tipo TypeError def incrementaintn if not isinstancen int raise TypeErrorn deve ser um inteiro return n 1 Fonte do autor 2021 Neste exemplo caso a função seja chamada com um valor que não seja um número inteiro o fluxo de execução será interrompido pelo comando raise que irá encerrar a função e retornar uma mensagem de erro Esse retorno não é o mesmo retorno que ocorre quando usamos a palavra chave return ou seja não é possível atribuílo a uma variável e ele continuará subindo na pilha de execução até que seja tratado ou chegue no módulo principal momento em que o processo em execução é encerrado prematuramente mostrando na tela a mensagem de erro Para entender um pouco melhor o que significa o erro subir ou ser elevado podemos pensar que toda vez que chamamos uma função dentro de outra a função atual fica pausada esperando a função chamada encerrar a sua execução e retornar Caso a 7 raise pode ser traduzido para levantar ou elevar 6 O termo cliente aqui se refere a qualquer programa ou código que consuma faça uso do nosso código Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS função retorne seu valor normalmente o fluxo de execução continua Caso ela retorne um erro e este erro não seja tratado a função que recebeu como retorno o erro repassao para quem a chamou e assim sucessivamente Veja o exemplo da codificação 915 na qual a função calculaidade é chamada com um número do tipo float como argumento Codificação 915 Código com lançamento de um erro do tipo TypeError def incrementaintn if not isinstancen int raise TypeErrorn deve ser um inteiro return n 1 def calculaidadeidade novaidade incrementaintidade printesse código não é executado se der erro na linha acima return novaidade def main printexecutando a função principal resposta calculaidade205 printesse código não será executado se der erro na linha acima printa nova idade é resposta if name main printchamando a função principal main printesse código não será executado se der erro na linha acima Fonte do autor 2021 O erro que ocorreu na função incrementaint foi elevado para a função calculaidade que por sua vez foi elevado para a função main e por fim foi elevado para o programa principal de onde a função main foi chamada Como em nenhum momento fizemos o tratamento deste erro a execução do programa foi interrompida e tal informação é mostrada na tela onde conseguimos ver todo o caminho percorrido pelo erro no que chamamos em inglês de Traceback como mostra a figura 97 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 97 Visualização do traceback do erro na Codificação 911 Fonte do autor 2021 No exemplo que acabamos de ver faz sentido lançar um TypeError pois estamos falando exatamente de um erro de tipo o dado fornecido não é do tipo correto No entanto nem sempre o Python terá uma classe que seja adequada para representar as exceções que estamos prevendo em nossa aplicação portanto é possível criarmos nossas próprias exceções usando o conceito de herança que vimos na introdução a POO 942 Criação de exceções Em Python toda exceção deve herdar da classe Exception ou de outra classe que por sua vez herde de Exception Isto é toda nova exceção deve ser uma descendente de Exception filha neta etc o que garante que o nosso erro ou exceção personalizado irá herdar todos os comportamentos mínimos necessários para que o Python possa identificála como uma exceção E é especialmente importante para que um bloco except Exception seja capaz de pegar todas as exceções que não sejam específicas como veremos a seguir na seção 943 Imagine que estamos desenvolvendo um sistema de cadastro para uma clínica veterinária uma funcionalidade que precisaremos implementar será a de criar a ficha dos animais que serão ali tratados o que podemos modelar em uma classe Paciente Caso aconteça alguma falha durante a criação como por exemplo se o campo nome não for uma string ou estiver vazio podemos levantar um erro neste método Veja na Codificação 916 um exemplo de implementação simplificada da classe Paciente na implementação real desta classe o método inicializador teria mais parâmetros Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Codificação 916 Criação e utilização de exceção personalizada class NameIsEmptyErrorException pass class Paciente def initself nome selfpaciente nome restante do código que inicializa os dados do paciente property def pacienteself return selfpaciente pacientesetter def pacienteself nome if not isinstancenome str raise TypeErrornome inválido if nome raise NameIsEmptyErrornome é obrigatório selfpaciente nome Fonte do autor 2021 Na classe Paciente da codificação 916 estamos usando uma propertysetter para atribuir o valor do atributo não público paciente E no setter fazemos uma validação do valor recebido e só permitimos a atribuição caso este valor seja uma string e não seja vazio É comum fazermos a verificação logo no começo e levantarmos os erros pertinentes interrompendo o fluxo de execução Dessa forma garantimos que o código que irá consumir esta classe irá falhar o mais cedo possível caso usea de maneira incorreta permitindo ao desenvolvedor perceber e corrigir o erro 943 Tratamento de exceções O tratamento de exceções é extremamente importante para garantir que a aplicação ou programa continue funcionando ao encontrar algo inesperado em relação ao seu funcionamento normal Ele captura o erro impedindo que ele continue subindo na pilha de execução e permite desvios no fluxo para que sejam tomadas as medidas necessárias em cada caso o que pode incluir enviar mensagens aos usuários escrever mensagens de log reagendar a tarefa que falhou fechar um arquivo aberto ou encerrar a conexão com o banco de dados entre outros Observe que essa situação pode ser inesperada do ponto de vista do funcionamento padrão mas do ponto de vista de quem está programando a aplicação as Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS falhas são sempre esperadas pois em uma situação real não é possível controlar todo o ambiente e garantir que o usuário não irá digitar um valor inválido que o servidor do banco de dados não irá passar por uma instabilidade ou que a conexão não será interrompida porque uma API estava sobrecarregada e demorou demais para responder Portanto faz parte do nosso trabalho identificar os pontos suscetíveis a falha e implementar o tratamento adequado Em Python esse tratamento é feito com o bloco tryexcept como mostra a Codificação 917 Codificação 917 Sintaxe do bloco tryexcept em Python try código suscetível a falha except código executado após ocorrer um erro else código executado apenas se nenhum erro ocorrer finally código executado sempre Fonte do autor 2021 Durante o tratamento de uma exceção o único trecho de código seguro é aquele contido no bloco do try ou seja qualquer erro que ocorrer ali será capturado e o fluxo redirecionado para os blocos except No entanto se ocorrer um erro nos demais blocos esse erro irá seguir o fluxo padrão de erros e será elevado na pilha de execução É possível aninhar blocos tryexcept mas em geral isso é considerado uma má prática pois piora a legibilidade do código Veja na Codificação 918 um exemplo de código que utiliza a classe Paciente da Codificação 916 Codificação 918 Exemplo de uso do bloco tryexcept em Python from paciente import Paciente NameIsEmptyError try nome inputDigite o nome do paciente p Pacientenome except TypeError printO nome deve ser uma string except NameIsEmptyError printO nome não pode ser uma string vazia except Exception as e printOcorreu um erro inesperado ao criar o objeto printinformações do erro e Fonte do autor 2021 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Aqui podemos observar que há um encadeamento dos tipos de exceções que podem ser capturados seguindo uma lógica parecida com a dos blocos elif no Python isto é será executado o bloco except da primeira exceção que corresponder sendo os blocos subsequentes ignorados pulando direto pro bloco do finally se houver Devido a natureza da função input que sempre retorna uma string não é possível termos um erro de tipo e devido a simplicidade deste exemplo dificilmente teremos um erro genérico portanto neste exemplo simplificado poderíamos capturar apenas a exceção NameIsEmptyError Caso queira testar a captura dos demais erros podemos introduzir erros propositais no código Faça o teste substituindo no bloco do try a instrução do input por nome 23 ou forçando também no bloco do try o levantamento de um erro genérico com raise Exceptionerro genérico 8 Há ainda três pontos importantes sobre o tratamento de exceções no Python 1 Como no exemplo dado é possível capturar o objeto de exceção levantado pelo Python em uma variável usando o comando as para fazer a atribuição como no exemplo da codificação 918 2 É possível agrupar mais de um tipo de exceção no mesmo bloco except colocandoas em uma tupla Codificação 919 Agrupamento de mais de um tipo de exceção try except TypeError ValueError ZeroDivisionError Fonte do autor 2021 3 Podemos também apenas interceptar a exceção fazer algum tipo de tratamento como por exemplo salvar em um registro de log a ocorrência e deixála seguir o seu fluxo natural para ser tratada em outra parte da aplicação Para isso basta usar o comando raise sozinho dentro de um bloco except Codificação 920 Interceptando a exceção except loggerexceptionsalvando log da exceção raise Fonte do autor 2021 Com isso a mesma exceção que ocorreu originalmente será relançada com o comando raise após a execução do tratamento parcial 8 Observe que levantar um erro dentro de um bloco try fará com que esse erro seja capturado e tratado no próprio bloco portanto isso não é uma prática utilizada normalmente servindo aqui apenas para ilustrar o exemplo dado já que no código do exemplo não há margem para um erro genérico Alternativamente poderíamos ter editado a nossa classe para ao receber um nome específico levantar um erro genérico este exemplo seria mais perto de um exemplo de utilização real do tratamento de exceções Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Bibliografia BECK K Testdriven development by example Boston AddisonWesley Professional 2002 BECK K Quora why does kent beck refer to the rediscovery of testdriven development 2012 Disponível em httpsqraepGIvYU Acesso em 18 abr 2021 KREGEL H Pytest usage and invocations 2020 Disponível em httpsdocspytestorgenstableusagehtml Acesso em 10 fev 2021 PSF Expressions conditional expressions 2021a Disponível em httpsdocspythonorg3referenceexpressionshtmlconditionalexpressions Acesso em 07 fev 2021 PSF Builtin exceptions exception hierarchy 2021b Disponível em httpsdocspythonorg3libraryexceptionshtmlexceptionhierarchy Acesso em 18 abr 2021 Núcleo de Educação a Distância Faculdade Impacta

Envie sua pergunta para a IA e receba a resposta na hora

Recomendado para você

Playlist YouTube Marketing Digital - Estrategias e Conteudo

1

Playlist YouTube Marketing Digital - Estrategias e Conteudo

Linguagens de Programação

FIT

Links de Vídeos Educacionais

1

Links de Vídeos Educacionais

Linguagens de Programação

FIT

Persistência de Dados em Arquivos com Python

21

Persistência de Dados em Arquivos com Python

Linguagens de Programação

FIT

Características Funcionais do Python: Decoradores e Classes Abstratas

15

Características Funcionais do Python: Decoradores e Classes Abstratas

Linguagens de Programação

FIT

Introdução ao HTML: Tópicos e Objetivos de Aprendizagem

32

Introdução ao HTML: Tópicos e Objetivos de Aprendizagem

Linguagens de Programação

FIT

Introdução a Padrões de Projeto e Princípios do SOLID

14

Introdução a Padrões de Projeto e Princípios do SOLID

Linguagens de Programação

FIT

AC1-Programacao-Orientada-a-Objetos-Python-Questoes-e-Respostas

18

AC1-Programacao-Orientada-a-Objetos-Python-Questoes-e-Respostas

Linguagens de Programação

FIT

AC1 Desenvolvimento Web - Tecnologias Server-Side, Códigos de Erro e Estrutura HTML

5

AC1 Desenvolvimento Web - Tecnologias Server-Side, Códigos de Erro e Estrutura HTML

Linguagens de Programação

FIT

AC3-POO-TDD-Excecoes-e-Padroes-de-Projeto-Questoes-para-Estudo

10

AC3-POO-TDD-Excecoes-e-Padroes-de-Projeto-Questoes-para-Estudo

Linguagens de Programação

FIT

Texto de pré-visualização

9 TEXTO BASE PROGRAMAÇÃO ORIENTADA A OBJETOS Faculdade IMPACTA PROGRAMAÇÃO ORIENTADA A OBJETOS Texto base 9 Testes unitários e tratamento de erros Prof MSc Rafael Maximo Carreira Ribeiro Resumo Neste capítulo iremos aprender sobre dois conceitos muito importantes na programação de todo tipo de aplicação ou software o tratamento de exceções e a criação e execução de testes unitários automatizados Faremos também uma breve introdução a metodologia TDD que é o Desenvolvimento Guiado por Testes em português 91 Introdução Vimos em LP que linguagens de programação fazem parte do que chamamos de linguagens formais pois possuem um conjunto definido de regras e não permitem nenhuma margem para ambiguidades Portanto um computador irá executar exatamente aquilo que lhe é instruído e pode nos dizer facilmente quando há uma instrução que não segue as regras da linguagem ou que tenta realizar uma operação não permitida erros de sintaxe e execução respectivamente Já com relação a erros de lógica somos nós os responsáveis por garantir que nosso código esteja fazendo a coisa certa Por exemplo imagine que ao fazer um depósito na sua conta o programa do banco tente adicionar um valor que não seja um número Isso configuraria um erro de execução pois não é possível somar um número a um nãonúmero em Python e o computador nos informaria desse erro Imagine agora outro erro em que o programa subtraia o valor depositado do seu saldo ao invés de somálo Isso caracteriza um erro de lógica também chamado de erro de semântica pois há uma divergência entre o que o código faz e o que esperávamos que fosse feito Neste caso computador não tem como saber que isso está errado já que ele executa fielmente suas instruções então se há um erro de lógica somos nós os responsáveis por encontrálo e corrigilo Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS 92 Desenvolvimento Guiado por Testes TDD O desenvolvimento guiado por testes é uma técnica para o desenvolvimento de software em que os requisitos são convertidos em testes antes de começarmos a programar o software propriamente dito Ou seja primeiro escrevemos os testes e só depois escrevemos o código que deverá cumprir as tarefas para as quais os testes foram escritos Essa metodologia foi apresentada por Kent Beck 2002 no começo dos anos 2000 Segundo o próprio autor BECK K 2012 ele apenas redescobriu essa técnica que já era usada por programadores desde a época dos cartões perfurados 921 Ciclos do TDD O TDD é constituído por ciclos de desenvolvimento e cada ciclo possui 3 fases Red Green Refactor A última fase é também conhecida como a fase azul Blue Na fase vermelha escrevemos os testes para a nova funcionalidade que não existe ainda na fase verde escrevemos o código que implementa a funcionalidade sendo testada e na fase azul refatoramos o código aprimorando a solução inicial da fase verde Podemos descrever mais detalhadamente cada fase como RED Adicionamos um novo teste para a nova funcionalidade e rodamos todo o conjunto de testes Nessa fase o teste deverá obrigatoriamente falhar pois a funcionalidade ainda não foi implementada Se o teste passar há algo errado com ele e precisamos refatorálo até que ele falhe GREEN Implementamos a nova funcionalidade e executamos os testes até que o novo teste passe sem quebrar nenhum outro teste O objetivo aqui é escrever a solução mais simples possível que faça o teste passar sem precisar se preocupar com padrões de projeto com os princípios do SOLID com deixar o código elegante ou com a eficiência do nosso algoritmo tudo isso ficará para a etapa de refatoração do código BLUE Com o teste passando sabemos duas coisas 1 a nova funcionalidade está implementada 2 não introduzimos nenhuma modificação que quebre outras funcionalidades O objetivo nesta fase é melhorar desempenho legibilidade e manutenabilidade do código e com os testes agora temos segurança para fazer melhorias na implementação que podem envolver entre outros renomear as variáveis e melhorar a legibilidade do código aplicar os princípios do SOLID que sejam relevantes reorganizar o código de acordo com a responsabilidade de cada classe aplicar um ou mais padrões de projeto que sejam pertinentes Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS remover código duplicado e valores hardcoded 1 subdividir os métodos e funções se necessário 922 Principais vantagens do TDD O ciclo do TDD é então repetido para cada nova funcionalidade que precisamos implementar No começo pode parecer contraintuitivo programar primeiro o teste mas com o tempo irá se tornar natural e no médio e longo prazo traz muitos benefícios como por exemplo Código mais simples e fácil de ler e dar manutenção Código mais flexível e adaptável com menos acoplamentos e interfaces mais claras e classes mais direcionadas De certa forma podemos dizer que a prática correta do TDD automaticamente leva à aplicação do princípio da responsabilidade única o S do SOLID Maior atendimento dos requisitos uma vez que precisamos pensar nos testes antes de escrever o código acabamos fazendo um exercício maior de interpretação dos requisitos e melhoramos o nosso entendimento sobre o comportamento da nova funcionalidade Segurança ao desenvolver pois sabemos que caso nossa implementação quebre alguma outra funcionalidade seremos avisados pelos testes ainda durante o desenvolvimento e poderemos corrigir o problema antes de introduzir bugs silenciosamente na aplicação 923 Limitações do TDD Assim como qualquer outra metodologia de desenvolvimento o TDD também apresenta algumas limitações como por exemplo O TDD por usar principalmente testes unitários não é capaz de testar completamente as partes da aplicação que exigem outros tipos de testes como por exemplo conexões com um banco de dados configurações de rede no ambiente interfaces de usuário etc Nestes casos devemos testar a parte lógica interna da nossa aplicação usando um mock para representar as partes externas 2 às quais não temos controle Para que as vantagens do TDD possam ser aproveitadas toda a equipe envolvida no projeto precisa ter conhecimento da metodologia caso contrário é possível que parte da equipe encare os testes como perda de tempo 2 mock é um objeto que simula o objeto real por exemplo uma conexão com um banco de dados No objeto de mock podemos definir o comportamento esperado daquela conexão se vai dar erro ou não qual o erro qual o retorno etc E assim podemos testar a nossa lógica interna em cada uma dessas situações 1 Hardcoded ou codificação rígida é quando colocamos um valor fixo no próprio código fonte por exemplo quando colocamos a url para uma api como uma string no próprio código ao invés de ler este valor de um arquivo de configurações ou variável de ambiente Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Projetos com um grande número de testes podem passar uma falsa sensação de segurança e isso pode levar a equipe a negligenciar outros tipos de testes O conjunto de testes precisa de manutenção assim como o restante do código então testes mal escritos podem acabar aumentando o custo de manutenção da aplicação pois será necessário mais tempo de desenvolvimento para corrigilos Um exemplo é o uso de testes com mensagens de erro escritas como strings literais no código que poderão eventualmente falhar após uma atualização de algum módulo na qual as mensagens de erro sejam alteradas O desenvolvedor irá escrever tanto os testes quanto o código então caso haja um erro de interpretação dos requisitos do projeto é provável que tanto o código quanto os testes compartilhem esse mesmo erro e isso passe sem ser percebido Portanto é necessário estar atento a esse tipo de problema sendo que ter o códigotestes revisados por outros desenvolvedores ajuda a mitigálo 93 Testes Unitários e Testes Automatizados O exemplo dado na introdução é simples e pode parecer besta mas em situações reais as aplicações e programas são mais complexos com diversos módulos diferentes que interagem entre si de maneira muitas vezes não linear e interdependente Sendo assim nem sempre conseguimos garantir que uma alteração em um trecho de código não irá afetar outras áreas da aplicação de maneira inesperada Para resolver isso após alterarmos alguma coisa no código podemos testar nossa aplicação para garantir que tudo esteja funcionando como antes mas conforme a aplicação cresce fazer tais testes manualmente demandará cada vez mais tempo e eventualmente se tornará inviável A resposta óbvia é portanto a utilização de testes automatizados Existem diversos tipos de testes mas agora vamos estudar os testes unitários ou testes de unidade Testes unitários servem para testar uma unidade isolada de código para garantir que ela faz aquilo a que se propõe isso pode ser o teste de uma função de um método da criação de um objeto com as propriedades corretas etc Vamos criar uma função que recebe um valor inteiro e nos retorna esse valor mais 2 Para isso crie o arquivo meumodulopy na pasta aula09 e digite o código da Codificação 91 Codificação 91 Exemplo de função que retorna número recebido mais dois def soma2numero return numero 2 Fonte do autor 2021 Talvez você tenha percebido que há um erro na função Esse erro é proposital e vamos supor que tenha passado despercebido por hora Como sabemos o que a função Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS deve fazer podemos pensar em alguns casos de teste para verificar seu funcionamento como mostra a Tabela 91 Tabela 91 Casos de teste para a função soma2 Caso de teste Entrada Saída esperada 1 2 4 2 5 7 Fonte do autor 2021 Agora adicione o trecho de código da Codificação 92 ao arquivo anterior para testar nossa função Codificação 92 Código de teste inicial test1 soma22 4 test2 soma25 7 msg1 sucesso if test1 else falha msg2 sucesso if test2 else falha printfResultado do teste 1 msg1 printfResultado do teste 2 msg2 Fonte do autor 2021 Neste código estamos guardando o resultado das verificações em uma flag booleana uma variável que guarda um valor booleano True ou False referente ao status de algo em nosso código Em seguida usamos o operador ternário para decidir 3 qual mensagem deve ser exibida na tela e por fim exibimos as mensagens do resultado de cada teste A Figura 91 mostra o resultado da execução deste código no terminal 3 Este operador foi introduzido com a PEP 0308 e funciona assim na expressão x if C else y primeiro a condição C é avaliada se resultar em True x é avaliado e o valor retornado caso contrário y será avaliado e retornado PSF 2021a Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 91 Execução da primeira versão dos testes automatizados Fonte do autor 2021 Codificação 93 Comando utilizado na Figura 91 e respectiva saída no terminal python aula04meumodulopy Resultado do teste 1 sucesso Resultado do teste 2 falha Fonte do autor 2021 A primeira coisa que podemos fazer para melhorar nossos testes é criálos em um arquivo separado pois não é uma boa prática deixar nossas funções e nossos testes em um mesmo arquivo Portanto crie na mesma pasta um arquivo chamado testmeumodulopy e copie para lá o código dos testes Para executálos precisamos acessar a nossa função que continua no arquivo original então para isso vamos importála colocando na primeira linha do arquivo a instrução da Codificação 94 Codificação 94 Instrução para importação da função soma2 no arquivo de teste from meumodulo import soma2 Fonte do autor 2021 A criação e importação de módulos em Python é um assunto já visto em outra aula mas da forma acima não precisamos alterar o código do teste pois estamos importando a partir de meumodulopy a função soma2 O resultado pode ser visto na Figura 92 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 92 Execução da segunda versão dos testes automatizados Fonte do autor 2021 Conseguimos separar as responsabilidades de cada arquivo então agora poderíamos tentar melhorar as mensagens exibidas incluindo informações dos valores esperados e obtidos entre outras No entanto fazer isso para todos os testes nos daria muito trabalho extra com configuração e formatação tirando o foco do desenvolvimento dos testes que verificam a lógica da aplicação em si Para nos ajudar nisso vamos usar o pytest uma ferramenta de testes automatizados que simplifica a construção e execução dos testes 931 Instalando o Pytest A instalação do pytest é feita através do gerenciador de pacotes do Python que já usamos em aulas passadas o PIP Execute no terminal o comando da Codificação 95 referente ao sistema operacional que estiver utilizando Codificação 95 Comando para instalação do pytest py m pip install U pytest Windows python3 m pip install U pytest Linux e Mac Fonte do autor 2021 Caso ao final da instalação o pip mostre um aviso warning informando que o caminho para a pasta de pacotes do Python não está na PATH do sistema adicione tal Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS pasta a variável de ambiente PATH do seu usuário Em seguida verifique se a 4 instalação foi bem sucedida conferindo a versão instalada como na Codificação 96 Codificação 96 Verificação da instalação correta do módulo pytest pytest version pytest 622 Fonte do autor 2021 Caso o comando da Codificação 96 não funcione corretamente tente executar o comando da codificação 97 Se isso tampouco funcionar é possível que sua instalação do Python esteja com algum erro ou que não tenha sido adicionado à PATH do sistema para Windows Às vezes reinstalar o Python pode resolver o problema Codificação 97 Verificação da instalação correta do módulo pytest py m pytest version Windows python3 m pytest version Linux e Mac pytest 622 Fonte do autor 2021 Ao executar o pytest ele irá automaticamente buscar na pasta atual e em todas as subpastas por arquivos da forma testpy ou testpy ou seja que comecem ou terminem com a palavra test seguida ou precedida respectivamente de um sublinhado 5 Após encontrar os arquivos que correspondem ao padrão de nome o pytest busca os testes em si que podem ser funções ou classes Vamos começar vendo a criação de testes usando funções O pytest irá executar todas as funções que começarem com test caso a função execute até o final sem levantar nenhum erro o teste passa se ocorrer qualquer erro durante a execução da função o teste falha e a informação do erro é exibida junto com os resultados do teste 932 Escrevendo funções de teste com o Pytest Para escrever nossos testes usamos o comando assert para verificar se a condição que queremos é atendida ou não ele nos permite avaliar qualquer expressão lógica e levanta um erro do tipo AssertionError caso ela seja avaliada para falso É possível gerar erros personalizados como veremos mais adiante na seção 94 Abra uma Shell do Python e pratique o uso do assert Siga os exemplos da Codificação 98 5 O asterisco indica que o resto do nome do arquivo não importa podem ser quaisquer caracteres válidos para nomes de arquivos 4 Caso não saiba adicionar um caminho à variável de ambiente PATH uma rápida pesquisa no google irá te trazer diversos tutoriais sobre como editar esta variável de ambiente do seu sistema operacional Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Codificação 98 Exemplos de uso do comando assert do Python assert True assert 3 2 1 assert False Fonte do autor 2021 As duas primeiras expressões avaliam para True portanto não há nenhum retorno do comando assert já a última avalia para False e levanta o erro mostrado na Codificação 99 Codificação 99 Exemplo do erro levantado pelo comando assert Traceback most recent call last File stdin line 1 in module AssertionError Fonte do autor 2021 O pytest captura o erro e faz uma introspecção para avaliar o motivo que o gerou mostrando o resultado na tela para nós Vamos então alterar nosso código criando duas funções de teste Altere o código do arquivo testmeumodulopy para corresponder à Codificação 910 Codificação 910 Funções de teste do arquivo testmeumodulopy from meumodulo import soma2 def test1numero2 assert soma22 4 def test2numero5 assert soma25 7 Fonte do autor 2021 A Figura 93 mostra ambos os arquivos no VSCode lembrando que para o teste funcionar da forma que fizemos eles precisam estar na mesma pasta Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 93 Visualização do código no VSCode Fonte do autor 2021 933 Executando os testes com o Pytest O VSCode nos traz alguns atalhos e consegue gerenciar a execução dos testes de modo que podemos escolher executar um por um ou todos de uma vez mas é importante aprender o funcionamento usando a linha de comando assim não ficamos dependentes de uma ferramenta específica Para executar o pytest no terminal há pelo menos três maneiras diferentes 1 pytest Digitando apenas o comando no terminal o pytest irá buscar e executar todos os testes da pasta atual e suas subpastas 2 pytest caminhoparaarquivotestpy Digitando o comando no terminal seguido do nome do arquivo que queremos executar o pytest irá executar apenas os testes contidos neste arquivo sem fazer a busca por arquivos de teste e portanto nesse caso o nome do arquivo não importa 3 py m pytest Windows python3 m pytest Linux e Mac Precedendo qualquer uma das opções anteriores por python m fará com que o pytest seja executado a partir do interpretador do python como um módulo Dependendo da forma como o pytest tenha sido instalado pode ser que o seu comando como mostrado nos itens 1 e 2 não seja reconhecido no terminal então a forma do item 3 pode ser uma solução mais rápida que atualizar a PATH ou reinstalar o Python Um guia completo da utilização do pytest no terminal de comandos pode ser visto na documentação oficial KREGEL 2020 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS 934 Interpretando os resultados do Pytest Após a execução do pytest será exibido no terminal um resumo sobre os testes encontrados e executados uma saída com detalhes do erro para cada teste que falhou e por fim uma versão resumida dos erros nos testes que falharam Vejamos a saída para o exemplo dado acima 9341 Resumo dos testes coletados Codificação 911 Resumo dos testes do arquivo testmeumodulopy PS EPOO pytest test session starts platform win32 Python 391 pytest622 py1100 pluggy0131 rootdir EPOO collected 2 items aula09 estmeumodulopy F 100 Fonte do autor 2021 Podemos ver as informações da plataforma sistema operacional e versões do interpretador do Python e do pytest diretório raiz a partir do qual o comando de testes foi executado a quantidade de testes encontrados e coletados pela busca automática e por fim na última linha temos os arquivos de teste executados um ponto para testes bem sucedidos e uma letra F para testes com falha a porcentagem de testes executados independente de terem passado ou não Caso sejam encontrados mais de um arquivo de testes haverá uma linha para cada um 9342 Saída detalhada dos testes Codificação 912 Saída detalhada dos testes do arquivo testmeumodulopy FAILURES test2numero5 def test2numero5 assert soma25 7 E assert 10 7 E where 10 soma25 aula09 estmeumodulopy9 AssertionError Fonte do autor 2021 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Podemos ver aqui uma seção com o nome do teste que falhou em seguida a linha de definição deste teste e a introspecção do assert que levantou o erro indicando tanto o código da linha que levantou o erro quanto os valores que foram avaliados durante a execução do teste Por fim temos novamente o nome do arquivo mas dessa vez seguido de um número que representa a linha do código em que houve o erro durante o teste e o tipo do erro Nesse caso podemos concluir que a chamada à função soma2 com o valor 5 retornou o valor 10 que quando comparado com o valor esperado 7 resultou em False e por isso o erro no assert 9343 Saída resumida dos testes Codificação 913 Saída resumida dos testes do arquivo testmeumodulopy short test summary info FAILED aula09testmeumodulopytest2numero5 assert 10 7 1 failed 1 passed in 029s Fonte do autor 2021 Na saída resumida vemos uma lista de testes que falharam que inclui o nome do arquivo o nome do teste e a comparação que falhou e em seguida um resumo geral da execução indicando quantos testes falharam e passaram e o tempo de execução A Figura 94 mostra a saída vista no terminal do VSCode Figura 94 Visualização da saída dos testes no terminal do VSCode Fonte do autor 2021 Após analisar o resultado dos nossos testes vemos que a função soma2 está incorreta pois ao receber o valor 5 não retornou o valor esperado que era 5 2 7 Portanto vamos corrigir o código e executar novamente os testes Veja a Figura 95 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 95 Visualização da saída dos testes no terminal do VSCode após correção do código original Fonte Elaborado pelo autor No momento de criar um teste não nos importa a implementação da função apenas o que ela faz isto é o que ela precisa receber e o que irá retornar Com isso podemos ver um pouco da importância de se construir casos de teste adequados e de estudar o motivo que fez os testes não passarem Um outro ponto muito importante é que os testes são uma ferramenta para nos auxiliar mas não são absolutos e não estão acima do nosso discernimento como programadores ao avaliar o código pois mesmo estando incorreta a primeira versão da função passou em um teste Devemos pensar nos casos de testes de maneira a cobrir o maior número de situações diferentes que seja viável Tente pensar em outros testes para a função acima Há outros valores que podem gerar situações semelhantes à do primeiro teste 94 Erros e exceções Vimos em LP que podemos agrupar os erros em programação em três categorias de acordo com sua origem quando eles ocorrem 1 Erros de sintaxe são erros em que o interpretador não é capaz de entender as instruções pois elas não seguem as regras da linguagem Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS 2 Erros de execução ocorrem quando as regras estão corretas mas por algum motivo não é possível executar a ação pedida 3 Erros de semântica são erros na lógica implementada Do ponto de vista do interpretador nada está errado e a execução é bem sucedida mas a ação realizada não condiz com o comportamento esperado No primeiro tipo de erro os de sintaxe o interpretador indica o arquivo e a linha na qual ele encontrou o erro e inclui também um marcador na região em que o erro foi detectado Os erros de sintaxe devem ser corrigidos para que o código possa ser executado e como é um erro que está escrito diretamente no código fonte é possível garantir que todos eles sejam eliminados Veja no exemplo da Figura 96 que nenhum código é executado pois o interpretador não é capaz de começar a execução já que estamos quebrando uma das regras de sintaxe do Python no caso estamos tentando atribuir um valor a uma palavra reservada da linguagem o comando return Figura 96 Exemplo de erro de sintaxe ao executar um arquivo py Fonte do autor 2021 Já com erros de execução o segundo tipo não é possível eliminálos pois muitas vezes eles ocorrem em virtude de elementos que fogem ao controle do programador como por exemplo uma falha na conexão com o banco de dados uma entrada incorreta do usuário uma falha de comunicação com uma API etc A estes erros normalmente damos o nome de exceções e para evitar que eles façam a nossa aplicação parar de funcionar existe o tratamento de exceções que veremos em seguida na seção 943 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS E por fim em relação ao terceiro tipo de erro os de semântica a melhor forma de lidar com eles é a criação de testes automatizados como começamos a ver neste capítulo e que irão testar o funcionamento correto de uma aplicação ou software com base no comportamento esperado definido no teste Neste caso é preciso que o programador escreva os testes manualmente pois o interpretador não tem como saber o que está errado dado que a execução é finalizada com sucesso independentemente de produzir ou não o resultado esperado Em relação aos erros de execução o segundo tipo podemos distinguir duas situações o lançamento ou levantamento de uma exceção e o seu respectivo tratamento Ambas as partes não precisam acontecer sempre por exemplo em um trecho da aplicação podemos apenas levantar exceções que serão tratadas ou não pelo código cliente e em outra podemos apenas tratar exceções que são levantadas por algum 6 módulo que estamos usando aqui nós seríamos o cliente Ou podemos ter as duas coisas acontecendo na mesma aplicação uma parte do código levanta uma exceção que será tratada em outra parte da mesma aplicação 941 Lançamento de exceções Para lançar uma exceção em Python usamos a palavra reservada raise e 7 podemos lançar qualquer exceção da lista de exceções integradas à linguagem que pode ser vista na documentação PSF 2021b Veja o exemplo da Codificação 914 Codificação 914 Lançamento de uma exceção do tipo TypeError def incrementaintn if not isinstancen int raise TypeErrorn deve ser um inteiro return n 1 Fonte do autor 2021 Neste exemplo caso a função seja chamada com um valor que não seja um número inteiro o fluxo de execução será interrompido pelo comando raise que irá encerrar a função e retornar uma mensagem de erro Esse retorno não é o mesmo retorno que ocorre quando usamos a palavra chave return ou seja não é possível atribuílo a uma variável e ele continuará subindo na pilha de execução até que seja tratado ou chegue no módulo principal momento em que o processo em execução é encerrado prematuramente mostrando na tela a mensagem de erro Para entender um pouco melhor o que significa o erro subir ou ser elevado podemos pensar que toda vez que chamamos uma função dentro de outra a função atual fica pausada esperando a função chamada encerrar a sua execução e retornar Caso a 7 raise pode ser traduzido para levantar ou elevar 6 O termo cliente aqui se refere a qualquer programa ou código que consuma faça uso do nosso código Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS função retorne seu valor normalmente o fluxo de execução continua Caso ela retorne um erro e este erro não seja tratado a função que recebeu como retorno o erro repassao para quem a chamou e assim sucessivamente Veja o exemplo da codificação 915 na qual a função calculaidade é chamada com um número do tipo float como argumento Codificação 915 Código com lançamento de um erro do tipo TypeError def incrementaintn if not isinstancen int raise TypeErrorn deve ser um inteiro return n 1 def calculaidadeidade novaidade incrementaintidade printesse código não é executado se der erro na linha acima return novaidade def main printexecutando a função principal resposta calculaidade205 printesse código não será executado se der erro na linha acima printa nova idade é resposta if name main printchamando a função principal main printesse código não será executado se der erro na linha acima Fonte do autor 2021 O erro que ocorreu na função incrementaint foi elevado para a função calculaidade que por sua vez foi elevado para a função main e por fim foi elevado para o programa principal de onde a função main foi chamada Como em nenhum momento fizemos o tratamento deste erro a execução do programa foi interrompida e tal informação é mostrada na tela onde conseguimos ver todo o caminho percorrido pelo erro no que chamamos em inglês de Traceback como mostra a figura 97 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 97 Visualização do traceback do erro na Codificação 911 Fonte do autor 2021 No exemplo que acabamos de ver faz sentido lançar um TypeError pois estamos falando exatamente de um erro de tipo o dado fornecido não é do tipo correto No entanto nem sempre o Python terá uma classe que seja adequada para representar as exceções que estamos prevendo em nossa aplicação portanto é possível criarmos nossas próprias exceções usando o conceito de herança que vimos na introdução a POO 942 Criação de exceções Em Python toda exceção deve herdar da classe Exception ou de outra classe que por sua vez herde de Exception Isto é toda nova exceção deve ser uma descendente de Exception filha neta etc o que garante que o nosso erro ou exceção personalizado irá herdar todos os comportamentos mínimos necessários para que o Python possa identificála como uma exceção E é especialmente importante para que um bloco except Exception seja capaz de pegar todas as exceções que não sejam específicas como veremos a seguir na seção 943 Imagine que estamos desenvolvendo um sistema de cadastro para uma clínica veterinária uma funcionalidade que precisaremos implementar será a de criar a ficha dos animais que serão ali tratados o que podemos modelar em uma classe Paciente Caso aconteça alguma falha durante a criação como por exemplo se o campo nome não for uma string ou estiver vazio podemos levantar um erro neste método Veja na Codificação 916 um exemplo de implementação simplificada da classe Paciente na implementação real desta classe o método inicializador teria mais parâmetros Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Codificação 916 Criação e utilização de exceção personalizada class NameIsEmptyErrorException pass class Paciente def initself nome selfpaciente nome restante do código que inicializa os dados do paciente property def pacienteself return selfpaciente pacientesetter def pacienteself nome if not isinstancenome str raise TypeErrornome inválido if nome raise NameIsEmptyErrornome é obrigatório selfpaciente nome Fonte do autor 2021 Na classe Paciente da codificação 916 estamos usando uma propertysetter para atribuir o valor do atributo não público paciente E no setter fazemos uma validação do valor recebido e só permitimos a atribuição caso este valor seja uma string e não seja vazio É comum fazermos a verificação logo no começo e levantarmos os erros pertinentes interrompendo o fluxo de execução Dessa forma garantimos que o código que irá consumir esta classe irá falhar o mais cedo possível caso usea de maneira incorreta permitindo ao desenvolvedor perceber e corrigir o erro 943 Tratamento de exceções O tratamento de exceções é extremamente importante para garantir que a aplicação ou programa continue funcionando ao encontrar algo inesperado em relação ao seu funcionamento normal Ele captura o erro impedindo que ele continue subindo na pilha de execução e permite desvios no fluxo para que sejam tomadas as medidas necessárias em cada caso o que pode incluir enviar mensagens aos usuários escrever mensagens de log reagendar a tarefa que falhou fechar um arquivo aberto ou encerrar a conexão com o banco de dados entre outros Observe que essa situação pode ser inesperada do ponto de vista do funcionamento padrão mas do ponto de vista de quem está programando a aplicação as Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS falhas são sempre esperadas pois em uma situação real não é possível controlar todo o ambiente e garantir que o usuário não irá digitar um valor inválido que o servidor do banco de dados não irá passar por uma instabilidade ou que a conexão não será interrompida porque uma API estava sobrecarregada e demorou demais para responder Portanto faz parte do nosso trabalho identificar os pontos suscetíveis a falha e implementar o tratamento adequado Em Python esse tratamento é feito com o bloco tryexcept como mostra a Codificação 917 Codificação 917 Sintaxe do bloco tryexcept em Python try código suscetível a falha except código executado após ocorrer um erro else código executado apenas se nenhum erro ocorrer finally código executado sempre Fonte do autor 2021 Durante o tratamento de uma exceção o único trecho de código seguro é aquele contido no bloco do try ou seja qualquer erro que ocorrer ali será capturado e o fluxo redirecionado para os blocos except No entanto se ocorrer um erro nos demais blocos esse erro irá seguir o fluxo padrão de erros e será elevado na pilha de execução É possível aninhar blocos tryexcept mas em geral isso é considerado uma má prática pois piora a legibilidade do código Veja na Codificação 918 um exemplo de código que utiliza a classe Paciente da Codificação 916 Codificação 918 Exemplo de uso do bloco tryexcept em Python from paciente import Paciente NameIsEmptyError try nome inputDigite o nome do paciente p Pacientenome except TypeError printO nome deve ser uma string except NameIsEmptyError printO nome não pode ser uma string vazia except Exception as e printOcorreu um erro inesperado ao criar o objeto printinformações do erro e Fonte do autor 2021 Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Aqui podemos observar que há um encadeamento dos tipos de exceções que podem ser capturados seguindo uma lógica parecida com a dos blocos elif no Python isto é será executado o bloco except da primeira exceção que corresponder sendo os blocos subsequentes ignorados pulando direto pro bloco do finally se houver Devido a natureza da função input que sempre retorna uma string não é possível termos um erro de tipo e devido a simplicidade deste exemplo dificilmente teremos um erro genérico portanto neste exemplo simplificado poderíamos capturar apenas a exceção NameIsEmptyError Caso queira testar a captura dos demais erros podemos introduzir erros propositais no código Faça o teste substituindo no bloco do try a instrução do input por nome 23 ou forçando também no bloco do try o levantamento de um erro genérico com raise Exceptionerro genérico 8 Há ainda três pontos importantes sobre o tratamento de exceções no Python 1 Como no exemplo dado é possível capturar o objeto de exceção levantado pelo Python em uma variável usando o comando as para fazer a atribuição como no exemplo da codificação 918 2 É possível agrupar mais de um tipo de exceção no mesmo bloco except colocandoas em uma tupla Codificação 919 Agrupamento de mais de um tipo de exceção try except TypeError ValueError ZeroDivisionError Fonte do autor 2021 3 Podemos também apenas interceptar a exceção fazer algum tipo de tratamento como por exemplo salvar em um registro de log a ocorrência e deixála seguir o seu fluxo natural para ser tratada em outra parte da aplicação Para isso basta usar o comando raise sozinho dentro de um bloco except Codificação 920 Interceptando a exceção except loggerexceptionsalvando log da exceção raise Fonte do autor 2021 Com isso a mesma exceção que ocorreu originalmente será relançada com o comando raise após a execução do tratamento parcial 8 Observe que levantar um erro dentro de um bloco try fará com que esse erro seja capturado e tratado no próprio bloco portanto isso não é uma prática utilizada normalmente servindo aqui apenas para ilustrar o exemplo dado já que no código do exemplo não há margem para um erro genérico Alternativamente poderíamos ter editado a nossa classe para ao receber um nome específico levantar um erro genérico este exemplo seria mais perto de um exemplo de utilização real do tratamento de exceções Núcleo de Educação a Distância Faculdade Impacta PROGRAMAÇÃO ORIENTADA A OBJETOS Bibliografia BECK K Testdriven development by example Boston AddisonWesley Professional 2002 BECK K Quora why does kent beck refer to the rediscovery of testdriven development 2012 Disponível em httpsqraepGIvYU Acesso em 18 abr 2021 KREGEL H Pytest usage and invocations 2020 Disponível em httpsdocspytestorgenstableusagehtml Acesso em 10 fev 2021 PSF Expressions conditional expressions 2021a Disponível em httpsdocspythonorg3referenceexpressionshtmlconditionalexpressions Acesso em 07 fev 2021 PSF Builtin exceptions exception hierarchy 2021b Disponível em httpsdocspythonorg3libraryexceptionshtmlexceptionhierarchy Acesso em 18 abr 2021 Núcleo de Educação a Distância Faculdade Impacta

Sua Nova Sala de Aula

Sua Nova Sala de Aula

Empresa

Central de ajuda Contato Blog

Legal

Termos de uso Política de privacidade Política de cookies Código de honra

Baixe o app

4,8
(35.000 avaliações)
© 2025 Meu Guru®