Introdução

Apesar de muitas empresas ainda não utilizarem técnicas de teste de software para o desenvolvimento dos seus produtos, alegando o atraso, o tempo ou o custo para esta tarefa, as pesquisas indicam que os testes ajudam na garantia de qualidade do software.

Vamos a outra realidade, imagine você adquirindo um carro, que foi projetado, montado, mas sem ser testado, pois os testes sairiam muito caro, e de repente você está andando e nota que na curva o carro não é eficiente. Você ficaria contente com esta situação? O mesmo acontece com o cliente de um software ao adquirir um produto que não funciona adequadamente. O Standish Group, no relatório de chaos, apresenta constantemente o resultado da pesquisa e demonstra que o percentual de software tido como completo e aceitável é muito baixo. Além disso, quanto mais tardiamente descobrirmos os erros, mais caros estes se tornam. Aplicando-se assim a regra dos 10 ao custo da correção, ou seja, encontrar um erro durante o requisito custa 1, por exemplo, durante a fase de análise e modelagem, custa 10, durante a codificação custa 100, durante a fase de teste, pós desenvolvimento, custa 1.000 e durante a produção, ou seja, quando já está na mão do cliente, o processo custa 10.000. Desta forma, é importante que a fase de requisitos possua validações, evitando-se assim problemas de entendimento de requisito.

Os problemas de requisitos são reduzidos quando utiliza-se de metodologias ágeis, isto porque o cliente acompanha o processo e como os ciclos são curtos, a velocidade da correção também o é. Mas como muitas empresas negligenciam o teste durante a fase de desenvolvimento, os erros só são encontrados tardiamente, elevando os custos dos produtos e criando impactos negativos aos processos e negócios.

Temos de lembrar que qualidade não é uma etapa apenas, uma fase do desenvolvimento, é parte de todo o ciclo de vida de desenvolvimento do software.

Mas o que é qualidade no processo de desenvolvimento de software? Segundo Bartié, “qualidade de software é um processo sistemático que focaliza todas as etapas e artefatos produzidos com o objetivo de garantir a conformidade de processos e produtos, prevenindo e eliminando defeitos”.

A qualidade aplicada tardiamente não gera um produto com qualidade, Bartié afirma que a maioria das organizações aplicam em seus processos de desenvolvimento testes tardios, o que não garante a qualidade do produto, e como vimos na regra de Myers, o custo do produto aumenta consideravelmente. Ainda segundo Miller e Presmann, "a motivação que está por trás do teste de programas é a confirmação da qualidade de software com métodos que podem ser economicamente e efetivamente aplicados a todos os sistemas, de grande e pequena escala". Desta forma, utilizar uma metodologia que permita testes no processo de desenvolvimento, auxilia na garantia de qualidade.

O TDD

O TDD (Test Driven Development / Desenvolvimento orientado a teste) é parte da metodologia XP e também utilizado em diversas outras metodologias, além de poder ser utilizada livremente.

O que você tem a perder utilizando o TDD?

Segundo Freeman (2012), você não tem nada a perder, a não ser os seus bugs. "Finalmente, consegui separar o projeto lógico do físico. Sempre me disseram para fazer isso, mas nunca ninguém tinha explicado como", o TDD é a forma de se fazer isso. A criação de teste unitários ou de componentes é parte crucial para o TDD.

O TDD transforma o desenvolvimento, pois deve-se primeiro escrever os testes, antes de implementar o sistema. Os testes são utilizados para facilitar no entendimento do projeto, pois clareiam a ideia em relação ao que se deseja em relação ao código. Segundo Presmann (2011), "os componentes individuais são testados para garantir que operem corretamente. Cada componente é testado independentemente, sem os outros componentes de sistema. Os componentes podem ser entidades simples, tais como funções ou classes de objetos, ou podem ser grupos coerentes dessas entidades".

Mas não é só o teste unitário que vai trazer o sucesso a aplicação, é necessário testar o sistema como um todo, que segundo Sommerville, "os componentes são integrados para compor o sistema. Esse processo está relacionado com a busca de erros que resultam das interações não previstas entre os componentes".

Um sistema é um conjunto de unidades integradas, por este motivo é importante os testes unitários para ver se no micromundo tudo funciona, mas também temos de testar a integração, ou seja, ao integrar dois ou mais componentes, devemos realizar testes para verificar se a integração funciona. Voltemos ao exemplo do carro, não adianta eu testar a roda, a porta, o volante, mas não testar o carro completo. Erros podem ocorrer, justamente no processo de montagem/integração de componentes.

E qual o benefício em utilizar o TDD?

Em primeira instância, torna o processo mais confiável, mas reduz custos, pois desenvolvemos e já sabemos o erro, pois como os testes são criados antes do processo de desenvolvimento, conseguimos testar constantemente. Outro ponto é que se os testes foram criados, isso quer dizer que foram entendidas as regras de negócio durante a fase de desenvolvimento dos testes unitários.

Além disso, evita retrabalho da equipe, que ao final reduz custo e tem maior chance de sucesso.

O Ciclo do TDD é simples: criamos um teste -> Fazemos a codificação para passar no teste -> Refatoramos nosso código, conforme a Figura 1.

Ciclo do TDD
Figura 1. Ciclo do TDD

