DevSecOps

8 jul, 2015

Como eu precisei ver Testes

Publicidade

Alguns fatos:

  • Fato 1: Eu invisto (alguns dizem que eu perco) tempo compreendendo alguma coisa pela qual surja interesse (fato 1).
  • Fato 2: Há algum tempo venho refletindo sobre testes e também – aliás, especialmente –, sobre Test Driven Development (TDD).
  • Fato 3: O último fato, e de menor importância é que este artigo é longo. Logo, se você reclama de textos longos, não acho que valha a pena dedicar seu tempo a ele

Vamos ao que interessa

Conversando com o Diogo Baeder, o Ney Basilio e o Rafael Valeira, acabei juntando uma peça aqui e outra acolá, e encontrando uma maneira realística, não ligada diretamente a software, mas sim à vida, na qual apoiar uma escolha por TDD.

Eu perguntava sobre as dificuldades que tenho em utilizar testes, tais como racionalizar o porquê dos mocks, que criamos e mantemos em paralelo à implementação original para poder isolar completamente uma teste de suas dependências, ou também a diferença entre usar fixtures em um teste e “mockar”, quando uma das resposta me levou a lembrar, não sei porquê, da seguinte frase: “A gente devia ter duas vidas, uma pra treinar e outra pra viver”.

E foi daí que cheguei à síntese de como resolvi encarar testes, e é isso que pretendo apresentar aqui: “um software deve ser desenvolvido para sobreviver em um ambiente previamente definido”.

Se definirmos o domínio de um problema como um mundo e o software como um ser que deve viver naquele mundo, ele, o software, pode ser colocado pra treinar em um mundo simulado (testes) e ir melhorando, antes de passar a realmente viver (live).

O mundo real está lá, com efeitos imprevisíveis. Os usuários (com seu julgamento) estão lá. A latência está lá. A falha em um serviço está lá. Num espaço onde os efeitos são reais. E se pudermos, antes de estar lá, praticar como fazemos em um treinando ou como o faz um jovem aprendiz ou um estudante, tanto melhor.

Mas para isso precisamos pressupor que um software tem certas características:

1. Um software, assim como uma criança, pode, apesar de seus pais o achar perfeito, sofrer com o ambiente em que vive e cresce influenciado pelas companhias. Crescer na companhia de bons softwares/hardwares é muito saudável e o contrário pode fazer com que se pareça errar por sua própria natureza, mas na realidade é só um “bubbles” de coisas que acontecem no ambiente.

Podemos definir uma lei baseada no clichê que é “dize-me com quem andas e te direi quem és“.

2. Um software aprende sempre, mesmo que não tenha sido escrito para isso. Uma regra escrita hoje se prova obsoleta amanhã, porque agora existe um dado que permite mais acurácia. O programador vai alterar aquela regra e, por reflexo, podemos ver, num sistema de versionamento de arquivos, toda a evolução em termos psicológicos, algorítmicos e físicos, a quantidade de código (linhas apagadas, acrescidas e alteradas) e todo o ganho de novas capacidades e aperfeiçoamento das habilidades já existentes.

Podemos definir essa como uma segunda lei, e utilizar aqui a frase “interação e tempo geram conhecimento”.

Precisamos pressupor essas duas características para entender que o melhor lugar para um software aprender a lidar com “as coisas da vida” é o mesmo melhor lugar de quem está em processo de aprendizado.

Este lugar é um ambiente controlado, sem as penalidades reais, onde as situações que precisam ser aprendidas podem ser reproduzidas e seus resultados analisados, para que se saiba o que deve ser aperfeiçoado.

Este lugar tem nome: ele é chamado de “ambiente de testes”. O equivalente para um software do que é a escola, para os humanos.

Construir um lugar assim e utilizá-lo tem um custo, assim como construir um mundo qualquer (consultar os ratos sobre isso), mas é um custo infinitamente menor que o de “errar na realidade. Aliás, se pegarmos o espírito dos seriados de sucesso atual, essa diferença pode ser explicada como a diferença de emoção em passar um capítulo inteiro de Walking Dead atirando em alvos imóveis de feno, ou atirar diretamente em zumbis.

Criar um “mundo ambiente de testes” para que os “seres vivos softwares” possam praticar ser testados é a melhor maneira de garantir que tenham uma vida, um deploy no live, segura e tranquila, sem que seu criador seja apedrejado por heresia.

