
Compartilhar:
Yonatan já participou de alguns projetos incríveis tanto no meio acadêmico quanto no setor privado — desde C/C++, passando por Matlab, até PHP e JavaScript. Ex-CTO da Webiks e arquiteto de software na WalkMe. Atualmente, ele é arquiteto de software na Vonage e instrutor na Egghead.
Como os testes de software podem contribuir para a comunicação
Tempo de leitura: 6 minutos
Os testes de software podem melhorar a comunicação e economizar tempo (e frustração). Testes mal elaborados podem ter o efeito contrário. Neste artigo, vamos explorar um exemplo da vida real que mostra como testes mal elaborados são prejudiciais e como os bons transmitem as informações corretas.
Uma história sobre um título
Em Vivid, precisávamos adicionar um título ao nosso botão. Não é que o botão não tivesse um. O Vivid é uma biblioteca baseada em componentes da web e, dentro do nosso elemento de botão, há um botão nativo oculto no Shadow DOM.
Esse botão nativo não herdou o título do elemento pai, o que prejudicava a acessibilidade do nosso site (com base em padrões de ).
Então… a tarefa era bem simples. Pegar um título do host (o elemento personalizado) e exibi-lo no botão interno. Simples assim:

Vamos usar esse exemplo e acompanhar seu histórico de commits para entender e aprender como evitar erros simples em testes.
Lição nº 1: Mudar a interface é um sinal de alerta
O primeiro commit nesta solicitação de pull alterou a interface. Aqui está a alteração no teste:

Isso fez com que os testes falhassem. Dá para ver que o teste mudou de toBeFalsy para “ser igual a uma string vazia”. O que há de errado nisso?
Há três erros neste caso:
toBeFalsypode ser várias coisas (uma string vazia,null,undefined,NaN, 0 efalse), mas, ao contrário de uma string vazia, não é aberta.A interface não estava documentada de forma adequada, porque
toBeFalsyé muito abrangente.A interface foi alterada para '' no teste, por algum motivo. Qual é o motivo disso? Trata-se de uma alteração que causa incompatibilidade?
Aí, a história fica mais complicada. Esses dois erros são apenas a entrada para uma perda de 24 horas de desenvolvimento. Vamos ao prato principal.
Como testes ruins levam a código ruim
Enquanto tentava ajudar a resolver o problema com o teste que não estava funcionando, eu estava voltando de férias.
Analisei o código de teste pelo celular e percebi que a interface documentada indicava que o valor do título deveria ser uma string vazia.
“Ora, é claro que não funciona! O valor inicial não é uma string vazia. Basta defini-lo como uma string vazia, e vai funcionar.”
A alteração foi bem fácil. Basta definir o valor no construtor, e o teste será aprovado:

Essa correção agravou o problema que observamos no primeiro erro. Não só alteramos a documentação, como também modificamos a própria interface. Sim, os testes foram aprovados, mas será que eram os testes certos? E como é que algo tão simples nos custou 24 horas de trabalho? Vamos passar para o segundo erro.
Erro nº 2: Não passarás (pelo motivo certo)
A mudança na interface foi apenas o primeiro passo. Ainda havia uma lógica propriamente dita a ser implementada, certo? Aqui está o teste para a próxima implementação:

