Testes e especificações

Linguagens são umas criaturas muito flexíveis. As melhores linguagens de programação são as mais maleáveis, aquelas que permitem ao programador moldá-las às necessidades da sua aplicação. Quem usa a biblioteca de testes JUnit em Java, faz scripts de build com Rake em Ruby ou usa o Monad IO em Haskell praticamente não pensa nas primitivas da linguagem. Ao invés disso, a mente passeia pelos termos próprios ao domínio da aplicação. Não se pensa em classes, objetos, métodos e funções, mas em casos de teste, tarefas e comandos.

As linguagens naturais não são diferentes, estão o tempo todo mudando. Basta um grupo de pessoas se comunicando para que jargões e dialetos comecem a se formar. Novas palavras surgem e outras saem de moda com uma velocidade surpreendente. Há oito anos atrás, por exemplo, se a palavra “agilidade” fosse citada em uma conferência de desenvolvedores de software, poderia muito facilmente ser associada a soluções rápidas e sujas. Hoje para muita gente é sinônimo de alta iteratividade, valorização do feedback e adaptação constante. Parece mais com rápido e limpo do que com outra coisa qualquer.

Para que algumas palavras mudem de sentido, basta que sejam usadas por duas pessoas diferentes. “Especificação” é uma dessas famigeradas palavras com muitos significados. Muita gente presume que uma especificação é completa, ou seja, que prevê as saídas para todas as entradas possíveis. Por outro lado, outras tantas pessoas presumem apenas que uma especificação é não-ambígua, isto é, pode ser interpretada de um único modo.

Entretanto, a maioria das pessoas — e isto inclui programadores e seus clientes — não conseguem fazer especificações de nenhum desses dois tipos. Pelo menos não naturalmente. Não sem conscientemente se obrigar a isso. Estas especificações acabam saindo tanto ambíguas quanto incompletas. Seria bom que tivéssemos algum tipo de máquina capaz de garantir pelo menos uma dessas duas propriedades.

O que não é muito difícil de se achar…

Computadores são máquinas construídas exclusivamente para seguir instruções. Eles não podem interpretar a mesma instrução de dois modos diferentes. Podemos então escrever nossas especificações como um programa de computador e só vai haver um modo de interpretá-las. Assim eliminamos a ambigüidade e ainda ganhamos a habilidade de executar tudo automaticamente. Só que o nome “especificação” é um tanto quanto controverso, é melhor chamar estes programas somente de testes. Testes são executáveis. Podem não ser especificações, mas são executáveis.

Para executá-los basta fornecê-los ao computador adequado e eles vão rodar rapidamente. Muito mais rápido do que alguém poderia fazer manualmente. Programadores são especialmente bons em generalizar o comportamento esperado do sistema a partir de um conjunto de entradas. Se escrevermos testes para os casos excepcionais, podemos ficar razoavelmente seguros que o código está completo. Caso não esteja, quase sempre podemos encontrar mais testes. Esta segurança é somente estatística, pois é impossível testar todas as entradas na prática, mas é muito mais segurança do que se tem com uma linguagem natural.

Moral da estória: não dá para especificar tudo com testes automáticos, mas dá para especificar muita coisa.



%d blogueiros gostam disto: