Quando devo escrever testes de integração?

30

De acordo com as regras do TDD, os testes de unidade são escritos antes do código de produção, mas e os testes de integração que exercitam a interação entre objetos com fio (não zombados) concretos?

Eles devem ser escritos antes dos testes de unidade ou após o código de produção apenas para testar a "fiação"?

Observe que não estou falando de aceitação ou testes funcionais, mas de testes de integração de nível inferior.

Chedy2149
fonte

Respostas:

49

O Rspec Book , entre outros recursos do BDD, sugere um ciclo como este:

insira a descrição da imagem aqui

Em essência, o processo é:

While behaviour required
    Write an integration test for a specific behaviour
    While integration test failing
        Write a unit test to fulfil partial behavior
        While unit test failing
            Write code to make unit test pass
        Commit
        While refactoring can be done
            Refactor
            While unit test failing
                Write code to make unit test pass
            Commit
    Push

Isenção de responsabilidade: Não tenho dúvidas de que isso leva ao melhor código e produto, mas pode ser demorado. Existem todos os tipos de dificuldades em torno de dados e determinismo, quando se trata de dizer que os testes de integração sempre devem passar. Não é apropriado em todas as circunstâncias; às vezes você só precisa tirar as coisas da porta.

Dito isto, ter um processo ideal em mente é ótimo. Dá a você um ponto a partir do qual se comprometer.

pdr
fonte
2
Obrigado @pdr, mas especifiquei que não estava falando sobre testes de aceitação que são escritos antes / no início de uma iteração, estou interessado em testes de integração de nível inferior.
Chedy2149
@ chedy2149: Akkh. Perdeu esse comentário. Antes de remover minha resposta, acho que você deve ser mais específico sobre o que você quer dizer com "nível inferior" no contexto dos testes de integração.
PDR
Nível inferior: qual comportamento não é especificado por usuários ou clientes e que é usado para testar interações de classes / componentes esperado pelos desenvolvedores.
Chedy2149
4
Na verdade, não acho que faça diferença se você colocar "teste de aceitação" ou "teste de integração" nessa imagem - é uma visão idealizada para qualquer tipo de teste em diferentes níveis de abstração. Mas o problema real da IMHO não é que isso possa ser "demorado" - o problema real é que escrever testes de integração "de antemão" contra uma interface pública que ainda está sendo projetada com a ajuda do TDD é como atirar em um "alvo em movimento" "
Doc Brown
@DocBrown, então sua resposta é após o código de produção e antes do lançamento?
Chedy2149
10

Um projeto real me mostrou que não é possível escrever testes de unidade e, em seguida, a integração e mesmo a direção oposta estão erradas :-) Então, eu costumo escrever testes de unidade junto com os de integração.

Por quê? Deixe-me escrever como vejo os dois tipos de testes:

  1. Testes de unidade - Além da Wikipedia e todas as informações conhecidas, os testes de unidade ajudam você a restringir seu design , melhorar seu modelo e relações. O fluxo é simples: quando você começa a digitar novo projeto / novo componente, na maioria das vezes você está criando algum tipo de PoC . Quando você termina, sempre tem métodos longos, classes longas, métodos e classes não coerentes, etc.

    Os testes de unidade ajudam a remover esses problemas, pois quando você faz testes de unidade reais usando as simulações (sem a dependência de outro componente), as classes descritas acima não podem ser testadas. O sinal básico de código não testável é uma grande parte de zombaria dos testes, porque você é forçado a zombar de muitas dependências (ou situações)

  2. Testes de integração - testes corretos e funcionais dizem que seu novo componente (ou componentes) trabalha em conjunto ou com outros componentes - essa é a definição usual. Descobri que os testes de integração principalmente ajudam a definir o fluxo de como usar seu componente do lado do consumidor .

    Isso é realmente importante, pois às vezes diz a você que sua API não faz sentido do lado de fora.

Bem, o que aconteceu depois que escrevi testes de unidade e testes de integração depois?

