Muitas equipes XP não automatizam seus testes de aceitação. Essa é uma afirmação dura, porém muito comum de acontecer. A equipe abraça TDD e testes de unidade automatizados, porém quando chega a hora dos testes de aceitação, a coisa complica. Por que isso acontece? Como melhorar essa situação?
Nesse post, inspirado por uma pergunta na XP@Rio, espero dar algumas dicas para ajudar quem tenha se identificado com minha alfinetada. :-)
O que é Teste de Aceitação?
Em primeiro lugar, é bom deixar claro qual a visão Ãgil sobre testes. XP, em particular, pede que sejam escritos dois tipos de testes automatizados:
- Testes de Unidade: testes do programador. Geralmente testa um pedaço isolado do código. Quando seguimos TDD, o teste é escrito antes do código e funciona como especificação, te ajudando a pensar no design. Depois de escrito, serve como documentação executável do seu código.
- Testes de Aceitação: testes do cliente. Um teste de aceitação (ou Story Test, ou Customer Test) descreve um cenário (de sucesso ou não) com uma expectativa do cliente em relação à história ou funcionalidade. Como o nome sugere, ele ajuda a equipe a entender quando uma história está completa (aceita).
Um pequeno adendo: apesar de ser importante reconhecer esses dois tipos de teste propostos por XP, existem outros tipos de teste igualmente importantes como: testes funcionais, de interação, de carga, de segurança, etc… Isso varia conforme sua situação particular, mas esse não é o assunto desse post :-)
Algumas desculpas
Como disse no inÃcio do post, muitas equipes deixam de automatizar seus testes de aceitação. Existem muitas justificativas para explicar esse fato:
- Automatizar testes de aceitação é difÃcil: Testar um sistema web do ponto de vista do usuário ficou muito mais fácil atualmente com ferramentas como o Selenium ou Watir. Testar uma interface gráfica Swing é um pouco mais chato porém não impossÃvel. Testar um software que gera imagens ou modelos visuais (um CAD como o Archimedes, por exemplo) é bem mais difÃcil. Testar um sistema embarcado depende do hardware. Testar um jogo depende de um jogador (automatizar o jogador pode não ser tão fácil). E por aà vai… dependendo da sua situação, tenho que concordar que sua tarefa pode não ser tão fácil. Mas qual a graça de programar sem desafios? :-)
- O teste fica muito grande: Para testar um cenário, geralmente é preciso fazer muito setUp. Você vai precisar criar diversos objetos, suas associações e terá que se preocupar em apagá-los depois (para manter a independência entre os testes e entre diferentes execuções do mesmo teste). Isso pode gerar problemas de dependência e você passa a perder mais tempo fazendo setUp e tearDown do que efetivamente escrevendo os testes importantes.
- O teste demora muito: O problema anterior faz com que seu teste demore muito para executar. Muitas vezes você pode depender de um banco de dados ou de outro sistema para testar um cenário de aceitação real. Se utiliza um sistema de Integração ContÃnua, perceberá rapidamente que seus ciclos de build demoram muito mais.
- O cliente não sabe escrever testes: É muito mais fácil um programador aprender a usar o JUnit ou qualquer framework do que o cliente. É papel da equipe encontrar a melhor forma de comunicação com o cliente. Se o cliente trabalha num banco, tente usar uma planilha ou uma tabela. Se seu sistema é cheio de regras de negócio complicadas, tente explorar os diferentes cenários pensando em exemplos. Infelizmente, não existe uma estratégia universal.
Alguns desses problemas são mais difÃceis que outros. Mas de que adianta falar mal e enumerar problemas sem dar idéias de soluções?
Sugestões para melhorar a situação
Um novo papel
Quando falo que a Toyota eliminou o departamento de qualidade e teve ganhos incrÃveis de produtividade, geralmente recebo olhares espantados e desconfiados, principalmente da equipe de testes.
“Você está dizendo que devo ser demitido?”. Calma, não é bem assim. A Toyota não eliminou sua preocupação com qualidade. Pelo contrário, ela valoriza tanto esse aspecto que compartilhou essa responsabilidade com
TODOS os envolvidos no processo. Não quero que os testadores sejam mandados embora. Pelo contrário, suas habilidades devem ser espalhadas e aproveitadas por todo o processo de desenvolvimento. Devem trabalhar muito mais próximos e não no final da cadeia. Shigueo Shingo já dizia: “Inspecionar para procurar defeitos é desperdÃcio. Inspecionar para previnir defeitos é essencial”.
O papel do testador numa equipe ágil é tão importante quanto o do programador. Ele ajuda a equipe e o cliente a aprimorar suas estratégias de teste (principalmente de aceitação). Eles fazem parte da equipe e também são responsáveis pela entrega! Lembrem-se: a história não está pronta enquanto não estiver testada!
Reaproveitando uma estratégia conhecida
Eu citei os maiores benefÃcios dos testes de unidade e
TDD: eles te ajudam antes, durante e depois. Antes, te ajudam a especificar o problema e pensar no design do código. Durante, eles servem como rede de segurança, identificando um bug de regressão assim que ele é inserido e dando suporte à refatoração sem medo. Depois, servem como documentação executável do seu código, auxiliando você a dar manutenção e novos integrantes a entender o que o sistema faz.
Esses mesmos benefÃcios se aplicam aos testes de aceitação! O Kent Beck percebeu essa
Auto Semelhança na segunda edição do livro de XP. A prática conhecida como
Story Test Driven Development (ou
STDD) funciona exatamente como TDD, porém no nÃvel das histórias. Eu comentei sobre essa prática num
post anterior da XP2007.
O cliente deve colaborar com a equipe para enumerar os cenários de aceitação. Pense em exemplos. Uma pergunta que te ajuda a definir tais cenários é:
“Como saberei que terminei essa história?”. Se seu cliente não sabe ou não quer definir os cenários de aceitação, apenas responda:
“Pronta!”. Os testes de aceitação te ajudam a saber quando a história está pronta. Se o cliente não define nenhum cenário de aceitação, a história está automaticamente pronta (inclusive testada!!). :-)
Ferramentas
Diversas ferramentas e frameworks têm surgido para auxiliar sua vida. Como já disse anteriormente, o
Selenium e o
Watir podem facilitar sua vida no teste de aplicações web. O
FIT, que já comentei
algumas vezes aqui, também te ajuda a sair do lado técnico e define uma linguagem de comunicação mais simples com o cliente (através de tabelas de exemplo). O
Fitnesse armazena essas tabelas (e outras informações) num wiki.
Um framework que atraiu bastante minha atenção ultimamente foi o
RBehave. Atualmente ele está sendo incorporado ao
RSpec, um framework bem conhecido para
BDD em Ruby (e Rails, mais recentemente). O assunto teve até um
tutorial na última
RailsConf na Europa. Ele te permite escrever cenários de aceitação da história de forma executável. Vale a pena dar uma olhada. Tem a versão Java também:
jBehave.
Apesar de ter escrito muito, acredito ter apenas arranhado a superfÃcie desse assunto tão interessante e tão amplo. Para um pouco mais de informações, sugiro ouvir o
AgilCast #9 e assistir alguns dos nossos
AgilVÃdeos.
Também gostaria de saber:
O que você programa/desenvolve? Qual sua estratégia para automatização dos testes de aceitação? O que de legal você fez em relação ao assunto? Qual sua maior dificuldade?