A principal diferença, para mim, é que os testes de integração revelam se um recurso está funcionando ou está quebrado, pois enfatizam o código em um cenário próximo à realidade. Eles invocam um ou mais métodos ou recursos de software e testam se agem conforme o esperado.
Pelo contrário, um teste de unidade que testa um único método depende da suposição (geralmente errada) de que o restante do software está funcionando corretamente, porque zomba explicitamente de todas as dependências.
Portanto, quando um teste de unidade para um método que implementa algum recurso é verde, isso não significa que o recurso está funcionando.
Digamos que você tenha um método em algum lugar como este:
public SomeResults DoSomething(someInput) {
var someResult = [Do your job with someInput];
Log.TrackTheFactYouDidYourJob();
return someResults;
}
DoSomething
é muito importante para o seu cliente: é um recurso, a única coisa que importa. É por isso que você geralmente escreve uma especificação de pepino afirmando-a: deseja verificar e comunicar se o recurso está funcionando ou não.
Feature: To be able to do something
In order to do something
As someone
I want the system to do this thing
Scenario: A sample one
Given this situation
When I do something
Then what I get is what I was expecting for
Sem dúvida: se o teste for aprovado, você poderá afirmar que está entregando um recurso funcional. Isso é o que você pode chamar de Valor comercial .
Se você deseja escrever um teste de unidade, DoSomething
deve fingir (usando algumas simulações) que o restante das classes e métodos está funcionando (ou seja: todas as dependências que o método está usando estão funcionando corretamente) e afirmar que seu método está funcionando.
Na prática, você faz algo como:
public SomeResults DoSomething(someInput) {
var someResult = [Do your job with someInput];
FakeAlwaysWorkingLog.TrackTheFactYouDidYourJob(); // Using a mock Log
return someResults;
}
Você pode fazer isso com Injeção de Dependência, ou algum Método de Fábrica ou qualquer Mock Framework ou apenas estendendo a classe sob teste.
Suponha que haja um erro Log.DoSomething()
. Felizmente, a especificação Gherkin o encontrará e seus testes de ponta a ponta falharão.
O recurso não funcionará, porque Log
está quebrado, não porque [Do your job with someInput]
não está fazendo seu trabalho. E, a propósito, [Do your job with someInput]
é de responsabilidade exclusiva desse método.
Além disso, suponha que Log
seja usado em 100 outros recursos, em 100 outros métodos de 100 outras classes.
Sim, 100 recursos falharão. Felizmente, porém, 100 testes de ponta a ponta também estão falhando e revelando o problema. E sim: eles estão dizendo a verdade .
É uma informação muito útil: eu sei que tenho um produto quebrado. Também é uma informação muito confusa: não me diz nada sobre onde está o problema. Ele me comunica o sintoma, não a causa raiz.
No entanto, DoSomething
o teste de unidade é verde, porque ele está usando um falso Log
, construído para nunca quebrar. E sim: está claramente mentindo . Está comunicando que um recurso quebrado está funcionando. Como isso pode ser útil?
(Se DoSomething()
o teste de unidade falhar, verifique se [Do your job with someInput]
há alguns erros.)
Suponha que este seja um sistema com uma classe quebrada:
Um único bug quebrará vários recursos e vários testes de integração falharão.
Por outro lado, o mesmo bug interrompe apenas um teste de unidade.
Agora, compare os dois cenários.
O mesmo bug interrompe apenas um teste de unidade.
- Todos os seus recursos usando o quebrado
Log
são vermelhos
- Todos os seus testes de unidade são verdes, apenas o teste de unidade
Log
é vermelho
Na verdade, os testes de unidade para todos os módulos que usam um recurso quebrado são verdes porque, usando zombarias, eles removeram dependências. Em outras palavras, eles correm em um mundo ideal, completamente fictício. E esta é a única maneira de isolar bugs e procurá-los. Teste de unidade significa zombaria. Se você não está zombando, não é um teste de unidade.
A diferença
Os testes de integração informam o que não está funcionando. Mas eles não servem para adivinhar onde o problema poderia estar.
Os testes de unidade são os únicos testes que informam exatamente onde está o erro. Para desenhar essas informações, eles devem executar o método em um ambiente simulado, onde todas as outras dependências devem funcionar corretamente.
É por isso que acho que a sua frase "Ou é apenas um teste de unidade que abrange 2 classes" está de alguma forma deslocada. Um teste de unidade nunca deve abranger 2 classes.
Essa resposta é basicamente um resumo do que escrevi aqui: Os testes de unidade mentem, é por isso que eu os amo .
Quando escrevo testes de unidade, limite o escopo do código que está sendo testado à classe que estou escrevendo atualmente, zombando de dependências. Se eu estiver escrevendo uma classe Sentença, e a Sentença tiver dependência do Word, usarei uma Palavra simulada. Ao zombar do Word, posso me concentrar apenas em sua interface e testar os vários comportamentos da minha classe Sentença, pois ela interage com a interface do Word. Dessa forma, estou testando apenas o comportamento e a implementação da Sentença e não ao mesmo tempo testando a implementação do Word.
Depois de escrever os testes de unidade para garantir que a Sentença se comporte corretamente quando ele interage com o Word com base na interface do Word, escrevo o teste de integração para garantir que minhas suposições sobre as interações estejam corretas. Para isso, forneço os objetos reais e escrevo um teste que exerce um recurso que acabará usando a frase e o Word.
fonte
Meus 10 bits: D
Sempre me disseram que testes de unidade é o teste de um componente individual - que deve ser exercido ao máximo. Agora, isso tende a ter muitos níveis, já que a maioria dos componentes é feita de peças menores. Para mim, uma unidade é uma parte funcional do sistema. Portanto, ele deve fornecer algo de valor (ou seja, não um método para análise de string, mas talvez um HtmlSanitizer ).
Testes de integração é o próximo passo, é pegar um ou mais componentes e garantir que eles funcionem juntos como deveriam. Você estará acima da complexidade de se preocupar com a forma como os componentes funcionam individualmente, mas quando você insere html no seu HtmlEditControl , ele de alguma forma magicamente sabe se é válido ou não ..
É realmente uma linha móvel. Prefiro me concentrar mais em fazer com que o maldito código funcione ponto final ^ _ ^
fonte
Os testes de unidade usam zombarias
Você está falando sobre testes de integração que realmente testam toda a integração do seu sistema. Mas quando você faz o teste de unidade, deve realmente testar cada unidade separadamente. Tudo o resto deve ser ridicularizado. Portanto, no seu caso de
Sentence
classe, se ele usaWord
classe, suaWord
classe deve ser ridicularizada. Dessa forma, você testará apenas aSentence
funcionalidade da sua classe.fonte
Acho que quando você começa a pensar em testes de integração, está falando mais de um cruzamento entre as camadas físicas, e não as lógicas.
Por exemplo, se seus testes se preocupam em gerar conteúdo, é um teste de unidade: se seu teste se refere apenas à gravação em disco, ainda é um teste de unidade, mas depois que você testar a E / S e o conteúdo do arquivo, então você terá um teste de integração. Quando você testa a saída de uma função em um serviço, é um teste de unidade, mas depois que você faz uma chamada de serviço e vê se o resultado da função é o mesmo, então é um teste de integração.
Tecnicamente, você não pode testar apenas uma classe. E se a sua turma for composta por várias outras turmas? Isso o torna automaticamente um teste de integração? Acho que não.
fonte
usando design de responsabilidade única, preto e branco. Mais de uma responsabilidade, é um teste de integração.
Pelo teste do pato (aparência, charlatão, gingado, é um pato), é apenas um teste de unidade com mais de um objeto novo nele.
Quando você entra no mvc e o testa, os testes do controlador sempre são integrados, porque o controlador contém uma unidade modelo e uma unidade de exibição. Testando a lógica nesse modelo, eu chamaria de teste de unidade.
fonte
A natureza dos seus testes
Um teste de unidade do módulo X é um teste que espera (e verifica) problemas apenas no módulo X.
Um teste de integração de muitos módulos é um teste que espera problemas que surjam da cooperação entre os módulos, para que seja difícil encontrar esses problemas usando apenas testes de unidade.
Pense na natureza de seus testes nos seguintes termos:
Lembre-se de que um teste de integração ainda pode stub / fake / mock algumas de suas dependências. Isso fornece um meio termo entre testes de unidade e testes de sistema (os testes de integração mais abrangentes, testando todo o sistema).
Abordagem pragmática do uso de ambos
Portanto, uma abordagem pragmática seria: Confie de forma flexível nos testes de integração o máximo possível e use testes de unidade onde isso seria arriscado ou inconveniente demais. Essa maneira de pensar pode ser mais útil do que alguma discriminação dogmática de testes de unidade e testes de integração.
fonte
No teste de unidade, você testa todas as partes isoladas:
no teste de integração, você testa muitos módulos do seu sistema:
e é isso que acontece quando você usa apenas testes de unidade (geralmente as duas janelas estão funcionando, infelizmente não estão juntas):
Fontes: source1 source2
fonte
Na minha opinião, a resposta é "Por que isso importa?"
É porque testes de unidade são algo que você faz e testes de integração são algo que você não faz? Ou vice-versa? Claro que não, você deve tentar fazer as duas coisas.
É porque os testes de unidade precisam ser rápidos, isolados, repetíveis, com auto-validação e oportuna, e os testes de integração não devem? Claro que não, todos os testes devem ser esses.
É porque você usa zombarias em testes de unidade, mas não em testes de integração? Claro que não. Isso implicaria que, se eu tiver um teste de integração útil, não tenho permissão para adicionar uma simulação para alguma parte, receio ter que renomear meu teste para "teste de unidade" ou entregá-lo a outro programador para trabalhar.
É porque os testes de unidade testam uma unidade e os testes de integração testam várias unidades? Claro que não. De que importância prática é essa? De qualquer maneira, a discussão teórica sobre o escopo dos testes é interrompida na prática, porque o termo "unidade" depende inteiramente do contexto. No nível da classe, uma unidade pode ser um método. No nível da montagem, uma unidade pode ser uma classe e, no nível do serviço, uma unidade pode ser um componente. E até as classes usam outras, então qual é a unidade?
Isso não tem importância.
O teste é importante, o PRIMEIRO é importante, dividir os cabelos sobre as definições é uma perda de tempo que confunde apenas os novatos nos testes.
fonte
Eu acho que ainda chamaria algumas classes de interação de teste de unidade, desde que os testes de unidade da classe1 estejam testando os recursos da classe1, e os testes de unidade da classe2 estão testando seus recursos e também que eles não estão atingindo o banco de dados.
Eu chamo um teste de teste de integração quando ele percorre a maior parte da minha pilha e atinge o banco de dados.
Eu realmente gosto dessa pergunta, porque a discussão sobre TDD às vezes parece um pouco purista demais para mim, e é bom para mim ver alguns exemplos concretos.
fonte
Eu faço o mesmo - eu os chamo de todos os testes de unidade, mas em algum momento tenho um "teste de unidade" que cobre tanto o nome que muitas vezes o renomeio para "..IntegrationTest" - apenas uma alteração de nome, nada mais muda.
Eu acho que há uma continuação de "testes atômicos" (testando uma classe minúscula ou um método) para testes de unidade (nível de classe) e testes de integração - e depois testes funcionais (que normalmente cobrem muito mais coisas de cima para baixo) - parece não haver um corte limpo.
Se o seu teste configurar dados e talvez carregar um banco de dados / arquivo, etc., talvez seja mais um teste de integração (acho que os testes de integração usam menos zombarias e mais classes reais, mas isso não significa que você não pode zombar de alguns do sistema).
fonte
Teste de unidade é um método de teste que verifica se as unidades individuais do código fonte estão funcionando corretamente.
Teste de integração é a fase do teste de software na qual os módulos de software individuais são combinados e testados como um grupo.
A Wikipedia define uma unidade como a menor parte testável de um aplicativo, que em Java / C # é um método. Mas, no seu exemplo da classe Word e Sentença, eu provavelmente escreveria os testes para a sentença, pois provavelmente consideraria um exagero usar uma classe de palavras simuladas para testar a classe de sentenças. Portanto, a sentença seria minha unidade e a palavra é um detalhe de implementação dessa unidade.
fonte
Testes de integração: a persistência do banco de dados é testada.
Testes de unidade: o acesso ao banco de dados é ridicularizado. Métodos de código são testados.
fonte
Teste de unidade é um teste contra uma unidade de trabalho ou um bloco de código, se você preferir. Geralmente realizado por um único desenvolvedor.
Teste de integração refere-se ao teste executado, preferencialmente em um servidor de integração, quando um desenvolvedor confirma seu código em um repositório de controle de origem. O teste de integração pode ser executado por utilitários como o Cruise Control.
Portanto, você faz seu teste de unidade para validar que a unidade de trabalho que você criou está funcionando e, em seguida, o teste de integração valida que o que você adicionou ao repositório não quebrou outra coisa.
fonte
Eu chamo de testes de unidade aqueles testes que a caixa branca testa uma classe. Quaisquer dependências exigidas pela classe são substituídas por falsas (zombarias).
Testes de integração são aqueles em que várias classes e suas interações são testadas ao mesmo tempo. Apenas algumas dependências nesses casos são falsificadas / falsificadas.
Eu não chamaria os testes de integração do Controlador, a menos que uma de suas dependências seja real (ou seja, não falsificada) (por exemplo, IFormsAuthentication).
A separação dos dois tipos de testes é útil para testar o sistema em diferentes níveis. Além disso, os testes de integração tendem a ter vida longa e os testes de unidade devem ser rápidos. A distinção de velocidade de execução significa que eles são executados de maneira diferente. Em nossos processos de desenvolvimento, os testes de unidade são executados no check-in (o que é bom, porque são super rápidos) e os testes de integração são executados uma vez / duas vezes por dia. Eu tento executar testes de integração o mais rápido possível, mas geralmente atingindo o banco de dados / gravando em arquivos / tornando o rpc / etc lento.
Isso levanta outro ponto importante: os testes de unidade devem evitar atingir as entradas / saídas (por exemplo, disco, rede, banco de dados). Caso contrário, eles diminuem bastante. É preciso um pouco de esforço para projetar essas dependências de E / S - não posso admitir que fui fiel à regra "os testes de unidade devem ser rápidos", mas se você for, os benefícios em um sistema muito maior se tornam aparentes rapidamente .
fonte
Explicação simples com analogias
Os exemplos acima se dão muito bem e não preciso repeti-los. Então, vou me concentrar em usar exemplos para ajudá-lo a entender.
Testes de integração
Os testes de integração verificam se tudo está funcionando juntos. Imagine uma série de engrenagens trabalhando juntas em um relógio. Um teste de integração seria: o relógio está indicando a hora correta? Ainda está informando a hora correta em 3 dias?
Tudo o que você diz é se a peça geral está funcionando. Se falhar: não informa exatamente onde está falhando.
Testes unitários
Estes são realmente tipos específicos de teste. Eles dizem se uma coisa específica está funcionando ou falhando. A chave para esse tipo de teste é que ele testa apenas uma coisa específica, assumindo que todo o resto está funcionando bem. Esse é o ponto chave.
Exemplo: Vamos elaborar neste ponto usando um exemplo:
Usando Stubs
Suponha que seu teste de integração de carro falhe. Não conduz com sucesso a Echuca. Onde está o problema?
Agora, suponhamos que o seu motor use um sistema especial de injeção de combustível e que esse teste de unidade do motor também falhou. Em outras palavras, o teste de integração e o teste da unidade do motor falharam. Onde então está o problema? (Dê a si mesmo 10 segundos para obter a resposta.)
O problema está no motor ou no sistema de injeção de combustível?
Você vê o problema aqui? Você não sabe exatamente o que está falhando. Se você usar dependências externas diferentes, cada uma dessas 10 poderia ter causado o problema - e você não saberá por onde começar. É por isso que os testes de unidade usam stubs para assumir que todo o resto está funcionando bem.
fonte
Um pouco acadêmica essa questão, não é? ;-) Meu ponto de vista: para mim, um teste de integração é o teste de toda a parte, não se duas de cada dez partes estiverem juntas. Nosso teste de integração mostra se a compilação principal (contendo 40 projetos) será bem-sucedida. Para os projetos, temos toneladas de testes de unidade. O mais importante para os testes de unidade para mim é que um teste de unidade não deve depender de outro teste de unidade. Então, para mim, os dois testes que você descreve acima são testes de unidade, se forem independentes. Para testes de integração, isso não precisa ser importante.
fonte
Eu acho que sim e sim. Seu teste de unidade, que abrange 2 classes, tornou-se um teste de integração.
Você pode evitá-lo testando a classe Sentença com implementação simulada - classe MockWord, que é importante quando essas partes do sistema são grandes o suficiente para serem implementadas por diferentes desenvolvedores. Nesse caso, o Word é testado em unidade sozinho, Sentença é testado em unidade com a ajuda do MockWord e, em seguida, Sentença é testado em integração com o Word.
Um exemplo da diferença real pode ser o seguinte 1) A matriz de 1.000.000 elementos é facilmente testada em unidade e funciona bem. 2) O BubbleSort é facilmente testado em uma matriz simulada de 10 elementos e também funciona bem. 3) O teste de integração mostra que algo não está tão bem.
Se essas partes forem desenvolvidas por uma única pessoa, o problema mais provável será encontrado durante o teste de unidade do BubbleSoft apenas porque o desenvolvedor já possui um array real e ele não precisa de uma implementação simulada.
fonte
Além disso, é importante lembrar que os testes de unidade e de integração podem ser automatizados e gravados usando, por exemplo, JUnit. Nos testes de integração do JUnit, é possível usar a
org.junit.Assume
classe para testar a disponibilidade de elementos do ambiente (por exemplo, conexão com o banco de dados) ou outras condições.fonte
Se você é um purista de TDD, escreve os testes antes de escrever o código de produção. Obviamente, os testes não serão compilados, então você primeiro faz os testes compilarem e depois passar os testes.
Você pode fazer isso com testes de unidade, mas não com testes de integração ou aceitação. Se você tentasse com um teste de integração, nada seria compilado até você terminar!
fonte