Ortogonalidade dos testes unitários vs. concisão dos testes unitários


14

Estou escrevendo testes de unidade para um sistema de direção para um videogame. O sistema possui vários comportamentos (evite esta área por causa do motivo A, evite essa área por causa do motivo B, cada um adicionando um pouco de contexto a um mapa da região. Uma função separada analisa o mapa e produz o movimento desejado.

Estou tendo problemas para decidir como escrever os testes de unidade para os comportamentos. Como o TDD sugere, estou interessado apenas em como os comportamentos afetam o movimento desejado. Por exemplo, evitar por causa da razão A deve resultar em um movimento para longe da má posição sugerida. Na verdade, não me importo como ou por que o comportamento adiciona contexto ao mapa, apenas que o movimento desejado está longe da posição.

Portanto, meus testes para cada comportamento configuram o comportamento, fazem com que ele escreva no mapa e depois executa a função de análise de mapa para calcular o movimento desejado. Se esse movimento satisfaz minhas especificações, estou feliz.

No entanto, agora meus testes dependem dos comportamentos funcionando corretamente e da função de análise de mapa funcionando corretamente. Se a função de análise falhar, eu receberia centenas de testes com falha em vez de alguns. Muitos guias de redação de testes sugerem que é uma má ideia.

No entanto, se eu testar diretamente contra a saída dos comportamentos, zombando do mapa, então certamente estou acoplando muito fortemente à implementação? Se eu conseguir o mesmo movimento desejado no mapa usando um comportamento ligeiramente diferente, os testes ainda deverão passar.

Então agora estou sofrendo dissonância cognitiva. Qual é a melhor maneira de estruturar esses testes?


... não tenho certeza se há uma resposta mágica. Basicamente, você testa coisas que podem quebrar. Então, idealmente, você seria capaz de dizer magicamente quais testes de baixo nível já seriam cobertos suficientemente por testes de alto nível que não precisavam de seus próprios testes de unidade de nível inferior. Outra maneira de analisar isso é: desde o momento em que um teste falha até o momento em que um desenvolvedor corrige o problema, quanto tempo será decorrido? Você quer que esse tempo seja baixo. Se você não tivesse unidades, mas apenas testes funcionais perfeitos (cobertura total de alto nível), esse tempo ainda seria muito alto. Tente usar isso como um guia heurístico.
Calphool

Respostas:


10

No mundo ideal, você realmente teria um conjunto de testes de unidade perfeitamente ortogonais, todos no mesmo nível de abstração.

No mundo real, você costuma fazer testes em vários níveis diferentes do aplicativo, com frequência os testes de nível superior exercem a funcionalidade que já foi testada por testes dedicados de nível inferior. (Muitas pessoas preferem chamar esses testes de nível superior de testes de subsistema / integração ao invés de testes de unidade; no entanto, eles ainda podem ser executados na mesma estrutura de teste de unidade; portanto, do ponto de vista técnico, não há muita diferença.)

Eu não acho isso ruim. O ponto é ter seu código testado da melhor maneira que se encaixa no seu projeto e sua situação, para não aderir à "maneira ideal".


Eu acho que o ponto principal do autor foi se você deve usar topos / simulações ou implementações reais para estes testes de nível superior
SiberianGuy

2

Esse tipo de teste é o motivo pelo qual as simulações foram inventadas. A idéia principal: você escreve uma simulação para o seu objeto (mapa, comportamento, personagem, ...) e depois escreve testes usando essa simulação em vez do objeto real. Às vezes, as pessoas chamam de zombaria de zombaria, e acredito que há outras palavras para ambas.

No seu caso, você escreveria uma farsa para o mapa sempre que precisar testar os comportamentos e outras zombarias para os comportamentos sempre que quiser testar o mapa. Idealmente, suas zombarias seriam muito mais simples do que os comportamentos reais que você está zombando, incorporando apenas métodos ou variáveis ​​que você realmente precisa para esse teste. Talvez você precise escrever uma simulação diferente para cada teste, ou poderá reutilizar algumas zombarias. Independentemente disso, eles devem ser adequados para o teste e não devem tentar ser o mais parecidos com o comportamento real possível.

Se você incluiu alguns exemplos de mapas ou comportamentos, talvez alguém possa fornecer exemplos das zombarias que você pode escrever. Não eu, pois nunca programei um videogame mais avançado que Pong, e mesmo assim seguia um livro, mas talvez alguém versado em testes de unidade e desenvolvimento de jogos.


0

Eu acho que você tenta testar coisas que são de nível muito superior a uma unidade.

A maioria dos testes comportamentais exigiria alguma inteligência por trás disso, para saber se ele se comportou corretamente. Isso não pode ser feito facilmente usando testes automatizados.


por isso mencionei concisão. Posso escrever muito facilmente pequenos testes de unidade para testar linhas de código individuais dentro de um comportamento, e o fiz, mas isso depende da leitura da saída da função de análise de mapa. Nenhum dos meus testes de comportamento é grande, cada um deles testa apenas uma parte da funcionalidade do comportamento.
tenpn
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.