Notemos aqui que o teste visa auxiliar a codificação, reduzindo consideravelmente os problemas na fase de desenvolvimento. No TDD é indicado que o projeto de teste unitário ocorra antes da fase de codificação/implementação.

O Teste antes da codificação, ou test-first, segundo Sommerville, “a escrita de testes primeiro define implicitamente tanto uma interface como uma especificação do comportamento para a funcionalidade que está sendo desenvolvida”.

Note que ao criar o teste antes de implementar a unidade, são reduzidos problemas como mal entendimento de requisitos ou interfaces, pois como criar um teste se eu não sei o que devo testar?

Neste caso o desenvolvedor, para implementar os testes iniciais, deve compreender com detalhes a especificação do sistema e as regras de negócio, só assim, será possível escrever testes para o sistema. Imagine o caso de querer testar um pneu criado para o carro, se não entendi que o pneu é redondo, por exemplo, criarei um teste para um pneu quadrado, não podendo ser realizado o teste. Desta forma, é de extrema importância, para o desenvolvedor, o entendimento dos requisitos do cliente. Além disso, não adianta criar testes que não validem o código como um todo para reduzir o tempo, é necessário criar testes para o conjunto completo de unidades, só assim o TDD vai funcionar como deve, devendo fornecer uma cobertura completa aos testes.

Além disso, os testes devem seguir o modelo F.I.R.S.T.

  • F (Fast) - Rápidos: devem ser rápidos, pois testam apenas uma unidade;
  • I (Isolated) - Testes unitários são isolados, testando individualmente as unidades e não sua integração;
  • R (Repeateble) - Repetição nos testes, com resultados de comportamento constante;
  • S (Self-verifying) - A auto verificação deve verificar se passou ou se deu como falha o teste;
  • T (Timely) - O teste deve ser oportuno, sendo um teste por unidade.

Atualmente, existem diversas ferramentas que analisam as coberturas de teste, podendo ser baixadas gratuitamente da Internet.

Outra vantagem de possuir testes é a chamada regressão. Imagine que criamos os testes, fizemos o sistema e tudo foi entregue ao cliente, mas posteriormente o cliente pediu pequenas modificações no sistema, mas não nas regras de negócio. Os testes já prontos servirão para validar se as modificações não criaram problemas nas regras de negócio que já estavam em funcionamento. Este procedimento exige que testes unitários estejam prontos, aguardando ser reutilizados. Um teste de unidade deve garantir que a execução daquele trecho mínimo de código esteja correta.

Como implementar o processo de TDD ao desenvolvimento?

  • Para começar a desenvolver seus primeiros testes, pode ser mais fácil a utilização de bibliotecas XUnit's. Existem diversas ferramentas que possibilitam esta prática, vamos a algumas:
  • JUnit: O JUnit é um framework de teste para Java, que permite a criação de testes unitários. Além disso, está disponível como plug-in para os mais diversos IDE'S como Eclipse, NetBeans etc.
  • TesteNG: Outra ferramenta de teste unitária, disponível para Java;
  • PHPUnit: Framework XUnit para teste unitário em PHP, também é possível integrar aos IDE's assim como o JUnit;
  • SimpleTest: Outra ferramenta para realização de teste para PHP. Além de possibilitar os testes unitários, é possível realizar MOCKS e outros testes;
  • NUnit: Framework de teste no molde XUnit para a plataforma .NET;
  • Jasmine: Framework para teste unitário de JavaScript;
  • CUnit: Ferramenta para os testes unitários disponível para Linguagem C;
  • PyUnit: Framework Xunit para testes na linguagem Python.
Depois, temos de iniciar a fase de desenvolvimento, criando primeiramente os testes. Nos sites das ferramentas existe documentação para saber como utilizá-las, mas é possível ver nestes tutoriais como utilizar algumas delas:

Como vimos, existem ferramentas para as mais diversas linguagens e plataformas, com integração a IDEs. E lembre-se: primeiro crie os testes, para posteriormente efetuar a sua implementação.

Conclusão

Neste artigo vimos o TDD e sua importância para a qualidade de software. Foram apresentadas ainda algumas ferramentas que permitem a utilização dos testes. Este artigo tem como principal objetivo apresentar fundamentos do porquê utilizar testes na fase de codificação e sua importância para a redução de falhas. Vimos que a utilização de teste durante a fase de desenvolvimento melhora a qualidade e reduz custos de manutenção.

Agora, você tem o que a perder?

Seus bug's!!!

Até a próxima e até o próximo artigo.

Referências bibliográficas

  • BARTIÉ, Alexandre. Garantia de qualidade de software. Rio de Janeiro: Campus, 2002.
  • FREEMAN, Steve. Pryce, Nat. Desenvolvimento de Software Orientado a objetos, Guiado por Testes. Rio de Janeiro: Alta Books, 2012.
  • PRESSMAN, Roger S. Engenharia de Software: Uma abordagem Profissional. Porto Alegre: Bookman, 2011.
  • SILVEIRA, Paulo et al. Introdução à arquitetura e design de software: uma visão sobre a plataforma Java. Rio de Janeiro: Campus, 2012.
  • SOMMERVILLE, Ian. Engenharia de software. São Paulo: Person, 2010.