O que é teste de unidade? [fechadas]


211

Vi muitas perguntas perguntando 'como' fazer o teste de unidade em um idioma específico, mas nenhuma pergunta perguntando 'o que', 'por que' e 'quando'.

  • O que é isso?
  • O que isso faz por mim?
  • Por que devo usá-lo?
  • Quando devo usá-lo (também quando não)?
  • Quais são algumas das armadilhas e equívocos comuns

Uber, existem muitos recursos disponíveis, e o artigo da Wikipedia é certamente um ótimo lugar para começar. Depois de ter uma idéia básica, talvez algumas perguntas mais específicas possam ajudá-lo a decidir por si mesmo se deseja usar o teste de unidade.
Palehorse

Conversas sobre códigos limpos: youtube.com/watch?v=wEhu57pih5w
Kieran

1
Essa não é uma pergunta específica. São 5 questões amplas.
precisa

9
Ainda bem que você fez essa pergunta, ler uma resposta de um programador ativo é muito melhor e direto ao ponto em comparação à leitura de recursos on-line.
Pratyush Dhanuka

Respostas:


197

O teste de unidade está, grosso modo, testando bits do seu código isoladamente com o código de teste. As vantagens imediatas que vêm à mente são:

  • A execução dos testes se torna automatizada e repetível
  • Você pode testar em um nível muito mais granular do que o teste de apontar e clicar por meio de uma GUI

Observe que, se o código de teste gravar em um arquivo, abrir uma conexão com o banco de dados ou fazer algo pela rede, ele será categorizado como um teste de integração. Testes de integração são uma coisa boa, mas não devem ser confundidos com testes de unidade. O código do teste de unidade deve ser curto, suave e rápido de executar.

Outra maneira de analisar o teste de unidade é escrever primeiro os testes. Isso é conhecido como Desenvolvimento Orientado a Testes (TDD). TDD traz vantagens adicionais:

  • Você não escreve código especulativo "Talvez eu precise disso no futuro" - apenas o suficiente para fazer os testes passarem
  • O código que você escreveu é sempre coberto por testes
  • Ao escrever o teste primeiro, você é forçado a pensar em como deseja chamar o código, o que geralmente melhora o design do código a longo prazo.

Se você não está fazendo testes de unidade agora, recomendo que você comece a usá-lo. Obtenha um bom livro, praticamente qualquer livro xUnit fará porque os conceitos são muito transferíveis entre eles.

Às vezes, escrever testes de unidade pode ser doloroso. Quando isso acontecer, tente encontrar alguém para ajudá-lo e resista à tentação de "apenas escrever o maldito código". O teste de unidade é como lavar a louça. Nem sempre é agradável, mas mantém sua cozinha metafórica limpa e você realmente quer que ela seja limpa. :)


Edit: Um equívoco vem à mente, embora eu não tenha certeza se é tão comum. Ouvi um gerente de projeto dizer que os testes de unidade fizeram a equipe escrever todo o código duas vezes. Se parece e parece assim, bem, você está fazendo errado. A escrita dos testes não apenas acelera o desenvolvimento, mas também fornece um indicador conveniente "agora estou pronto" que você não teria de outra maneira.


2
Você expandiria seu argumento sobre como o TDD acelera o desenvolvimento?
297 Martin

70

Não discordo de Dan (embora uma escolha melhor possa ser apenas para não responder) ... mas ...

Teste de unidade é o processo de escrever código para testar o comportamento e a funcionalidade do seu sistema.

Obviamente, os testes melhoram a qualidade do seu código, mas isso é apenas um benefício superficial do teste de unidade. Os benefícios reais são:

  1. Facilite a alteração da implementação técnica e certifique-se de não alterar o comportamento (refatoração). O código devidamente testado em unidade pode ser agressivamente refatorado / limpo com poucas chances de quebrar algo sem perceber.
  2. Dê confiança aos desenvolvedores ao adicionar comportamento ou fazer correções.
  3. Documente seu código
  4. Indique áreas do seu código que estão fortemente acopladas. É difícil codificar o código de teste unitário
  5. Forneça um meio de usar sua API e procure dificuldades desde o início
  6. Indica métodos e classes que não são muito coesas

Você deve realizar o teste de unidade, pois é do seu interesse entregar um produto de manutenção e de qualidade ao seu cliente.

Eu sugiro que você o use para qualquer sistema ou parte de um sistema que modele o comportamento do mundo real. Em outras palavras, é particularmente adequado para o desenvolvimento empresarial. Eu não o usaria para programas descartáveis ​​/ utilitários. Eu não o usaria para partes de um sistema que são problemáticas para testar (a interface do usuário é um exemplo comum, mas esse nem sempre é o caso)

A maior armadilha é que os desenvolvedores testam uma unidade muito grande ou consideram um método uma unidade. Isso é particularmente verdade se você não entender a Inversão do controle - nesse caso, seus testes de unidade sempre se transformarão em testes de integração de ponta a ponta. O teste de unidade deve testar comportamentos individuais - e a maioria dos métodos tem muitos comportamentos.

O maior equívoco é que os programadores não devem testar. Somente programadores ruins ou preguiçosos acreditam nisso. O cara que está construindo seu telhado não deve testá-lo? O médico que substituir uma válvula cardíaca não deve testar a nova válvula? Somente um programador pode testar se seu código faz o que ele pretendia fazer (o controle de qualidade pode testar casos extremos - como o código se comporta quando é instruído a fazer coisas que o programador não pretendia e o cliente pode fazer o teste de aceitação - o código faz o que o cliente pagou para fazer)


44

A principal diferença do teste de unidade, em vez de "apenas abrir um novo projeto e testar esse código específico", é que ele é automatizado , portanto, repetível .

Se você testar seu código manualmente, poderá convencê-lo de que o código está funcionando perfeitamente - no estado atual . Mas e uma semana depois, quando você fez uma ligeira modificação? Você deseja testá-lo novamente novamente manualmente sempre que algo mudar no seu código? Provavelmente não :-(

Mas se você pode executar os testes a qualquer hora, com um único clique, exatamente da mesma maneira, dentro de alguns segundos , em seguida, eles irão mostrar-lhe imediatamente sempre que algo está quebrado. E se você também integrar os testes de unidade em seu processo automatizado de criação, eles o alertarão sobre erros, mesmo nos casos em que uma mudança aparentemente completamente diferente quebrou algo em uma parte distante da base de código - quando nem sequer lhe ocorreu que existe uma necessidade de testar novamente essa funcionalidade específica.

Essa é a principal vantagem dos testes de unidade sobre os testes manuais. Mas espere, há mais:

  • Os testes de unidade diminuem drasticamente o ciclo de feedback de desenvolvimento : com um departamento de testes separado, pode levar semanas para você saber que existe um bug no seu código; nesse momento, você já esqueceu muito do contexto; portanto, pode levar horas para encontre e corrija o erro; OTOH com testes de unidade, o ciclo de feedback é medido em segundos e o processo de correção de erros geralmente ocorre ao longo de um "oh sh * t, eu esqueci de verificar essa condição aqui" :-)
  • testes de unidade documentam efetivamente (sua compreensão) o comportamento do seu código
  • O teste de unidade obriga a reavaliar suas opções de design, o que resulta em um design mais simples e limpo

As estruturas de teste de unidade, por sua vez, facilitam a gravação e a execução de seus testes.


Além disso, minha parte favorita sobre o código de teste (especialmente quando recebe uma nova base de código): demonstra o uso esperado do código em teste.
Steven Evers

34

Nunca fui ensinado a testar unidade na universidade, e levei um tempo para "obtê-lo". Eu li sobre isso, fui "ah, certo, testes automatizados, isso poderia ser legal, eu acho", e então eu esqueci.

Demorou um pouco mais para eu entender o ponto: digamos que você esteja trabalhando em um sistema grande e que escreva um pequeno módulo. Ele compila, você o acompanha, funciona muito bem, passa para a próxima tarefa. Nove meses depois e duas versões depois, outra pessoa faz uma alteração em alguma parte aparentemente não relacionada do programa e quebra o módulo. Pior, eles testam suas alterações e seu código funciona, mas não testam seu módulo; inferno, eles podem nem saber que seu módulo existe .