A primeira coisa que aparece é a descrição do teste. O erro ortográfico (falta “set” depois de “not”) é o erro mais evidente ali, mas há algo mais.
A descrição está redigida na forma negativa. Na ciência, não é possível provar que algo não existe. Como o software faz parte da Ciência da Computação, podemos encarar a questão da mesma forma. Não me diga o que ele não deve fazer — diga-me o que ele deve fazer.
Há duas coisas ainda piores do que a descrição no próprio código de teste. Reserve um minuto para ver se consegue identificá-las.
…
…
Tudo bem, o minuto já passou. Você encontrou mais um ou dois erros?
Motivo errado nº 1: testar a coisa errada
Mencionei no início que nossa missão era definir o título no botão interno. Este teste não descreve esse cenário.
Você percebe que o teste é feito no elemento, e não no botão interno? Quando li o teste, presumi que o autor quisesse que o título aparecesse no elemento. É isso que diz a documentação. E é isso que espero que o componente faça.
Motivo errado nº 2: a expectativa não corresponde à descrição
Outra questão é que, nesse teste, espera-se que o título seja uma string vazia. O que queremos alcançar é totalmente diferente: queremos remover o atributo “title” nesse caso.
Passaram-se 12 horas e eu já estava de volta em casa depois das férias, pensando em como implementar o código para atender às especificações fornecidas.
Algumas mensagens no Slack confirmaram minhas suspeitas — o atributo “title” deve ser removido quando o valor do título for falsy. Não tive a menor dúvida de que o título não deveria ser definido nesse elemento.
Alterei um pouco o teste para ter certeza de que estamos no caminho certo:
t
Agora, a expectativa é que o atributo seja realmente removido.
Para que fosse aprovado, tive que alterar algumas coisas no modelo e na classe do componente. Na classe, tive que sobrescrever o atributo “title” (nosso Class estende outro elemento básico Class). Também tive que definir um conversor que defina o valor como `null` no modelo se o valor for falsy, mas o deixe como uma string se for alterado a partir da própria visualização:

Tudo correu como esperado. Eu me esforcei e esperava ouvir elogios da autora do comunicado de imprensa, dizendo que eu tinha salvado o dia dela. Ou… não?
A comunicação é fundamental
A mensagem esperada no Slack chegou algumas horas depois. O conteúdo da mensagem, porém, foi menos esperado:

Espera aí, O QUÊ?!?
E assim começou mais uma troca de mensagens no Slack. Foi curta, mas, no fim das contas, essa foi a minha opinião:

Fiquei chocado quando foi revelado que o problema estava no botão interno.
A correção, como era de se esperar, foi mínima. Tive que realizar o teste tanto no elemento quanto no botão interno (chamamos esses elementos de “elementos de controle”):

Agora que já tínhamos um teste em funcionamento, também poderíamos garantir que nosso valor inicial fosse mais específico e estivesse de acordo com a especificação HTML (nulo):

Essa correção simples nos levou 24 horas (sim, eu sei que passei metade desse tempo de férias, mas desculpas são para os fracos 😉 ). Isso poderia ter sido evitado com testes mais eficazes ou com uma melhor comunicação da minha parte.
Conclusão
Como escrever bons testes
Os testes devem falhar quando o seu código não faz o que deveria. Os testes também devem ser uma descrição direta de como o seu código funciona. Se o teste indicar que um título deve estar presente no elemento, essas são as instruções para quem vai implementar o código.
A interface também é protegida por testes. Se o teste não proteger a interface corretamente ou com rigor suficiente (como no caso do toBeFalsy em vez de toBeNull exemplo aqui), então não sabemos realmente o que esperar, tanto como desenvolvedores quanto como usuários da interface. Você pode ler mais sobre a importância dos testes de interface no meu post, Uma História de Implementação e Detalhes.
Elaboração de testes para fins de comunicação
É importante ter boas habilidades de comunicação. Nem todo mundo as possui. Especialmente em ambientes de trabalho remoto. Se estivéssemos programando juntos pessoalmente, isso talvez não tivesse demorado tanto. Nossa equipe trabalha remotamente (é uma equipe internacional) e a comunicação costuma ser “assíncrona” – o que significa que geralmente há um atraso na resposta.
Escrever os testes corretamente, com uma descrição clara e uma lógica que explique como eles devem ajudar a mitigar esses erros de comunicação na equipe.
Venha participar da conversa na nossa Slack da Comunidade Vonage ou envie-nos uma mensagem no X, antes conhecido como Twitter.
Compartilhar:
Yonatan já participou de alguns projetos incríveis tanto no meio acadêmico quanto no setor privado — desde C/C++, passando por Matlab, até PHP e JavaScript. Ex-CTO da Webiks e arquiteto de software na WalkMe. Atualmente, ele é arquiteto de software na Vonage e instrutor na Egghead.