Automação de Testes de Aceitação – Teoria ou Prática

Mais um post esclarecedor e de bom conteúdo, relacionado a Qualidade de Software. Meus parabéns ao trabalho da Gisela Nogueira pelo trabalho de tradução e divulgação! Leia abaixo o texto retirado do InfoQ.

Existem relatos esporádicos do sucesso em escrever requisitos e automatizá-los como teste de aceitação (algumas vezes chamado de test driven requirements, story driven development, e – dependendo de quem você pergunta – behavior driven development).  Até agora essa prática é utilizada por uma minoria da comunidade. Alguns líderes dizem que é uma idéia ruim e um desperdício de esforço. A automação de testes de aceitação escritos no início de cada interação seria somente uma afirmação teórica que se mostrou ineficaz pela falta de utilização?

Primeiramente, vamos definir o que significa automação de testes de aceitação: são testes escritos geralmente no início de uma interação e são uma forma de execução dos requisitos. Eles são exemplos detalhados de como o sistema supostamente deve funcionar quando o requisito descrito está completo – uma resposta para “Como se parece quando está pronto?” Historicamente FIT and FITNesse são as ferramentas escolhidas, no entanto, atualmente existem novas ferramentas como cucumber e rspec.

Esse tipo de teste realmente não pegou. De fato, houve recentemente uma conversa chamada Is FIT Dead?. Também, em uma entrevista com a InfoQ no Agile 2008, Brian Marick fez seu registro:

InfoQ: Então isso parece interessante. Faz sentido para mim estes testes no nível de negócio em si, coisas que o cliente entende e pretende ver. E você fala sobre exemplos. Não sei se você está utilizando isso para simplificar, para se livrar da palavra teste. Mas você está realmente falando sobre testes para cliente, não está? Você pode nos falar mais sobre isso?

Brian: O que tenho notado de interessante é que isso não parece funcionar em nenhum ponto tão bem quanto o teste unitário do Test Driven Design, no seguinte sentido: quando você desenha um teste, você geralmente focaliza tudo o que significa, realmente, um ganho. E claro, os testes unitários fazem a mesma coisa que os testes unitários costumavam fazer. Mas a escrita real do código de teste, que é necessário para criar aquele exemplo, aquele teste automatizado para ser executado sem intervenção humana, com muita freqüência, não tem o mesmo resultado tipo “Oh! Estou realmente satisfeito de ter escrito este código, eu realmente aprendi algo, é meu, eu já escrevi um monte de códigos chatos, e não aprendi nada” então não há uma recompensa por ter escrito aquele código, você não tem um real benefício, além do benefício do próprio teste. E também, aparentemente, estes exemplos externos, não são testes de aceitação que realmente geram conseqüências estruturais profundas como uma refatoração faz em testes unitários. Então a pergunta que eu faço é se o valor está na criação do teste, e há um custo substancial para escrever todo esse código, vale realmente a pena gastar o nosso dinheiro automatizando estes testes? Porque se não compensar financeiramente, por que simplesmente não fazer os testes num quadro, com os programadores implementando-os, um de cada vez, checando-os manualmente, e até mesmo mostrando-os ao dono do produto, manualmente, e ao finalizarmos, simplesmente os apagamos e esquecemos? Porque temos esta necessidade de salvar estes testes e executá-los outra vez e mais e mais vezes, diversas vezes novamente?

Então, existem vários outros lideres na comunidade que ainda recomendam a utilização de testes de aceitação automatizados; entre eles incluem-se nomes como Robert C. Martin, Joshua Kerievsky, e James Shore, para mencionar alguns.

Chris Matts apresenta uma forma interessante de olhar o problema, como um problema de chegada das informações. Suponha que você tenha um processo de desenvolvimento de software (não necessariamente Ágil-específico) que não tem testes de aceitação escritos com antecedência. Os times de QA tipicamente executam seus próprios cenários de teste e quando o defeito é localizado é passado para os desenvolvedores. Esses defeitos são localizados randomicamente e, portanto, afetam a velocidade do time do software randomicamente porque um percentual da sua capacidade é utilizado para detectar esses defeitos. Novas informações chegam randomicamente para o time do desenvolvimento.

Agora, considere se o teste é escrito pelo departamento de QA antes que o desenvolvimento comece. A informação fornecida por esses cenários agora ocorrem no início da interação de forma previsível. Portanto, as incertezas são reduzidas, a velocidade se torna mais estável (menos interrupções randômicas), e isso significa mais previsibilidade.