Eu recebi boas aulas, design claro, bom construtor, métodos curtos e coerentes, pronto para IoC etc. Depois que eu der minha classe / API a algum consumidor, por exemplo, desenvolvedor da equipe de integração ou GUI, ele não poderá usar minha API, pois parece não lógica. , esquisito. Ele estava apenas confuso. Então, reparei a API de acordo com o ponto de vista dele, mas também foi necessário reescrever muitos testes, porque fui pressionado a alterar métodos e, às vezes, até o fluxo de como usar a API.

Bem, o que aconteceu depois que escrevi testes de integração e testes de unidade depois?

Eu tenho fluxo exato, boa usabilidade. O que eu também tenho são classes grandes, código não coerente, sem registro, métodos longos. Código de espaguete

Qual é o meu conselho?

Aprendi o seguinte fluxo:

  1. Desenvolva o esqueleto básico do seu código
  2. Escreva testes de integração que digam se faz sentido do ponto de vista do consumidor. Caso de uso básico é suficiente por enquanto. O teste obviamente não funciona.
  3. Escreva o código junto com os testes de unidade para cada classe.
  4. Escreva o restante / ausente dos testes de integração. Seria melhor implementar esses testes dentro do número 3 de como você está melhorando seu código.

Observe que fiz uma pequena apresentação sobre o teste de unidade / integração, consulte o slide 21, onde o esqueleto é descrito.

Martin Podval
fonte
5

Os testes de unidade são usados ​​para testar o menor bit de software testável possível em um aplicativo e para testar sua funcionalidade. Cada unidade é testada separadamente antes de juntá-las em partes ou em componentes maiores do aplicativo.

É aí que entram os testes de integração :
eles testam essas peças recém-criadas que consistem nas unidades testadas anteriormente durante a montagem dessas peças. O melhor caso seria escrever os testes nesse momento enquanto escrevia o próprio aplicativo.

Ben McDougall
fonte
Então sua resposta é após o código de produção?
Chedy2149
Isso não responde à pergunta. Ele está perguntando se o código de produção é gravado depois que os testes de integração são gravados. Sua resposta pode ser tomada de qualquer maneira.
Reactgular
11
@MathewFoscarini - resposta atualizada. Espero que fique mais claro agora.
Ben McDougall
No que diz respeito aos testes de unidade, eu aceitaria o "menor pedaço possível de software". Teste o que está no contrato (por exemplo, métodos públicos de um objeto, funções exportadas de uma biblioteca) porque o contrato define o que deve funcionar. Outras coisas são testáveis, mas fazer isso não é apenas uma perda de tempo, mas é contraproducente.
precisa saber é o seguinte
3

Costumo ver os testes de integração como muito semelhantes aos testes de unidade. Estou tratando um subconjunto do código como uma caixa preta. Portanto, os testes de integração são apenas uma caixa maior.

Eu prefiro escrevê-los antes do código de produção. Isso tem a vantagem de me ajudar a lembrar quais peças ainda não foram montadas ou que alterei um detalhe na interação dos objetos.

Schleis
fonte
Existem diferentes níveis de teste: teste de componente de caixa branca, teste de componente de integração de caixa branca. Teste de caixa preta de componente, teste de caixa preta de integração. Há também testes de sistema de integração.
Alexander.Iljushkin
2

Além dos testes de aceitação, costumo escrever apenas testes de integração nos limites de um aplicativo, para verificar se ele se integra bem a sistemas ou componentes de terceiros.

A idéia é criar objetos do adaptador que traduzam como os terceiros falam para o que seu aplicativo precisa e testar esses tradutores em relação ao sistema externo real. Se você faz isso primeiro ou último teste, acho que é menos importante do que com seus testes unitários regulares, porque

  • O insight de projeto fornecido pelo TDD não importa tanto aqui, já que o design é bastante conhecido com antecedência e normalmente não há nada terrivelmente complexo envolvido, você apenas mapeia as coisas de um sistema para outro.

  • Dependendo do módulo / sistema que você deseja abordar, isso pode exigir muita exploração, ajustes na configuração, preparação de dados de amostra, o que leva tempo e não se encaixa muito bem em um curto ciclo de feedback do TDD.

No entanto, se você realmente se sentir mais confortável construindo seu adaptador de forma incremental em pequenas etapas seguras, eu recomendaria definitivamente fazer o teste primeiro, não pode machucar.

