[MÚSICA] Olá, vamos hoje aprender uma coisa muito importante, fundamental computação, são os testes automatizados. E vamos ver por que é que eles são tão importantes. Por que é que a gente deve testar os programas que a gente desenvolve, o código que a gente escreve? E basicamente porque seres humanos erram. Então, quando a gente escreve código é muito comum cometermos erros, porque seres humanos cometem erros. E à medida que os nossos programas vão crescendo, eles vão contendo cada vez mais erros se nós não tomamos atitudes para coibir esses erros. E os testes são a melhor forma de evitar esses erros. Então, a gente vê por aí que muitas vezes os programas contêm erros. Quando a gente baixa aplicativo, às vezes, compra programa, e tem erros, a gente fica muito bravo. Nós, como clientes de software, ficamos muito bravos quando a gente encontra erro. Então, quando a gente desenvolve software, a gente tem que fazer o máximo de esforço possível para ter software livre de erros. Os erros podem ser de sintaxe, mas esses são erros simples que o próprio compilador, ou interpretador, detecta. E quando a gente está desenvolvendo ele já mostra o erro. Os erros mais difíceis são aqueles erros de lógica que o programa compila, ele executa, mas só de vez quando, esse erro se manifesta e causa algum comportamento errado do programa. Então, esses erros de lógica é o que a gente quer pegar principalmente com os nossos testes. Então, software robusto deve conter o mínimo possivel de erros. É isso que a gente deve buscar, desenvolver software de alta qualidade com o mínimo possível de erros. Alguns casos os 'bugs' podem causar catástrofes. Já houveram casos na história de foguetes que explodiram no espaço porque tinha bug software. Aconteceu de uma sonda chegar Marte, pousar Marte e não funcionar direito Marte porque a coisa não deu certo. Tem outras áreas do conhecimento humano, por exemplo, o software que controla grandes usinas, também tiveram bugs que causaram grandes prejuízos financeiros e, muitas vezes, até perdas de vidas humanas. Esses são casos raros mas extremos, onde se deve investir muito na qualidade do software. Mas, na maior parte dos casos, os bugs vão causar o desconforto do usuário. Algo que o usuário gostaria de fazer de jeito e aquilo não funciona, causa desconforto e pode até causar prejuízo financeiro para o usuário. Particular, se você está desenvolvendo software para vender para usuários, para vender para uma outra empresa, esses bugs podem fazer com que o cliente abandone o seu produto e deixe de comprar da sua empresa, da sua startup. A gente deve sempre buscar desenvolver software de alta qualidade, sem erros. A gente quer evitar essas bombas escondidas no nosso software que, algum momento, explodem quando a gente menos espera. Então, como evitar que essas bombas existam? Com bons testes. Agora, como é que a gente pode testar? Jeito são os testes manuais. Você escreve o programa e depois você mesmo vai testando o programa diferentes casos. Ou tem algumas empresas, que trabalham de jeito mais antigo e que têm uma equipe de desenvolvedores e depois uma equipe de testadores. E testadores vão testar todo o código que os desenvolvedores fizeram. Fazer testes dessa forma, de forma manual, é uma coisa cansativa. Você não vai ter vontade de repetir toda a bateria de testes toda a vez que tem alguma mudança no software. Você vai acabar testando apenas algumas casos, porque testar na mão dá muito trabalho, e você vai testar apenas algumas vezes. Você vai testar, sei lá, uma vez por semana. Você não vai testar toda vez que alguma coisa muda no programa. E os erros vão ser introduzidos e você vai acabar não detectando. Eu diria que esse aqui não é o jeito mais moderno, mais sofisticado, mais inteligente de se fazer estes. Se você trabalha numa empresa que usa testes manuais, você tem que batalhar dentro da sua empresa para mudar isso e pensar automatizar a execução dos seus testes. Para isso, você precisa escrever testes automatizados, ou seja, você vai escrever código que vai testar o seu código. A idéia é de que você deveria ter uma bateria de testes que cobre o máximo possível do seu código. Cobre no sentido de todas as linhas de código que você escreveu no seu programa Python, deveriam ser testadas pela sua bateria de testes. O primeiro objetivo que a gente busca é cobrir todas as linhas de código. Depois, tem outros objetivos mais ambiciosos ainda, por exemplo, cobrir todos os possíveis caminhos dentro do seu programa. Mas, o ideal é a gente testar, principalmente, os casos potencialmente mais problemáticos. A gente tem que refletir pouco sobre quais são os casos que podem dar erros e esses são os primeiros que a gente deve testar. E depois que você tem essa bateria de testes, você tem que executar essa bateria de testes rotineiramente, várias vezes ao dia. Enquanto você está programando, você tem aquela bateria de programa maior, 100, 200 mil testes, e você roda aquilo a toda hora, a cada duas horas. Ou, alguns casos, é cada vez que você faz alguma mudança, você roda o teste para ver se não quebrou nenhum pedaço do seu código. Esse é o jeito que bons grupos de desenvolvimento de software trabalham. É o jeito que boas empresas, empresas sérias, trabalham relação a testes. Então, automatizar é colocar as engrenagens para trabalhar a seu favor. É isso que a gente deve buscar. Para fazer isso de uma forma mais sistemática, mais efetiva, a gente acaba usando, muitas vezes, arcabouço de testes automatizados; que é uma ferramenta que já vem nas diferentes linguagens de programação, que nos ajudam a escrever e executar esses teste de uma forma mais fácil. Aqui nesse nosso curso, a gente vai aprender a usar o 'pytest', que é arcabouço de testes automatizados para o Python. Então, para vocês instalarem no computador de vocês o pytest, basta você visitar o "docs.pytest.org" e, de lá, vocês vão poder baixar o software e implementar. Deixa eu abrir aqui rapidamente. Essa aqui é a página do pytest. Se você clicar aqui 'install' a gente consegue ver aqui os comandos que você pode usar para instalar. No meu computador eu instalei usando esse 'easy install' aqui. Depois, aqui, para você verificar se a versão correta foi instalada. E, depois, tem pequeno exemplo de código de teste que você pode executar para ver se funciona. Eu vou copiar isso, vamos abrir arquivo. Eu vou colar. Então, o que faz nesse nosso pequeno exemplo do pytest? Primeiro, eu estou definindo uma função que se chama 'func', que recebe parâmetro 'x' e devolve 'x' mais. Então pronto, esse aqui é o código que eu testar, uma função mais simples que você pode conseguir imaginar. E, depois, a gente tem método de teste. Então, esse 'test_answer' aqui, o fato de ele começar com a palavra teste está indicando para o pytest que é método de teste. E o que é que a gente está testando? Esse assert... Verifique se 'func' de três é igual a cinco, ou seja, ao chamar a função 'func' passando três como parâmetro se isso dá cinco. Vamos salvar isso e agora eu vou executar. A gente vê que para executar basta a gente dizer pytest, ou pytest e o nome do arquivo. Deixa eu abrir. Eu vou escrever 'py.test' e o nome do arquivo é o 'test_sample.py'. Eu vou executar isso e ele me deu uma mensagem de erro. Falou, 'test_answer', teve 'failures'. Ele falou que teve teste que falhou aqui. Esse foi o tempo que demorou para executar os testes. E o que ele está falando? Ele está falando que onde falhou foi esse aqui: 'assert func(3) = 5' porque o 'func' de três deu quatro, não deu cinco. Então, o quatro é igual a cinco falhou. Então, não só ele diz o que está errado como ele diz exatamente que linha deu errado. Nesse caso específico, o que estava errado não era o código da 'func'. O 'func', na verdade, estava certo; o que estava errado era o nosso próprio código de teste. Porque 'func' de três deveria ser quatro. Porque o que essa 'func' faz? Ele soma. Então, eu vou agora salvar e executar novamente o nosso teste. Vamos ver o que acontece? Pronto. Agora ele deu certo. Ele colecionou item, ou seja, ele executou teste desse arquivo e teste passou. Ele está mostrando vermelho, desculpa, verde, para mostrar que passou. Quando algum dos testes falha, ele pinta de vermelho. Quando todos os testes deram certo, nesse caso só tinha e deu certo, ele pinta de verde. Então, esse é exemplo o mais simples possível de teste que a gente pode imaginar. Mas vamos voltar aqui. Então, esse 'pytest', quando a gente executa o pytest na linha de comando. Deixa eu digitar aqui 'pytest'. Se eu executo simplesmente pytest, sem nenhum parâmetro, ele vai considerar, vai olhar para todos os arquivos no diretório, vai buscar todos os arquivos que tem o nome 'teste' sublinhado, alguma coisa ponto 'py'. E ele vai considerar que isso são arquivos de teste. Além disso, ele vai executar dentro dentro desse arquivo as funções e métodos do tipo test, 'underscore, e que depois vem alguma coisa qualquer. E considera... Depois se a gente tiver classes de teste ali dentro. A gente vai ver isso mais para a frente. Ele vai considerar classes que começam com test, asterisco. Então, mais informações sobre isso, vocês podem encontrar aqui nesse site. Ele tem todas as informações sobre documentação do 'pytest', que eu sugiro que depois que vocês fizerem esses dois vídeos que eu explico como usar o 'pytest', você também dê uma boa olhada ali. Então vamos aqui fazer exemplo da função fatorial. Deixa eu abrir aqui uma nova função fatorial. Eu vou abrir aqui novo arquivo e eu vou chamar... Vamos fazer uma função fatorial, por exemplo. Então vamos implementar: fatorial de 'n' e vai calcular o fatorial de 'n'. Então, inicialmente, eu vou usar 'while' que vai repetindo e vai multiplicando os números de até 'n', depois devolve esse valor. Eu vou guardar essa multiplicação uma variável 'fat', que eu vou inicializar com que é o elemento neutro na multiplicação. E eu vou ter índice 'i' que vai indo desde até 'n'. Então, o 'i', eu também vou começar com. E daí, a gente pode fazer 'while'. E o meu while vai ser enquanto o 'i' for menor que 'n'. O que eu faço? Eu faço 'fat' recebe 'fat' vezes 'i'; e 'i' recebe mais. E daí, quando eu termino de fazer isso, eu simplesmente dou 'return fat'. Então, vamos supor que essa é a nossa função fatorial. Daí como a gente pode testar? Daí eu vou definir várias funções de teste que começam com teste sublinhado e, depois, alguma explicação do que eu estou testando. Então, por exemplo, eu vou testar a fatorial de zero. Como eu testo isso? Eu faço 'assert' que o fatorial de zero. Quanto tem que dar fatorial de zero? Por definição tem que dar igual a. Então, essa aqui já é possível teste. Que outro possível teste? Fatorial de também tem que dar a mesma coisa. Daí eu posso testar, por exemplo, fatorial de valor negativo. Fatorial, por exemplo, de menos dez. Aí, eu preciso definir o que eu gostaria que o programa devolvesse. O que eu gostaria é que não desse algo completamente errado, tipo o programa entrar laço infinito, loop infinito e travar. Mas vamos supor que eu queira que devolva zero, negativo, só para indicar que tem alguma coisa errada. E depois vamos ter uns outros casos de uns que ele realmente faz algum cálculo. Então, por exemplo, fatorial de quatro tem que dar 24, quatro vezes três vezes dois. E o fatorial de cinco, se não me engano, é 120. 120. Então já temos uma pequena bateria de testes que testa vários casos diferentes. Vamos executar aqui para ver o que acontece. Eu vou salvar isso aqui como fatorial. Eu vou chamar aqui de, como eu já tenho, teste fatorial. Normalmente, a gente divide as funções arquivo e os testes outro. Como os dois já estão aqui misturados no mesmo, eu vou chamar isso aqui de teste fatorial. Salvar. E eu vou, aqui, executar o 'pytest' no meu teste fatorial. Vamos ver o que acontece. Deu alguns erros aqui. Na verdade, três aqui, está mostrando, que três dos meus testes falharam e dois deram certo. Particular, esses vários aqui falharam. Então, vamos ver o 'assert' fatorial de... Esse aqui, o teste fatorial quatro, teria que ter dado 24, mas ele deu seis, está falando que o fatorial de quatro deu seis. Então, espera aí, o seis é fatorial de três, então, ele multiplicou dois vezes três e não multiplicou o quatro. Então, eu estou multiplicando número a menos. Se vocês olharem o teste fatorial cinco, é a mesma coisa. Tinha que ter dado 120, deu só 24. Ele não multiplicou pelo cinco. Então, está faltando multiplicar pelo 'n', pelo próprio número 'n' aqui. Então, vamos ver... Eu acho que olhando aqui. Como eu fiz o 'while', 'i' menos que 'n', o 'i', estritamente menor que 'n', ele não está executando quando o 'i' fica valendo 'n'. Então, ele não está multiplicando pelo 'n' si. Então, eu vou ter que fazer 'while', 'i' menor ou igual a 'n'. Note que a bateria de testes me ajudou a encontrar casos que não estava funcionando e, portanto, eu pude ir lá e consertar o caso. Então, acho que eu consertei. Vamos ver, vamos executar novamente aqui. Salvei ali. Executar novamente aqui. Melhorou. Só deu errado. Quatro deram certo e deu errado. Ele está pintando de vermelho, porque ainda deu errado. E qual deu errado? Exatamente o fatorial de menos dez que tinha que ter dado zero. Eu realmente não tinha implementado esse aspecto do fatorial de número negativo ter que devolver alguma coisa que faça sentido. Então, a gente pode começar fazendo algo do tipo: 'if' 'n' menor que zero, return zero. Então, qualquer número negativo, ele vai devolver zero para indicar que não faz sentido essa conta do fatorial de número negativo. Então, vamos ver se dá certo agora. Executar novamente. Pronto, agora deu que os meus cinco testes passaram. Então, essa aqui é uma forma da gente começar a escrever uma pequena bateria de testes para testar que a nossa função está funcionando. E é o que a gente vai fazer bastante ao longo desse curso. Nos trabalhos que vocês fizerem, é sempre muito saudável você escrever uma bateria de testes. Resumindo mais uma vez, então, o que você deve fazer quando você escreve o seu programa é pensar cuidadosamente nos casos que o seu programa pode falhar. E daí você vai escrever testes para esse caso que o programa pode falhar. Então, você tem que pensar nos diferentes tipos de entrada que exercitam caminhos diferentes dentro do seu programa. E você vai escrever testes para esses diferentes tipos de entrada. Você tem que pensar nos casos diferentes do seu código, escrever testes para esses casos diferentes. E, todos os casos, testes automatizados. Então, nada de ficar testando na mão. Se você tem alguma dúvida se o programa funciona determinado caso, vai lá e escreve teste automatizado para testar aquele caso. Se você está usando o seu programa e descobre erro, 'bug', no programa. Usuário seu descobre 'bug' no seu programa, você não vai lá e conserta o bug, Você primeiro escreve teste automatizado que vai expor aquele bug e daí assim você vai consertar o bug. Porque, dessa forma, na sua bateria de testes, vai ter aquele bug, uma proteção, contra que aquele bug apareça novamente no futuro. Então é isso... Testar, testar, testar... [MÚSICA] [MÚSICA] [MÚSICA] [MÚSICA]