E agora você tem um problema: código quebrado está no porta-malas e ninguém nem sabe. O melhor caso é que um testador interno o encontre antes de enviar, mas a correção do código no final do jogo é cara. E se nenhum testador interno o encontrar ... bem, isso pode custar muito caro.

A solução são testes de unidade. Eles pegam problemas quando você escreve código - o que é bom - mas você poderia ter feito isso manualmente. A verdadeira recompensa é que eles encontrarão problemas nove meses depois, quando você estiver trabalhando em um projeto completamente diferente, mas um estagiário de verão acha que ficará mais organizado se esses parâmetros estiverem em ordem alfabética - e depois o teste de unidade você escreveu o caminho de volta falha e alguém joga as coisas no estagiário até que ele altere a ordem dos parâmetros de volta. Esse é o "porquê" dos testes de unidade. :-)


13

A respeito dos profissionais filosóficos dos testes de unidade e do TDD, aqui estão algumas das principais observações de "lâmpada" que me impressionaram nos meus primeiros passos no caminho para a iluminação do TDD (nenhuma notícia original ou necessariamente) ...

  1. TDD NÃO significa escrever duas vezes a quantidade de código. O código de teste geralmente é bastante rápido e fácil de escrever e é uma parte essencial do seu processo de design e de forma crítica.

  2. O TDD ajuda você a perceber quando parar de codificar! Seus testes dão a você a confiança de que você já fez o suficiente por enquanto e pode parar de mexer e passar para a próxima coisa.

  3. Os testes e o código trabalham juntos para obter um código melhor. Seu código pode estar com defeito / com erros. Seu teste pode ser ruim / com erros. No TDD, você está apostando nas chances de AMBOS serem ruins / com erros razoavelmente baixos. Muitas vezes, é o teste que precisa ser corrigido, mas esse ainda é um bom resultado.

  4. O TDD ajuda na codificação da constipação. Você conhece esse sentimento de que você tem tanto para fazer e mal sabe por onde começar? É sexta-feira à tarde, se você apenas procrastinar por mais algumas horas ... O TDD permite detalhar muito rapidamente o que você pensa que precisa fazer e faz com que sua codificação se mova rapidamente. Além disso, como ratos de laboratório, acho que todos respondemos a essa grande luz verde e trabalhamos mais para vê-la novamente!

  5. Da mesma forma, esses tipos de designers podem VER no que estão trabalhando. Eles podem sair para fazer uma pausa para suco / cigarro / iphone e retornar a um monitor que lhes dá imediatamente uma indicação visual de onde chegaram. TDD nos dá algo semelhante. É mais fácil ver para onde chegamos quando a vida interfere ...

  6. Eu acho que foi Fowler quem disse: "Testes imperfeitos, executados com frequência, são muito melhores do que testes perfeitos que nunca são escritos". Eu interpreto isso como me dando permissão para escrever testes nos quais acho que serão mais úteis, mesmo que o restante da minha cobertura de código seja lamentavelmente incompleta.

  7. O TDD ajuda em todos os tipos de maneiras surpreendentes abaixo da linha. Bons testes de unidade podem ajudar a documentar o que algo deve fazer, podem ajudar a migrar o código de um projeto para outro e dar a você uma sensação injustificada de superioridade sobre seus colegas que não estão testando :)

Esta apresentação é uma excelente introdução a todos os gostoso testes de bondade.



5

Uso testes de unidade para economizar tempo.

Ao criar a lógica de negócios (ou acesso a dados), a funcionalidade de teste geralmente envolve a digitação de itens em várias telas que ainda podem ou não estar concluídas. A automação desses testes economiza tempo.

Para mim, os testes de unidade são um tipo de equipamento de teste modularizado. Geralmente, há pelo menos um teste por função pública. Escrevo testes adicionais para cobrir vários comportamentos.

Todos os casos especiais que você pensou ao desenvolver o código podem ser registrados no código nos testes de unidade. Os testes de unidade também se tornam uma fonte de exemplos de como usar o código.

