Baixe o app para aproveitar ainda mais
Prévia do material em texto
TESTES DE SOFTWARE E GERÊNCIA DE CONFIGURAÇÃO Jeanine dos Santos Barreto Testes unitários Objetivos de aprendizagem Ao final deste texto, você deve apresentar os seguintes aprendizados: Definir o que são os testes unitários e suas características. Identificar um teste unitário. Aplicar as técnicas de testes unitários. Introdução Os testes unitários realizam testes individualizados nas menores porções possíveis de um sistema, ou seja, no código trabalhado pelo programador. O teste unitário não serve para testar o sistema globalmente, mas indica se os métodos, as classes ou as funções estão definidas no programa de maneira que recebam as entradas necessárias e produzam as saídas correspondentes aos requisitos da aplicação. Neste capítulo, você vai estudar o conceito de testes unitários. Você vai conhecer as principais ferramentas desses testes e ver como aplicá-los com o framework JUnit. Os testes unitários e as suas características Por meio do teste unitário, também chamado de teste de unidade, o testador verifi ca a menor unidade de um projeto de software. A unidade pode ser uma parte do código, um componente, um módulo, uma função, um método, etc. (PEZZÈ; YOUNG, 2008). Esse teste normalmente é realizado pelos próprios desenvolvedores nas porções menores do software que estão sendo desenvolvidas no momento. Ele é aplicado de maneira individualizada e verifica se cada porção funciona de maneira isolada das demais partes do sistema. Os testes unitários não têm a intenção de testar o sistema de maneira global, e sim o inverso, isto é, as menores partes possíveis. Via de regra, tanto o planejamento quanto a execução do teste unitário ficam a cargo do próprio programador ou desenvolvedor do sistema. Durante a implementação do programa, o programador codifica a unidade e executa testes a cada progresso. Ao definir um pequeno pedaço que deve ser testado, pode-se garantir que todas as atenções do testador estejam voltadas apenas para aquele escopo. Ou seja, os caminhos do controle são testados para a identificação de problemas dentro dos limites predefinidos. Nesse sentido, a complexidade dos testes e os problemas encontrados revelam situações restritas ao escopo que foi definido para o teste de unidade. Na Figura 1, a seguir, você pode ver os aspectos testados pelos testes unitários. Figura 1. Aspectos testados pelos testes unitários. Fonte: Pressman e Maxim (2016, p. 474). Durante os testes unitários, é necessário testar a interface oferecida pela parte testada para verificar se as informações estão fluindo de maneira cor- Testes unitários2 reta para dentro e para fora. É possível, dessa maneira, saber se as entradas necessárias para a parte testada estão chegando corretamente, e ainda se o que foi produzido por ela está saindo para outras partes do sistema. Esse aspecto é particularmente importante. Afinal, se as entradas não estiverem chegando na unidade corretamente e se as saídas não estiverem produzindo o resultado que deveriam gerar, isso pode impedir a continuação dos testes; nesse caso, talvez seja preciso rever a estrutura antes de prosseguir. Além da interface, é preciso verificar também se os dados armazenados, sejam eles temporários ou permanentes, estão se mantendo íntegros e con- dizentes com as operações executadas sobre eles. Isso equivale a dizer que é preciso testar variáveis e também dados armazenados em banco de dados para saber se eles estão se modificando conforme estabelecido na aplicação, ou seja, se a sua estrutura está se mantendo íntegra. Outro elemento importante a ser considerado é a verificação de cada controle da parte testada em separado. Isto é, cada estrutura de controle, cada laço de repetição e cada condição presente devem ser averiguados a fim de se verificar se são todos executados e necessários, bem como se retornam a saída desejada (PRESSMAN, 2011). A escolha dos caminhos a serem seguidos pelos testes é essencial para o teste unitário. Afinal, esse teste deve identificar problemas decorrentes de cálculos errados, maneiras incorretas de programar, fluxos de controle inadequados, fluxos de exceção desprezados, regras de negócio mal interpretadas e todos os demais aspectos levados em consideração ao se codificar o programa. Nesse momento, é importante efetuar testes em áreas-limite impostas pela aplicação. A ideia é impedir o processamento caso algum campo tenha excedido seu limite, caso um valor tenha sido digitado de maneira incorreta, etc. Para cada problema desse tipo, deve haver um retorno do sistema com uma mensagem de erro, informando o que deve ser feito pelo usuário para que a situação seja resolvida. Entre os tipos de erro que precisam ser testados para se verificar se estão sendo manipulados corretamente, estão os listados a seguir (PRESSMAN; MAXIM, 2016): a descrição do erro é confusa; o erro descrito na mensagem não corresponde ao erro identificado; a condição do erro gera interrupção no sistema todo antes que o erro possa ser tratado; o processamento do erro vem de um fluxo de exceção incorreto; a descrição da mensagem de erro está incompleta e não informa ao usuário a respeito do erro nem do que deve ser feito para corrigi-lo. 3Testes unitários Apesar de os testes unitários apresentarem como desvantagem o fato de demandarem tempo extra do programador durante a fase de implementação, as vantagens da sua utilização superam essa suposta desvantagem. A seguir, você pode ver algumas das vantagens desses testes (PRESSMAN; MAXIM, 2016). Quando os testes unitários são automatizados, fica mais fácil aumentar a cobertura do teste para além da unidade, testando caminhos de controle passíveis de exceder a sua fronteira. Os testes unitários, quando automatizados, previnem que o código regrida, ou seja, que uma nova versão da unidade afete negativamente algo que já estava funcionando. Isso porque o programador recebe alertas sempre que os códigos já prontos apresentam defeitos devido a alterações no código que já funcionava. Os testes unitários, quando automatizados, incentivam o processo de refatoração, que nada mais é do que a otimização de um código que apresenta problemas, sem que isso afete uma parte do programa que já estava funcionando. Os testes unitários servem como fonte de documentação para o sistema. Quando são bem escritos, eles descrevem de maneira detalhada todas as funcionalidades do sistema e o comportamento dele para cada ação do usuário. Quando alguma manutenção for necessária, os programa- dores poderão ler a documentação dos testes unitários e compreender o funcionamento do sistema. O teste unitário serve de apoio durante a elaboração do código do sistema. O projeto para esse tipo de teste pode acontecer antes da codificação, ou depois que a unidade que será testada esteja completamente codificada. Por meio da avaliação do projeto do software, de seus requisitos e regras de negócio, é possível elaborar casos de teste capazes de identificar, senão todos, a maioria dos problemas presentes na unidade de teste. Identificação de um teste unitário Como você viu, o propósito dos testes unitários é testar as menores partes do sistema, que são as unidades, de maneira isolada, para assegurar que estejam funcionando conforme o esperado. Além disso, você deve ter em mente que é importante planejar os testes unitários, mesmo que eles sejam feitos geralmente durante o desenvolvimento, pelo próprio programador. Testes unitários4 Nesse sentido, é importante que o testador — nesse caso, o programador — conheça detalhadamente os requisitos da funcionalidade ou da unidade que será testada. Ele deve compreender quais são as entradas das quais a unidade depende e quais são as saídas que ela deve produzir, bem como a maneira como os fluxos de controle agem no decorrer da execução (PRESSMAN; MAXIM, 2016). “Unidade” é o termo genérico utilizado para fazer referência à estrutura, à menor parte do sistemaque será testada no teste unitário. A unidade pode ser tratada também como unit. É importante que o analista responsável pelos testes unitários se com- prometa a elaborar conjuntos ou cenários de testes unitários que auxiliem na verificação do desempenho da execução da unidade. Sem isso, os testes unitários não serão efetivos como deveriam. Assim, quanto mais automatizado um teste unitário for, mais eficiente ele será, pois se evita que o testador fique responsável por todos os detalhes dos testes. Cada vez com mais frequência, as linguagens de programação apresentam ferramentas específicas de teste, incluindo interface gráfica e amigável. Isso permite que o analista de testes programe os testes unitários, verifique a sua execução e tire conclusões disso tudo, analisando se o teste foi positivo ou negativo. A seguir, veja algumas das principais linguagens de programação, acompanhadas de suas respectivas ferramentas de automatização de testes unitários. Linguagem C#: sua ferramenta se chama NUnit. Ela serve para elaborar os testes unitários no Visual Studio e para realizar a sua execução. Os resultados dos testes são apresentados em uma interface gráfica que permite uma visualização simples e fácil do que foi executado, para que o testador possa entender se o teste fracassou ou foi bem-sucedido (NUNIT, 2017). Linguagem PHP: o nome da sua ferramenta é PHPUnit e ela possibilita a criação de testes unitários com PHP (PHPUNIT, 2019). 5Testes unitários Linguagem JavaScript: para essa linguagem, existem várias ferra- mentas, como as listadas a seguir. ■ Mocha: é uma das ferramentas mais conhecidas para JavaScript e possui muitas características que permitem criar e executar testes unitários com eficiência (MOCHA, 2019). ■ Jasmine: é uma ferramenta que trabalha com teste unitário orien- tado a comportamento, sendo muito utilizada pelos programadores (JASMINE, 2019). ■ Jest: essa ferramenta foi idealizada pelo Facebook e o seu foco principal é a simplicidade. O Jest é muito rápido e executa pri- meiramente testes anteriores que falharam; ele também organiza novamente o cenário de testes baseado em quanto a estrutura mudou (JEST, 2019). ■ QUnit: essa ferramenta muito poderosa e fácil de usar é utilizada pelo jQuery e é capaz de testar qualquer código feito em JavaScript, sendo que a promessa maior é que o QUnit pode testar até mesmo o código estrutural da própria JavaScript (QUNIT, 2019). Linguagem Ruby: conta com as ferramentas listadas a seguir. ■ RSpec: é uma ferramenta com excelente documentação para os testes. Ela é orientada a comportamento e é muito utilizada em aplicações de produção. Os testes são escritos primeiro e o código é desenvolvido de forma que preencha as necessidades dos testes (RSPEC, 2019). ■ Minitest: é uma ferramenta muito completa de testes. Ela também é orientada a comportamento e foi adicionada à biblioteca Ruby, o que aumentou a sua popularidade e a sua utilização entre os progra- madores (MINITEST, 2019). Linguagem Python: possui as ferramentas listadas a seguir. ■ Pytest: é muito utilizada pois possui muita integração e boa sintaxe. Ela facilita a criação de testes unitários e é ideal para suportar testes funcionais mais complexos para aplicativos e bibliotecas (PYTEST, 2019). ■ Locust: é uma ferramenta do Python para teste de carga, orientada para testar o comportamento do usuário ao utilizar o código. Essa ferramenta suporta testes de carga em execução, distribuídos em diversas máquinas, e pode ser usada para simular milhares de usuários simultâneos (LOCUST, 2019). Testes unitários6 Aplicação das técnicas de testes unitários Agora você vai ver um exemplo prático de como fazer um teste unitário utilizando a linguagem Java e a ferramenta JUnit na IDE Eclipse. Para esse exemplo, considere a criação de duas classes em Java: a Aritmetica.java e a AritmeticaTest.java. A classe Aritmetica.java possui métodos que servem para efetuar operações de soma, subtração, multiplicação e divisão em dois valores, a e b, passados como parâmetros. Ela tem o seguinte código: Já a classe AritmeticaTest.java inclui, entre as linhas 4 e 9, a iniciali- zação das variáveis que vão conter os valores das operações e também os valores esperados para as suas soma, subtração, multiplicação e divisão, respectivamente. Logo após, são feitos os testes: nas linhas 10 e 11 para a soma, nas linhas 12 e 13 para a subtração, nas linhas 14 e 15 para a multiplicação e nas linhas 16 e 17 para a divisão. Os testes funcionam da seguinte forma: nas primeiras linhas dos testes (10, 12, 14 e 16), são feitas chamadas para os respectivos métodos da classe Aritmetica, passando os valores como parâmetros. Depois, nas segundas linhas dos testes (11, 13, 15 e 17), é chamado o método assertE- quals, importado do JUnit na linha 1, para comparar o valor esperado para o teste com o valor encontrado durante a execução. 7Testes unitários A classe AritmeticaTest.java tem o seguinte código: Depois que as duas classes forem elaboradas, os testes podem ser execu- tados clicando no menu Run do Eclipse, em Run As e depois em JUnit Test (Figura 2). Figura 2. Tela do Eclipse com a opção JUnit Test. Testes unitários8 Caso os valores encontrados durante a execução dos testes sejam idênticos aos esperados, uma faixa verde vai aparecer à esquerda, indicando que o teste obteve sucesso (Figura 3). Figura 3. Resultado de teste bem-sucedido. Caso os valores encontrados durante a execução dos testes sejam diferentes dos esperados, uma faixa vermelha vai aparecer à esquerda, indicando que o teste fracassou. Ao passar o mouse sobre a mensagem de erro, você vai ver os resultados obtidos e os esperados (Figura 4). Figura 4. Resultado de teste com falha. 9Testes unitários JASMINE. Sample code. [S. l.: s. n.], 2019. Disponível em: https://jasmine.github.io/. Acesso em: 27 jun. 2019. JEST. Guia de introdução. [S. l.: s. n.], 2019. Disponível em: https://jestjs.io/pt-BR/. Acesso em: 27 jun. 2019. LOCUST. An open source load testing tool. [S. l.: s. n., 2019]. Disponível em: https://locust. io/. Acesso em: 27 jun. 2019. MINITEST. A simple and clean mock object framework. [S. l.: s. n.], 2019. Disponível em: https://apidock.com/ruby/MiniTest. Acesso em: 27 jun. 2019. MOCHA. Simple, flexible, fun. [S. l.: s. n.], 2019. Disponível em: https://mochajs.org/. Acesso em: 27 jun. 2019. NUNIT. What is NUnit? [S. l.: s. n.], 2017. Disponível em: https://nunit.org/. Acesso em: 27 jun. 2019. PEZZÈ, M.; YOUNG, M. Teste e análise de software: processos, princípios e técnicas. Porto Alegre: Bookman, 2008. PHPUNIT. Home. [S. l.: s. n.], 2019. Disponível em: https://phpunit.de/. Acesso em: 27 jun. 2019. PRESSMAN, R. S. Engenharia de software. São Paulo: MacGraw-Hill, 2011. PRESSMAN, R. S.; MAXIM, B. R. Engenharia de software: uma abordagem profissional. Porto Alegre: AMGH, 2016. PYTEST. Pytest: helps you write better programs. [S. l.: s. n.], 2019. Disponível em: https:// docs.pytest.org/en/latest/. Acesso em: 27 jun. 2019. QUNIT. QUnit: a javascript unit testing framework. [S. l.: s. n.], 2019. Disponível em: https:// qunitjs.com/. Acesso em: 27 jun. 2019. Testes unitários10
Compartilhar