Perspectiva:
Então, vamos dar um passo atrás e perguntar o que o TDD está tentando nos ajudar. O TDD está tentando nos ajudar a determinar se nosso código está correto ou não. E por correto, quero dizer "o código atende aos requisitos de negócios?" O ponto de venda é que sabemos que mudanças serão necessárias no futuro e queremos garantir que nosso código permaneça correto depois de fazer essas alterações.
Trago essa perspectiva porque acho que é fácil nos perder nos detalhes e perder de vista o que estamos tentando alcançar.
Princípios - SAP:
Embora eu não seja um especialista em TDD, acho que você está perdendo parte do que o SAP (Single Assertion Principle) está tentando ensinar. O SAP pode ser atualizado como "teste uma coisa de cada vez". Mas o TOTAT não sai da língua tão facilmente quanto o SAP.
Testar uma coisa de cada vez significa que você se concentra em um caso; um caminho; uma condição de contorno; um caso de erro; um qualquer por teste. E a idéia principal por trás disso é que você precisa saber o que quebrou quando o caso de teste falha, para poder resolver o problema mais rapidamente. Se você testar várias condições (ou seja, mais de uma coisa) dentro de um teste e o teste falhar, você terá muito mais trabalho em mãos. Primeiro você precisa identificar quais dos vários casos falharam e depois descobrir por que esse caso falhou.
Se você testar uma coisa de cada vez, seu escopo de pesquisa é muito menor e o defeito é identificado mais rapidamente. Lembre-se de que "testar uma coisa de cada vez" não necessariamente o impede de observar mais de uma saída do processo por vez. Por exemplo, ao testar um "bom caminho conhecido", posso esperar ver um valor específico resultante foo
, assim como outro valor, bar
e posso verificar isso foo != bar
como parte do meu teste. A chave é agrupar logicamente as verificações de saída com base no caso que está sendo testado.
Princípios - PMP:
Da mesma forma, acho que está faltando um pouco sobre o que o PMP (Private Method Principio) tem a nos ensinar. O PMP nos encoraja a tratar o sistema como uma caixa preta. Para uma determinada entrada, você deve obter uma determinada saída. Você não se importa como a caixa preta gera a saída. Você só se importa que suas saídas estejam alinhadas com suas entradas.
O PMP é realmente uma boa perspectiva para examinar os aspectos da API do seu código. Também pode ajudá-lo a definir o que você precisa testar. Identifique seus pontos de interface e verifique se eles atendem aos termos de seus contratos. Você não precisa se preocupar com a maneira como os métodos por trás da interface (também conhecidos como privados) fazem seu trabalho. Você só precisa verificar se eles fizeram o que deveriam fazer.
TDD aplicado ( para você )
Portanto, sua situação apresenta um pouco de rugas além de um aplicativo comum. Os métodos do seu aplicativo são válidos, portanto, a saída deles depende não apenas da entrada, mas também do que foi feito anteriormente. Tenho certeza de que devo <insert some lecture>
dizer aqui que o estado é horrível e blá blá blá, mas isso realmente não ajuda a resolver seu problema.
Eu vou assumir que você tem algum tipo de tabela de diagrama de estados que mostra os vários estados potenciais e o que precisa ser feito para desencadear uma transição. Caso contrário, será necessário, pois ajudará a expressar os requisitos de negócios para esse sistema.
Os testes: primeiro, você terminará com um conjunto de testes que promovem a mudança de estado. Idealmente, você terá testes que exercitam toda a gama de alterações de estado que podem ocorrer, mas posso ver alguns cenários em que talvez você não precise ir nessa extensão completa.
Em seguida, você precisa criar testes para validar o processamento de dados. Alguns desses testes de estado serão reutilizados quando você cria os testes de processamento de dados. Por exemplo, suponha que você tenha um método Foo()
que possua saídas diferentes com base nos estados Init
e State1
. Você desejará usar seu ChangeFooToState1
teste como uma etapa de configuração para testar a saída quando " Foo()
estiver dentro State1
".
Há algumas implicações por trás dessa abordagem que quero mencionar. Spoiler, é aqui que eu vou enfurecer os puristas
Primeiro, você precisa aceitar que está usando algo como teste em uma situação e configuração em outra. Por um lado, isso parece ser uma violação direta do SAP. Mas se você definir logicamente ChangeFooToState1
como tendo dois propósitos, ainda estará conhecendo o espírito do que a SAP está nos ensinando. Quando você precisar garantir que as Foo()
alterações sejam feitas, use-o ChangeFooToState1
como teste. E quando precisar validar Foo()
a saída de State1
"quando estiver", você estará usando ChangeFooToState1
como configuração.
O segundo item é que, do ponto de vista prático, você não desejará testes de unidade totalmente aleatórios para o seu sistema. Você deve executar todos os testes de alteração de estado antes de executar os testes de validação de saída. SAP é o tipo de princípio orientador por trás desse pedido. Para declarar o que deveria ser óbvio - você não pode usar algo como configuração se ele falhar como teste.
Juntar as peças:
Usando seu diagrama de estado, você gerará testes para cobrir as transições. Novamente, usando seu diagrama, você gera testes para cobrir todos os casos de processamento de dados de entrada / saída conduzidos por estado.
Se você seguir essa abordagem, os bloated, complicated, long, and difficult to write
testes deverão ficar um pouco mais fáceis de gerenciar. Em geral, eles devem acabar menores e devem ser mais concisos (isto é, menos complicados). Você deve observar que os testes também são mais dissociados ou modulares.
Agora, não estou dizendo que o processo será completamente indolor, porque escrever bons testes exige algum esforço. E alguns deles ainda serão difíceis porque você está mapeando um segundo parâmetro (estado) em vários de seus casos. E, como um aparte, deve ser um pouco mais evidente por que um sistema sem estado é mais fácil de construir testes. Mas se você adaptar essa abordagem para o seu aplicativo, deverá descobrir que é capaz de provar que seu aplicativo está funcionando corretamente.