É muito mais rápido descobrir que meu novo código quebra algo nos meus testes de unidade do que fazer check-in do código e pedir que algum desenvolvedor front-end encontre um problema.

Para o teste de acesso a dados, tento escrever testes que não tenham sido alterados ou que sejam limpos após eles mesmos.

Os testes de unidade não serão capazes de resolver todos os requisitos de teste. Eles poderão economizar tempo de desenvolvimento e testar partes principais do aplicativo.


4

Esta é a minha opinião. Eu diria que o teste de unidade é a prática de escrever testes de software para verificar se o seu software real faz o que deve. Isso começou com o jUnit no mundo Java e se tornou uma prática recomendada em PHP, assim como no SimpleTest e no phpUnit . É uma prática essencial da programação extrema e ajuda a garantir que seu software ainda funcione conforme o esperado após a edição. Se você tiver cobertura de teste suficiente, poderá realizar grandes refatorações, correção de bugs ou adicionar recursos rapidamente, com muito menos medo de apresentar outros problemas.

É mais eficaz quando todos os testes de unidade podem ser executados automaticamente.

O teste de unidade geralmente está associado ao desenvolvimento de OO. A idéia básica é criar um script que configure o ambiente para o seu código e depois o exercite; você escreve asserções, especifica a saída pretendida que deve receber e, em seguida, executa seu script de teste usando uma estrutura como as mencionadas acima.

A estrutura executará todos os testes no seu código e, em seguida, reportará o sucesso ou falha de cada teste. O phpUnit é executado a partir da linha de comando do Linux por padrão, embora haja interfaces HTTP disponíveis para ele. O SimpleTest é baseado na Web por natureza e é muito mais fácil de instalar, IMO. Em combinação com o xDebug, o phpUnit pode fornecer estatísticas automatizadas para cobertura de código, que algumas pessoas consideram muito úteis.

Algumas equipes gravam ganchos no repositório do subversion para que os testes de unidade sejam executados automaticamente sempre que você confirmar as alterações.

É uma boa prática manter seus testes de unidade no mesmo repositório que seu aplicativo.


4

Bibliotecas como NUnit , xUnit ou JUnit são apenas obrigatórias se você deseja desenvolver seus projetos usando a abordagem TDD popularizada por Kent Beck:

Você pode ler Introdução ao Desenvolvimento Orientado a Testes (TDD) ou o livro Test Driven Development: Por exemplo .

Então, se você quiser ter certeza de que seus testes abrangem uma parte "boa" do seu código, você pode usar software como NCover , JCover , PartCover ou qualquer outra coisa. Eles informarão a porcentagem de cobertura do seu código. Dependendo do quanto você é adepto do TDD, você saberá se o praticou bem o suficiente :)


3

Teste de unidade é o teste de uma unidade de código (por exemplo, uma única função) sem a necessidade da infraestrutura em que essa unidade de código depende. ou seja, teste-o isoladamente.

Se, por exemplo, a função que você está testando se conectar a um banco de dados e fizer uma atualização, em um teste de unidade, talvez você não queira fazer essa atualização. Você faria se fosse um teste de integração, mas neste caso não é.

Portanto, um teste de unidade exercitaria a funcionalidade incluída na "função" que você está testando sem efeitos colaterais da atualização do banco de dados.

Digamos que sua função recuperou alguns números de um banco de dados e, em seguida, executou um cálculo de desvio padrão. O que você está tentando testar aqui? Que o desvio padrão é calculado corretamente ou que os dados são retornados do banco de dados?

Em um teste de unidade, você só deseja testar se o desvio padrão é calculado corretamente. Em um teste de integração, você deseja testar o cálculo do desvio padrão e a recuperação do banco de dados.


3

O teste de unidade é sobre escrever código que testa o código do seu aplicativo.

A parte Unit do nome é sobre a intenção de testar pequenas unidades de código (um método por exemplo) por vez.

O xUnit existe para ajudar nesse teste - eles são estruturas que o ajudam. Parte disso são os corredores de teste automatizados que informam qual teste falha e quais passam.