Então, teste de aceitação automatizada é somente alguma coisa que a elite (ou sorte) consegue fazer funcionar? Existe uma falha interna, que não é vista, que causou a utilização menor do que a esperada? Ou é simplesmente difícil e com eficácia comprovada além de ser uma prática que todo time de desenvolvimento de software deveria adotar?

Como TDD e Pareamento Aumentam a Produtividade

Mais um artigo traduzido, retirado do InfoQ.

“Desenvolvimento orientado a testes” (TDD) e “Pareamento” são duas das práticas ágeis mais conhecidas, e mesmo assim não são postas em prática por muitas equipes ágeis. Com frequência, as pessoas afirmam estar “muito ocupadas” para praticarem TDD e pareamento; em essência, deixando a entender que esforçar-se para produzir um código de alta qualidade reduz a produtividade. Mike Hill explica como esta lógica está muito furada.

Mike afirma, essencialmente, que deve-se “fazer melhor” quem quiser “fazer mais rápido”:

Não só não é verdade que pode-se trocar qualidade interna por mais funcionalidades, o que ocorre é o exato oposto: quanto mais produtividade se deseja, mais elevado deve ser o padrão de qualidade interna.

Se você quer produzir mais, procure primeiramente aumentar sua qualidade interna.

E então ele explica:

Então, por que isso funciona?

  1. Porque qualidade interna e qualidade externa não são a mesma coisa.
  2. Porque o que mais influencia a produção de hoje é a qualidade da produção de ontem.
  3. Porque digitar não é, nem nunca foi o gargalo na hora de escrever código.

Mike continua aprofundando esses três motivos.   Primeiro, ele esclarece o termo “qualidade” para distinguir qualidade externa, que pode ser entendida como o número de funcionalidade em seu produto, de qualidade interna, que se refere ao código por três dessas funcionalidades. Ele faz essa dintinção pra destacar que qualidade externa pode ser diminuída para que o produto esteja no mercado mais rapidamente, enquanto qualidade interna não pode.

Por fim, Mike descreve como “o ontem determina o hoje”, ou como a qualidade interna do código já existente afeta a produtividade atual:

O dia todo, em qualquer coisa que você faça, você estará dependendo de código que já está lá. Cada linha de código que você tiver que estudar vai te deixar mais lento. Cada dependência aberta a mais vai te deixar mais lento. Cada nome de variável mal escolhido vai te deixar mais lento. Qualquer decisão de design deficiente, seja ela grande ou pequena, vai te deixar mais lento.

Se você quer trabalhar o mais rápido possível, você quer trabalhar com código limpo. Ponto final.

Por fim, fala a respeito do equívoco comum de acreditar que pareamento e TDD reduzem a produtividade, porque se vai ter [palavras deste autor] “metade do número de pessoas escrevendo metade do código de produção”. Ele então dá uma lista de 11 atividades comuns que são realizadas quando alguém “codifica”, e então afirma:

Note que escrever código na máquina ocupa apenas uma pequena parcela dessa lista. Isto ocorre porque a parte difícil da programação é pensar, e não digitar. Todas as demais coisas naquela lista (exceto talvez jogar coisas nos outros) está relacionada com atividade intelectual, e não com digitação.

TDD aumenta a produtividade, pois auxilia na hora de pensar. TDD limita back-tracking, e inclusão excessiva de funcionalidades, além de diminuir a necessidade de debugar o código e de ter que estudá-lo para entendê-lo. Pareamento aumenta a produtividade pelo mesmo motivo. Dois desenvolvedores juntos não digitam tão rapidamente quanto dois desenvolvedores separadamente, mas nós não nos importamos: o gargalo é pensar [e não digitar], e tanto pareamento quanto TDD ajudam nesse sentido.

Mike conclui com três sugestões resumidas de como melhorar a produtividade da sua equipe:

Se você quer aumentar a produtividade da sua equipe, faça essas três coisas:

  1. escreva um pequeno teste que falha antes de alterar qualquer coisa no código
  2. faça um acordo “sem par, nada feito”
  3. aja para que todos tenham um entendimento comum sobre qualidade interna

É provável que você conheça alguém (talvez até você mesmo) que acredita que não “tem tempo para parear ou fazer TDD”. O artigo do Mike pode te ajudar.

TDD- desenvolvimento guiado por testes