Você pode encontrar exemplos dessa abordagem aqui: http://davesquared.net/2011/04/dont-mock-types-you-dont-own.html (sexto parágrafo) http://blog.8thlight.com/eric- smith / 2011/10/27 / thats-not-yours.html

guillaume31
fonte
aqui você está falando sobre testes de integração que verificam interações entre "nosso sistema" e bibliotecas de terceiros; que tal testar interações em uma plataforma enquanto desenvolve um plug-in, por exemplo?
Chedy2149
Embora eu tenha pouca experiência com o desenvolvimento de plug-ins, acho que eles podem ser diferentes, pois, por natureza, estão fortemente acoplados ao aplicativo host, portanto, você pode abraçar completamente essa integração e decidir que não precisa de uma camada de adaptador. Nesse caso, eu teria muito cuidado com o desempenho do teste - dependendo do aplicativo host, chamar a API diretamente em um grande número de testes pode ser muito lento. Se você tem medo disso, sempre pode recorrer à abordagem "camada adicional de abstração" e usar testes de integração com zombarias + nos adaptadores.
precisa saber é o seguinte
1

Então, eu estava indo para aceitar a primeira resposta, mas foi excluída.
Para resumir
Em uma determinada iteração:

  1. Escrever teste de unidade
  2. Escreva código de produção
  3. Escreva testes de integração para testar interações

Lembre-se de testar a integração enquanto 1 e 2 para garantir a testabilidade no nível de integração.

Os testes de integração não são necessariamente escritos de ponta a ponta na etapa 3; eles podem ser parcialmente escritos entre as etapas 1 e 2.

Chedy2149
fonte
3
Este resumo ignora completamente a natureza iterativa do processo. Depois de manter a API do seu código de produção estável até certo ponto, você poderá começar a escrever testes de integração. Depois, poderá trabalhar no seu código de produção novamente e provavelmente alterar ou estender seus testes de integração. Portanto, na maioria dos casos, você não "escreve testes de integração após o código de produção", normalmente faz os dois até certo ponto em paralelo. E, na verdade, isso depende muito do tipo de software que você está trabalhando. O pensamento "preto e branco" não o leva mais longe.
Doc Brown
A resposta parece ignorar a natureza iterativa do design por meio da refatoração.
Chedy2149
0

Os testes de unidade testam blocos discretos de código em seu projeto.
Os testes de integração testam como o código interage com outro código: em outras palavras, eles testam a interface do seu código.

Escreva testes de unidade ao desenvolver código atrás de uma interface.
Escreva testes de integração ao desenvolver a interface ou qualquer código que implemente a interface.

Isso significa que, às vezes, você escreve testes de integração muito tarde em um projeto, porque a maior parte do trabalho está por trás da interface: por exemplo, um compilador, um serviço da web específico que implementa várias camadas de lógica ou .. algo que envolve muitas lógica interna.

No entanto, se você estiver implementando um conjunto de serviços REST ou refatorando o modelo de dados e adicionando suporte para transações XA, começará a desenvolver testes de integração quase que imediatamente, porque a maior parte do seu trabalho é centrada na interface, seja a API REST ou como o programa usa o modelo de dados.

Marco
fonte
Você concorda em dizer que os testes de unidade são de caixa branca e os de integração são de caixa preta?
Chedy2149
Infelizmente isso depende. As tecnologias para teste de integração fizeram enormes melhorias nos últimos anos (pelo menos no mundo Java), para que eu possa testar uma classe - mas em um servidor de aplicativos. A questão então se torna: onde está a linha entre testes de unidade e testes de integração? É um teste de integração quando você testa seu código em interface com outras tecnologias ou é um teste de integração quando você testa todo o seu aplicativo - mas não necessariamente no ambiente em que ele é executado?
Marco
Em resumo, em alguns casos, certos testes de integração são de caixa preta - mas não em todos os casos.
Marco
FYI: Wiki define teste de integração como "a fase no teste de software na qual módulos de software individuais são combinados e testados como um grupo"
Marco
Exatamente, Marco. Existem integrações em cada nível de componente. Nível de código, nível de aplicativo, nível do sistema.
Alexander.Iljushkin