Eles também têm recursos para configurar o código comum necessário em cada teste antes da mão e derrubá-lo quando todos os testes forem concluídos.

Você pode fazer um teste para verificar se uma exceção esperada foi lançada, sem ter que escrever o bloco inteiro try try.


3

Acho que o ponto que você não entende é que estruturas de teste de unidade como o NUnit (e similares) o ajudarão a automatizar testes de pequeno a médio porte. Geralmente, você pode executar os testes em uma GUI (é o caso do NUnit , por exemplo), basta clicar em um botão e, espero - ver a barra de progresso permanecer verde. Se ficar vermelho, a estrutura mostra qual teste falhou e o que exatamente deu errado. Em um teste de unidade normal, você costuma usar asserções, por exemplo Assert.AreEqual(expectedValue, actualValue, "some description")- por isso, se os dois valores forem desiguais, você verá um erro dizendo "alguma descrição: <valor esperado esperado> mas era <valor real>".

Portanto, como conclusão, o teste de unidade tornará o teste mais rápido e muito mais confortável para os desenvolvedores. Você pode executar todos os testes de unidade antes de confirmar o novo código para não interromper o processo de compilação de outros desenvolvedores no mesmo projeto.



3

O teste de unidade é uma prática para garantir que a função ou módulo que você implementará se comportará conforme o esperado (requisitos) e também para garantir que se comporte em cenários como condições de contorno e entrada inválida.

xUnit , NUnit , mbUnit , etc. são ferramentas que ajudam você a escrever os testes.


2

O Desenvolvimento Orientado a Testes adotou o termo Teste de Unidade. Como um temporizador antigo, mencionarei a definição mais genérica dele.

Teste de unidade também significa testar um único componente em um sistema maior. Esse componente único pode ser uma DLL, exe, biblioteca de classes etc. Pode até ser um sistema único em um aplicativo com vários sistemas. Então, finalmente, o Teste de Unidade acaba sendo o teste do que você deseja chamar de uma única parte de um sistema maior.

Você passaria para o teste integrado ou do sistema, testando como todos os componentes funcionam juntos.


2

Antes de mais nada, seja falando sobre teste de unidade ou qualquer outro tipo de teste automatizado (integração, carga, teste de interface do usuário etc.), a principal diferença do que você sugere é que ele é automatizado, repetível e não requer recursos humanos para ser consumido (= ninguém precisa executar os testes, eles geralmente são executados com o pressionar de um botão).


1

Fui a uma apresentação sobre o teste de unidade no FoxForward 2007 e me disseram para nunca fazer o teste de unidade que funcionasse com dados. Afinal, se você testar dados ativos, os resultados serão imprevisíveis e, se você não testar dados ativos, na verdade, não estará testando o código que escreveu. Infelizmente, essa é a maior parte da codificação que faço atualmente. :-)

Eu tirei uma foto no TDD recentemente quando estava escrevendo uma rotina para salvar e restaurar configurações. Primeiro, verifiquei que era possível criar o objeto de armazenamento. Então, que tinha o método que eu precisava chamar. Então, eu poderia chamá-lo. Então, eu poderia passar parâmetros. Então, eu poderia passar parâmetros específicos. E assim por diante, até que eu finalmente verifiquei que ela salvaria a configuração especificada, permita-me alterá-la e restaurá-la para várias sintaxes diferentes.

Não cheguei ao fim, porque precisava da rotina agora, droga, mas foi um bom exercício.


1

O que você faz se receber uma pilha de porcaria e parecer que está preso em um estado perpétuo de limpeza que você sabe que com a adição de qualquer novo recurso ou código pode quebrar o conjunto atual porque o software atual é como uma casa de cartões?

Como podemos fazer o teste de unidade então?

Você começa pequeno. O projeto em que acabei de entrar não tinha testes de unidade até alguns meses atrás. Quando a cobertura era tão baixa, simplesmente pegávamos um arquivo que não tinha cobertura e clicávamos em "adicionar testes".

No momento, estamos com mais de 40% e conseguimos colher a maioria das frutas mais baixas.

