Testes… eis uma questão delicada. No fundo, todos pensam que
sabem a importância dos testes, mas na prática poucos sabem como testar,
quando testar e a real importância dos testes. Neste artigo vou falar
sobre hábitos e conceitos de testes, bem como de alguns níveis básicos de
testes que um bom desenvolvedor deveria fazer.
Muitos
profissionais ainda pensam que realizar testes é tarefa dos testadores e, quem
sabe, dependendo da empresa, tem um cara de SQA envolvido na questão.
Testes muitas vezes não são realizados por desenvolvedores e
arquitetos, mas em muitos casos deveriam.
Nem sempre é fácil
testar. Muitas vezes a complexidade de se criar e realizar testes é uma
barreira para a utilização desta disciplina tão importante da
engenharia. Existem algumas barreiras para o uso de testes ou o uso
adequado desta prática. Quero falar deste
assunto também.
Não estou aqui para falar do teste funcional,
conhecido também como teste de tela. Existem várias técnicas e
práticas para realizar esse tipo de testes, mas neste artigo não vou
focar nisso; o objetivo aqui é falar dos testes do desenvolvedor e dos testes que o
desenvolvedor pode e deve fazer.
Debugar não é testar?
Não mesmo. Debugar não é testar. O pior é que muitos desenvolvedores só usam o
debug depois de colocar o código em produção e dar um erro que eles não
sabem como corrigir. Já vi muito disso, assim como também é comum ver
desenvolvedores que acreditam que debugar é suficiente.
Quando
você debuga você não faz isso com o intuito de verificar se a sua
unidade de código está ok, ou se o que você fez é o que o usuário
realmente deseja. Você até pode repetir o debug, mas é complicado seguir
ou se lembrar dos passos corretos.
Precisamos de mais,
precisamos de testes. Quando falo em testes começo falando de testes do
desenvolvedor. Isso mesmo. O testador ou SQA não deve ser a primeira barreira para achar defeitos e bugs, mas sim a última.
O Modelo em V
Esse
modelo de desenvolvimento de software foca muito em testes. Na prática,
do lado esquerdo do V estão as práticas de desenvolvimento e do lado
direito, as práticas de testes. Com isso você vai testar em diversos
momentos, evitando aquele velho modelo de testes em cascata apenas
depois da construção.
Dessa forma também conseguimos obter
erros, defeitos e bugs mais rapidamente e, com isso, podemos corrigir
mais rápido, deixando a aplicação cada vez mais sólida e criando
uma aplicação mais confiável para o cliente.
Modelo em V
Esse
modelo é muito bom e traz um bom retorno ao cliente. Mas no modelo em V
vão existir testes que não são do desenvolvedor, como o teste de
aceitação e os testes de arquitetura por exemplo. Podemos encarar a
prova de conceito de arquitetura (proposta pelo RUP) como um nível de
teste de arquitetura. Pois bem, vamos focar nos testes do desenvolvedor
então.
Testes unitários
Também
muito conhecidos como testes de unidade. São feitos pelo desenvolvedor.
Sim, o desenvolvedor deve criar estes testes. Os testes de unidade
devem testar apenas o desenvolvimento do programador naquela
construção. Por exemplo, imagine uma aplicação construída em camadas,
pode ser o clássico MVC ou qualquer N-Tier. Logo, neste momento não
importa testar a tela ou a camada de acesso ao banco. O que mais
importa é testar a lógica de negocio que o desenvolvedor fez.
Não
estou dizendo que não devemos testar o acesso ao banco e às telas, mas
isso será feito em outro nível de testes. Falarei destes níveis mais à
frente neste mesmo post :).
A necessidade dos Mocks…
Muitas
vezes, mesmo com uma aplicação em camadas, para poder testar a unidade
você irá precisar de mocks. Mocks são objetos que simulam o
comportamento de um objeto real. Mocks são utilizados pelos seguintes
motivos:
- 1 Possibilitar o teste de unidade
- 2 Performance e velocidade dos testes unitários
- 3 Isolamento dos testes
- 4 Possibilita paralelizar o desenvolvimento
#1
Porque muitas vezes sua classe de negócios acessa vários componentes
de banco de dados ou recursos externos como outros sistemas,
webservices, arquivos, etc… Além da dificuldade de acessar estes
recursos, isto pode deixar o seu teste unitário lento. O teste unitário
deve ser o mais rápido possível.
#2
Imagine que seu componente de banco carrega 30 mil registros – você não
precisa de tudo isso para testar. Logo, se acessar o componente real, seu
teste vai ficar lento, quanto mais lento o teste, mais demorada é a
correção.
#3 O
isolamento é outra questão importante. Os outros componentes que sua
classe de negócio chama podem ter defeitos e isso pode dificultar seu
testes. Usando mocks, você isola seu componente e tem certeza de que, se
existem erros, são da sua classe e não das outras do sistema.
#4
Com os mocks você pode desenvolver suas classes de negócio e testar
mesmo que as outras classes de negócio do sistema não estejam prontas,
você não precisa esperar elas estarem prontas para desenvolver seu
código.
Os testes unitários e a criação de mocks têm o seu custo
e nem sempre devemos criar testes. Em casos muito básicos e simples não
vale a pena testar. Você tem que sempre balancear isto e ver o que vale
a pena ter teste unitário e o que não vale.
Testes de Regressão
Ter
testes unitários é bom porque, além de o desenvolvedor liberar o código
mais redondo, ele permite a aplicação de testes de regressão que nada
mais são do que rodar os testes unitários de novo. Isso é fundamental, porque desta forma você pode modificar o código e tem um mecanismo que lhe
dá o mínimo de segurança de que as suas mudanças não estragaram o resto
da aplicação.
Testes Integrados
Nem
só de testes unitários vive o desenvolvedor. Testes unitários são bons,
mas não são o suficiente. Você vai precisar testar os componentes de
forma integrada, ou seja, você testou seu código de forma isolada,
agora tem que testar de forma conjunta, neste momento você pode colocar
banco de dados, webservices, arquivos e outros sistemas. Este teste
pode rodar em uma freqüência menor do que os testes unitários, pois estes
podem demorar bem mais.
Analise de Testes
Agora
já fugindo do domínio do desenvolvedor. Falando em um nível mais
avançando da implementação do modelo em V e de testes, a questão da
análise de testes é fundamental. Mais hora menos hora você irá precisar
de um analista de testes para trabalhar com isso.
Se você
trabalha com Requisitos e casos de uso, por exemplo, pode criar os casos
de testes a partir do requisitos. Este é o cenário ideal, mas nem
sempre conseguimos isto. Nestes casos a experiência de um analista de
testes ajuda a pegar situações perigosas, mas não é a solução para tudo.
Dependendo
do software, mesmo bem desenvolvido, testar pode não ser tão trivial e
você pode precisar criar a sua estratégia de testes através de um plano
de testes, por exemplo. Dependendo do caso será até necessário a criação
de uma arquitetura de testes.
Barreiras para o teste
A
primeira barreira é cultural. Nem todas as empresas têm cultura de
testes, algumas tratam esta questão como opcional ainda nos dias
de hoje. Quando existem equipes de testes, muitas vezes é
criado um clima de disputa entre desenvolvedores e testadores.
Sempre que vi isso foi em empresas que só possuem testes funcionais, e não testes do desenvolvedor.
Se o desenvolvedor cria testes unitários
e testes integrados, ele começa a ver os testes e os profissionais de
testes de outra forma, e isso facilita a adoção de outros níveis de
testes, além de melhorar a qualidade do produto, processo e do ambiente
profissional.
Adicionar testes em sistemas já existentes ou em
produção é mais difícil, porque muitas vezes o código não é testável.
Muitas equipes acabam escolhendo não criar testes porque não têm tempo
ou recursos para modificar os códigos para deixá-los testáveis.
Criar Código Testável…
Esta
deve ser uma preocupação do desenvolvedor. Dependendo do que o mesmo
fizer, pode ser mais fácil ou mais difícil ou até quase impossível de
testar. Às vezes até teríamos retorno em testar um certo ponto do
sistema, agora o código pode estar muito pouco testável e isso pode
acarretar um esforço tão grande que, no final das contas, se decide não
testar, isto é ruim e só temos a perder com isso.
O ideal é
começar, desde o início, pensando em testes e criando código testável – isso
tudo a partir do desenvolvedor. Como disse antes, isto nem sempre é
possível, eu já passei por essa situação. Neste caso você pode adotar
uma abordagem incremental ligada à manutenção e ao desenvolvimento de
coisas novas.
Quando você tem que realizar alguma manutenção ou
adicionar uma nova funcionalidade no sistema, deve aproveitar o momento
para criar testes unitários e integrados. Eu já fiz isso, depois de um
tempo eu tinha quase todo código com testes e o resultado foi muito bom.
Testar
é uma necessidade básica que começa pela fato de que você precisa saber
se o sistema funciona e termina no fato de que testar diminui os riscos
do projeto e aumenta o retorno para o cliente.
Abraços e até a próxima.