Este é um assunto muito interessante, mas que gera algumas discussões entre o pessoal de testes, desenvolvimento e os implantadores de alguma metodologia. Particularmente eu sou a favor de que os desenvolvedores codifiquem depois de escrever testes. Isso traz muitos benefícios, sendo dois deles claros: código limpo (sem escrita “macarrônica” e respondendo aos requisitos diretamente) e código testado. Desenvolvedor que escreve testes antes de codificar é desenvolvedor maduro (estive no evento Ruby+Rails no mundo Real e o Carlos Brando apresentou uma palestra sobre o assunto). Colocarei a seguir um texto que li nesses dias a respeito do TDD (Test Driven Development). Foi retirado do Blog do metronus. Desde já parabenizo o autor, e espero que vocês leitores também apreciem.

Uma coisa que sempre considerei interessante é a resistência de alguns de não partir para uma forma de desenvolvimento guiado por testes. Eu, assim que tive contato com este jeito de programar, nunca mais larguei e hoje, confesso, nem consigo fazer de outra forma.Ao me guiar por testes meu códigos sempre saem com qualidade acima da média (melhor que a da maioria no mercado). Este resultado se deve, não por minha suposta genialidade mas sim, por sempre testar de forma minunciosa as coisas (testes unitários, testes de comportamento, etc), escrever testes antes, etc.
Estamos sempre em busca de fazer mais em menos tempo… essa tem sido a missão principal de todos nós seres humanos e claro que não é diferente para desenvolvimento de sistemas. A pressão de prazos, custos, etc são aspectos importantes nos projetos e tem nos levado a buscar alternativas para atender. Por vezes, a opção acaba sendo, fazer sistemas de forma amadora, cheios de “gambiarras” e remendos, tudo para que o sistema seja entregue no dia e lucro desejado. Isso faz sentido, e é interessante, apenas para aquelas consultorias que ganham “rios de dinheiro”, pois além do desenvolvimento, elas aproveitam para vender, também o suporte. Mas para aqueles que desejam entregar coisas com qualidade, para os clientes que precisam de sistemas que realmente apresentem um ROI (retorno de investimento) sastifatório, uma solução tem sido o desenvolvimento guiado por testes, TDD.
Realizar um desenvolvimento guiado por teste significa, sendo bastante simplista, escrever os testes de acordo com a especificação do sistemas e estes determinarem a forma que o sistema serà implementado pois o código para ser aprovado deve passar pelos teste criados. Complicou, a gente descomplica: ao invés de desenvolvermos um sistema e depois testá-lo, verificando se ele funciona, se trata todos os casos, se ele é robusto, tolerante a falhas ,etc; nós escrevemos diversos testes automatizados(unitários, comportamento, etc) e vamos desenvolvendo o sistema de forma a que todos os testes sejam aprovados. Ao inverte a forma de conceber as coisas, um senso comum entre os autores que falam sobre TI, os ganhos são significativos ao ponto de não podermos ignorá-los:
1 – Evita-se desperdício de código: implementa-se o necessário para que teste funcione.
2 – Cobertura total contra falhas: Ao escrever os testes antes evita-se a programação otimista, ou seja, o programador não tem tentação de escrever e testar apenas o “caminho feliz”; escreve-se os testes de acordo com a especificação.
3 – Testes automatizados : sei que muitos poderiam dizer que teste automatizados não um ganho particular do TDD, mas são sua pedra fundamental. Ao automatizar seus testes, a cada nova compilação ou ação sobre o código, todo o sistema será testado garantindo seu funcionamento. Isso, gera uma robustez na solução pois evita que os efeitos colaterais desconhecidos, ao alterar uma aplicação, apareçam somente em produção.
Um gerente mais apegado ao passado poderia dizer que escrever testes antes significa perder tempo, pois ele vai precisar de prever mais dias em seus cronograma para a entrega do sistema. Isso, de certa forma, está correto. Entretanto, o material entregue é de grande qualidade pois foi amplamente testado, retestado, e por aí segue… não teremos retrabalho, horas extras para corrigir bugs desconhecidos, cobertura total para alterações…
Sei que isso não é a “bala de prata”: o fato de usar desenvolvimento guiado por teste, não garante que seu aplicativo será o melhor, ainda existe o talento da equipe, a tecnologia, uma boa especificação, etc. Embora, o uso de TDD em minha opnião, já seja 60% do caminho para tal objetivo.
Na próxima vez que for começar a desenvolver, pense nisso… Permita-se experimentar e espero, que assim como eu, vocês fiquem viciados nessa prática.