(A melhor parte é que, mesmo com este baixo nível de cobertura, já encontramos muitas instâncias do código fazendo a coisa errada e os testes pegaram. Isso é um grande motivador para levar as pessoas a adicionar mais testes.)


1

Isso responde por que você deveria fazer testes de unidade.


Os três vídeos abaixo abordam o teste de unidade em javascript, mas os princípios gerais se aplicam à maioria dos idiomas.

Teste de unidade: minutos agora economizarão horas depois - Eric Mann - https://www.youtube.com/watch?v=_UmmaPe8Bzc

Teste de unidade JS (muito bom) - https://www.youtube.com/watch?v=-IYqgx8JxlU

Escrevendo JavaScript testável - https://www.youtube.com/watch?v=OzjogCFO4Zo


Agora, estou apenas aprendendo sobre o assunto, para que eu não esteja 100% correto e não exista mais do que o que estou descrevendo aqui, mas meu entendimento básico do teste de unidade é que você escreve algum código de teste (que é mantido separado do seu código principal) que chama uma função em seu código principal com entrada (argumentos) que a função exige e o código verifica se recupera um valor de retorno válido. Se ele receber um valor válido, a estrutura de teste de unidade que você está usando para executar os testes exibirá uma luz verde (tudo de bom) se o valor for inválido, você receberá uma luz vermelha e poderá resolver o problema imediatamente antes de libere o novo código para produção, sem testar, talvez você não tenha capturado o erro.

Então, você escreve testes para o seu código atual e cria o código para que ele passe no teste. Meses depois, você ou outra pessoa precisa modificar a função em seu código principal, porque, anteriormente, você já havia escrito o código de teste para essa função, agora executa novamente e o teste pode falhar porque o codificador introduziu um erro lógico na função ou retorna algo completamente diferente do que essa função deve retornar. Novamente, sem o teste, esse erro pode ser difícil de rastrear, pois também pode afetar outros códigos e passará despercebido.


Além disso, o fato de você ter um programa de computador que executa seu código e o testa, em vez de fazê-lo manualmente na página por página do navegador, economiza tempo (teste de unidade para javascript). Digamos que você modifique uma função usada por algum script em uma página da Web e ela funcione muito bem para o novo objetivo pretendido. Mas, digamos também por razões de argumentos que há outra função que você tem em outro lugar no seu código que depende dessa função recém-modificada para que ela funcione corretamente. Agora, essa função dependente pode parar de funcionar devido às alterações feitas na primeira função; no entanto, sem os testes executados automaticamente pelo seu computador, você não notará que há um problema com essa função até que seja executada e executada. vocês'

Para reiterar, ter testes executados durante o desenvolvimento de seu aplicativo detectará esses tipos de problemas durante a codificação. Não tendo os testes instalados, você teria que passar manualmente por todo o aplicativo e, mesmo assim, pode ser difícil identificar o bug, ingenuamente você o envia para produção e depois de um tempo um usuário gentil envia um relatório de bug (que não será tão bom quanto suas mensagens de erro em uma estrutura de teste).


É bastante confuso quando você ouve o assunto pela primeira vez e pensa: não estou testando meu código? E o código que você escreveu está funcionando como deveria: "Por que preciso de outra estrutura?" ... Sim, você já está testando seu código, mas um computador é melhor nisso. Você só precisa escrever testes suficientemente bons para uma função / unidade de código uma vez e o resto é resolvido pelo poderoso cpu, em vez de ter que verificar manualmente se todo o seu código ainda está funcionando quando você faz uma alteração no código. seu código.

Além disso, você não precisa testar seu código de unidade, se não quiser, mas vale a pena à medida que o projeto / base de código começa a crescer à medida que as chances de introduzir bugs aumentam.


0

O teste de unidade e o TDD em geral permitem que você tenha ciclos de feedback mais curtos sobre o software que está escrevendo. Em vez de ter uma grande fase de teste no final da implementação, você testa gradualmente tudo o que escreve. Isso aumenta muito a qualidade do código, como você vê imediatamente, onde pode ter bugs.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.