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?
fonte
Respostas:
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".
fonte
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.
fonte
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.
fonte