A conclusão disso foi que, ao escrever testes, o ato de escrevê-los antes é primordial para o relacionamento programador/teste ser positivo (e não simplesmente boring) e que, ao escrever um teste, você está poupando uma vida (uma peça de software deixa de morrer).

Existe uma diferença tênue entre escrever um teste para uma peça de software e escrever uma peça de software através de um teste.

Se softwarelogia existisse, e se tivesse uma missão como a da antropologia, mas voltada a software, teríamos:

  • No primeiro caso, você está lidando com um ser pronto, cuja única parte visível é a externa (interface) e cujo conteúdo, se você quiser conhecer, terá de dissecar (uma tarefa complexa, e o ser pode morrer no processo).
  • No segundo, não existe ser, mas você está dizendo que, para que ele exista, deve atender a certas regras (como um peixe, que obedece a regra de viver grande parte do tempo em meio aquático) e você não precisará dissecá-lo para saber que ele cumpre tal regra, afinal, de inexistente, você, o criador, o fará existente e, fato, ele só conseguirá existir se atender aos requisitos do mundo que você projetou para validá-lo (fatalista, não?!).

Outra coisa muito importante é: ninguém consegue escrever um teste para uma peça de software sem cair na armadilha de concluir que não vai conseguir escrever um teste para um problema que não tenha pensando e tratado no código, porque se não conseguiu imaginar o problema na implementação, também não vai imaginá-lo no teste.

Para quem curte quadrinhos, e leu “A morte do Super Man”, a diferença do que foi definido acima é algo como se o Bertron tivesse criado o Apocalipse em laboratório, de acordo com o que imagina ser o certo, e colocasse ele pra matar o Super Homem (provavelmente o Apocalipse morreria) e criar o mesmo Apocalipse fazendo ele sobreviver no mesmo ambiente que o Super Homem. Praticamente, neste segundo caso, além do benefício de evolução incremental e positiva, ele ainda ganhou um parâmetro com o profiling todo publicado contra o qual comparar a sua criação (a saber, o próprio Super Homem).

O ambiente de testes fica então caracterizado como a peça mais importante dentro do processo de desenvolvimento de software, assim como é a escola dentro da formação de um ser humano.

É nele que um software vai ser confrontado com situações reais, com penalidades controladas, como um aluno que faz uma prova de aritmética e erra o troco de uma compra de 10 Reais quando deu uma nota de 100. Ele pode dizer na escola que o troco é de nove reais e, mesmo assim, não perder dinheiro, mas na vida real, ele teria um prejuízo de… responda aí!

Assim como na escola, o mundo de teste apresenta um novo desafio, à medida que julga que o software está preparado para ele. Você não cria todos os testes que caracterizam o “mundo de provas” de uma vez. Faz isso de maneira incremental, à medida em que vai assistindo à peça de software ir vencendo os desafios anteriores.

Este processo incremental permite que se saiba qual foi o erro, onde ele está e o que deve ser melhorado. Assim como uma prova baseada em um bimestre de aulas, e não em um ano inteiro: corrigir os erros de um bimestre é um processo bem menos doloroso do que corrigir os de um ano inteiro. Da mesma forma, corrigir um algoritmo de 7 linhas é mais compreensível do que corrigir um software de 100 linhas.

Foi assim que tive que pensar em testes para me sentir à vontade enquanto os uso.

Recapitulando

  1. Dize-me com quem andas e te direi quem és: um software deve ser testado isoladamente para que seu comportamento não seja influenciado pelos erros dos outros.
  1. Interação e tempo geram conhecimento: o processo de testes deve ser incremental e seguir uma linha de tempo pré-estabelecida. Isso adiciona conhecimento e permite sua recuperação, não importa se seu software utiliza algoritmos mutáveis ou não. O conhecimento se acumula no servidor de controle de versão de código que você esta utilizando.
  1. Ambiente de testes devem ser levados tão a sério para o software quanto é a escola para a educação de seres humanos: o processo de testes de um software permite uma co-relação com o processo de aprendizado de uma criança.
  2. Crie o ambiente de teste antes do software a ser testado: ninguém que projeta um software deixa de analisar questões que estejam ao seu alcance (falo de pessoas justas). Isso torna impossível em um momento não ver um defeito, e no outro, vê-lo. Na realidade, quando você passa a ver um erro depois do software criado é porque está sendo penalizado por ele com o custo mais caro possível, em produção. Assim como uma criança que deixa a escola, e não é mais criança, é penalizada pela vida quando percebe que não aprendeu algo quando devia tê-lo feito.

***

Texto publicado originalmente na Revista iMasters.