Como os testes de integração criticam o design?

38

Estou lendo uma postagem no blog de JB Rainsberger sobre testes integrados e me pergunto de que maneira um teste de integração é mais severo com nosso design?

Escrevemos testes mais integrados, que são maiores e não criticam nosso design com tanta severidade quanto os microtestes

Alex.U
fonte
3
A questão é confusa. "de que maneira um teste de integração é mais duro" ... "testes integrados, que são maiores e não criticam nosso design com tanta severidade" - e agora?
AnoE
"teste de integração"! = "teste integrado". Eu sei. Também não gosto, mas é o que essas palavras significam. "testes de integração" = "testes que verificam os pontos de integração (sem integrar itens)", enquanto "testes integrados" = "(maiores) testes que integram itens e verificam o todo integrado como uma única coisa". Dessa maneira, esses termos se tornam opostos um ao outro.
JB Rainsberger

Respostas:

46

Microtestes podem ajudar a levar a um bom design . Ao escrever bons pequenos testes, você está deliberadamente testando uma pequena quantidade de código e preenchendo suas lacunas com objetos simulados . Isso leva a um baixo acoplamento (as coisas não dependem umas das outras) e alta coesão (as coisas que pertencem uma à outra ficam juntas). Dessa forma, quando você volta e faz alterações, é fácil encontrar o que é responsável pelo que você está procurando e é menos provável que você quebre as coisas ao fazer a alteração. Isso não resolverá todo o seu design, mas pode ajudar.

Nesse contexto, o JB Rainsberger está observando que, se você estiver com dificuldades para escrever um teste de unidade, provavelmente terá um problema com o seu design que está causando a dificuldade e, portanto, os testes estão criticando o design implicitamente. Ele afirma que isso é uma coisa boa, porque sem os pequenos testes ajuda a manter sua arquitetura alinhada, é fácil desviar-se de bons padrões de design - que testes integrados não capturam.

Atualização : como Rainsberger observa abaixo, ele não pretendia que microtestes fossem sinônimos de testes de unidade. Ele também forneceu uma resposta detalhada que pode fornecer informações mais detalhadas sobre exatamente o que ele estava se comunicando.

Thorin Jacobs
fonte
2
Concordo com sua resposta em princípio, mas não da maneira como você a articula. É improvável que alguém que está fazendo essa pergunta em particular saiba o que significam os termos "zombaria", "acoplamento" e "coesão", e você não os definiu em sua resposta.
Robert Harvey
3
É melhor, mas você está dando mais crédito aos testes de unidade do que eu acho que eles realmente devem. Os testes de unidade informam principalmente a testabilidade do seu código. É menos claro se tornar seu código testável automaticamente confere melhores características de coesão e acoplamento, embora seja certamente uma influência positiva. Além disso, acho que você confundiu "alta coesão" com o "princípio de responsabilidade única"; coesão significa "coisas que pertencem juntas" (consulte o artigo da Wikipedia ).
Robert Harvey
10
Finalmente, "micro-testes" não é o termo preferido. Adoro quando os blogueiros criam seus próprios termos técnicos.
Robert Harvey
2
@RubberDuck: Microtestes (cerca de 16.900 resultados) vs testes de unidade (cerca de 193.000.000 resultados) . Nem mesmo perto. Mesmo se você misturar unidade e testar, ainda obtém 14 milhões de resultados.
Robert Harvey
5
Por favor, não iguale "microteste" e "teste de unidade" (veja minha resposta para mais detalhes); caso contrário, sinto que você entendeu o que tentei descrever.
JB Rainsberger
28

A versão extremamente curta: testes menores, porque executam partes menores do sistema, naturalmente restringem o que os programadores podem escrever, e isso cria uma oportunidade para um feedback mais preciso (mais fácil de perceber / mais difícil de ignorar). Permitam-me acrescentar que isso não leva necessariamente a um melhor design, mas, em vez disso, cria a oportunidade de perceber os riscos do design mais cedo.

Primeiro, para esclarecer, quando digo "microteste", quero dizer "um pequeno teste" e nada mais. Uso esse termo porque não quero dizer "teste de unidade": não quero me envolver em debates sobre o que constitui uma "unidade". Eu não ligo (pelo menos não aqui / agora). Provavelmente duas pessoas concordam mais facilmente em "pequenas" do que em "unidades", então gradualmente decidi adotar "microteste" como um termo padrão emergente para essa idéia.

Testes maiores, ou seja, testes que executam partes maiores do sistema em sua parte "ação", tendem a não criticar o design de maneira tão clara e completa quanto os testes menores. Imagine o conjunto de todas as bases de código que poderiam passar em um determinado grupo de testes, significando que eu poderia reorganizar o código e que ainda passaria nesses testes. Para testes maiores, esse conjunto é maior; para testes menores, esse conjunto é menor. Dito de forma diferente, testes menores restringem mais o design, portanto, menos designs podem fazê-los passar. Dessa forma, os microtestes podem criticar mais o design.

Digo "com mais severidade" para evocar a imagem de um amigo que diz diretamente o que você não quer ouvir, mas precisa ouvir, e que grita com você para transmitir urgência de uma maneira que outras pessoas possam não se sentir confortáveis fazendo. Os testes integrados, por outro lado, permanecem calados e apenas sugerem problemas principalmente quando você não tem mais tempo nem energia para resolvê-los. Testes integrados facilitam demais a varredura de problemas de projeto para debaixo do tapete.

Em testes maiores (como testes integrados), os programadores costumam ter problemas devido à negligência: eles têm liberdade suficiente para escrever código emaranhado que, de alguma forma, passa nos testes, mas sua compreensão desse código desaparece rapidamente no momento em que passa para a próxima tarefa. , e outros têm dificuldade indevida na leitura do design emaranhado. Aqui está o risco de confiar em testes integrados. Em testes menores (como microtestes), os programadores tendem a ter problemas com superespecificações: eles restringem demais os testes adicionando detalhes irrelevantes, geralmente copiando / colando do teste anterior e, assim, se pintam com relativa rapidez em um canto. Boas notícias: Acho muito mais fácil e seguro remover detalhes estranhos dos testes várias horas ou dias depois de escrevê-los do que em separar o código de produção emaranhado meses ou anos depois de escrevê-lo. À medida que os erros acontecem, a especificação excessiva causa danos cada vez mais óbvios mais rapidamente, e o programador de alertas percebe antes que precisa consertar as coisas. Considero isso uma força: noto problemas mais cedo e os soluciono antes que esses problemas estrangulem nossa capacidade de adicionar recursos.

JB Rainsberger
fonte
O que você faz sobre o problema de os testes de unidade confiarem mais em suas simulações do que no código real, levando ao problema de testes que parecem passar, mas na verdade não funcionam, porque ninguém manteve as simulações alinhadas com a realidade.
Zan Lynx
@ZanLynx Eu escrevi sobre isso longamente. Comece aqui: blog.thecodewhisperer.com/series#integrated-tests-are-a-scam
JB Rainsberger
9

Ele quer dizer que um bom design de software é mais bem informado pelos testes de unidade do que pelos testes de integração.

Aqui está o porquê. Escrever testes de unidade obriga a escrever um código que pode ser testado por unidade. O código testável por unidade tende a ter um design melhor do que o código que não possui testes de unidade.

Os testes de integração não informam seu código da mesma maneira, porque você está apenas testando a camada externa do software, não as interfaces internas que conectam o software.

Robert Harvey
fonte