Os testes para desenvolvimento orientado a testes (TDD) são sempre testes unitários?

40

Até agora, eu entendo o desenvolvimento orientado a testes que só é permitido escrever códigos produtivos quando você tem um teste de unidade (vermelho) com falha. Com base nisso, tenho a pergunta se a abordagem orientada a testes também pode ser aplicada a outras formas de testes.

    
por user1364368 08.06.2017 / 11:02
fonte

8 respostas

28

Tudo o que o TDD requer de você é que você escreva um teste com falha e modifique seu código para fazê-lo passar.

Normalmente, os "testes de unidade" são pequenos e rápidos e testam alguma parte do seu código isoladamente. Por serem rápidos, o loop red / green / refactor também é rápido. No entanto, eles sofrem apenas testando peças isoladamente. Então você precisa de outros testes também (integração, aceitação, etc). Ainda é uma boa prática seguir os mesmos princípios: escreva um teste com falha e modifique o código para fazê-lo funcionar. Apenas esteja ciente de que eles são normalmente mais lentos, portanto, podem afetar o tempo de ciclo vermelho / verde / refatorador.

    
por 08.06.2017 / 11:53
fonte
60

O ciclo de refatoração verde vermelho é construído sobre um princípio muito sólido:

Confie apenas nos testes que você viu passar e falhar.

Sim, também funciona com testes de integração automatizados. Também testes manuais. Heck, funciona em testadores de bateria de carro. É assim que você testa o teste.

Alguns pensam que os testes de unidade cobrem a menor coisa que pode ser testada. Alguns pensam em qualquer coisa que seja rápida de testar. O TDD é mais do que o ciclo de refatoração verde vermelho, mas essa parte tem um conjunto muito específico de testes: não são os testes que você executará de maneira ideal uma vez antes de enviar uma coleção de alterações. São os testes que você executará toda vez que fizer alguma alteração. Para mim, esses são seus testes de unidade.

    
por 08.06.2017 / 11:27
fonte
12

However, I am wondering if the test-driven approach can also be applied to other forms of tests.

Sim, e uma abordagem bem conhecida que faz isso é Desenvolvimento orientado pelo comportamento . Os testes que são gerados a partir da especificação formal no BDD podem ser chamados de "testes unitários", mas eles normalmente não são tão baixos quanto no TDD real, eles provavelmente se encaixam melhor no termo "testes de aceitação".

    
por 08.06.2017 / 12:51
fonte
8

I understand test-driven development so far that you are only allowed to write productive code when you have a failing (red) unit test.

Não. Você só tem permissão para escrever o código mais simples possível para alterar a mensagem do teste. Não diz nada sobre o tipo de teste.

Na verdade, você provavelmente começará escrevendo um teste de aceitação (vermelho) com falha para um critério de aceitação, mais precisamente, você escreverá o teste de aceitação mais simples que poderia falhar; depois você executa o teste, assiste a falha e verifica se ele falha pelo motivo certo. Em seguida, você escreve um teste funcional com falha para uma fatia de funcionalidade desse critério de aceitação; novamente, você grava o teste funcional mais simples que pode falhar, executa, assiste a falha e verifica se ele falha pelo motivo certo. Então você escreve um teste de unidade com falha, o teste de unidade mais simples que poderia falhar, execute-o assisti-lo falhar, verificar se ele falha pelo motivo certo.

Agora , você escreve o código de produção mais simples que poderia alterar a mensagem de erro. Execute o teste novamente, verifique se a mensagem de erro foi alterada, se foi alterada na direção correta e se o código alterou a mensagem pelo motivo correto. (Idealmente, a mensagem de erro deve ter passado, e o teste deve passar, mas na maioria das vezes, é melhor dar pequenos passos mudando a mensagem em vez de tentar fazer o teste passar de uma só vez - essa é a razão por que os desenvolvedores de frameworks de teste gastam tanto esforço em suas mensagens de erro!)

Depois de passar o teste de unidade, você refatora seu código de produção sob a proteção de seus testes. (Observe que, neste momento, o teste de aceitação e o teste funcional ainda estão falhando, mas tudo bem, já que você está apenas refatorando unidades individuais cobertas por testes de unidade.)

Agora você cria o próximo teste de unidade e repete o acima, até que o teste funcional também passe. Sob a proteção do teste funcional, você pode fazer refatorações em várias unidades.

Este ciclo intermediário agora se repete até que o teste de aceitação passe, e nesse ponto você pode fazer refatorações em todo o sistema.

Agora, você escolhe o próximo critério de aceitação e o ciclo externo começa novamente.

Kent Beck, o "descobridor" de TDD (ele não gosta do termo "inventor", ele diz que as pessoas têm feito isso o tempo todo, ele apenas deu um nome e escreveu um livro sobre isso) usa uma analogia da fotografia e chama isso de "zoom in e out".

Nota: você nem sempre precisa de três níveis de testes. Talvez, às vezes você precise de mais. Mais frequentemente, você precisa de menos. Se suas partes de funcionalidade são pequenas e seus testes funcionais são rápidos, então você pode passar sem (ou com menos testes de unidade). Muitas vezes, você só precisa de testes de aceitação e testes de unidade. Ou os seus critérios de aceitação são tão refinados que seus testes de aceitação são testes funcionais.

Kent Beck diz que se ele tiver um teste funcional rápido, pequeno e focado, ele primeiro escreverá os testes de unidade, deixará os testes de unidade conduzirem o código e, em seguida, excluirá (alguns) os testes de unidade que cobrem o código que também é coberto pelo teste funcional rápido. Lembre-se: o código de teste também é um código que precisa ser mantido e refatorado, quanto menos houver, melhor!

However, I am wondering if the test-driven approach can also be applied to other forms of tests.

Você não aplica o TDD aos testes. Você o aplica a todo o processo de desenvolvimento. É isso que a parte "impulsionada" do Test- Driven -Desenvolvimento significa: todo seu desenvolvimento é conduzido por testes. Os testes não apenas direcionam o código que você escreve, eles também direcionam o que codifica para escrever, qual código escrever em seguida. Eles dirigem seu design. Eles dizem quando você está feito. Eles dizem a você o que trabalhar em seguida. Eles informam sobre falhas de design em seu código (quando os testes são difíceis de escrever).

Keith Braithwaite criou um exercício que ele chama de TDD como se você Significou . Consiste em um conjunto de regras (baseado em As Três Regras de TDD do Tio Bob Martin , mas muito mais rigoroso) que você deve adotar estritamente. seguir e que são projetados para orientá-lo para aplicar TDD com mais rigor. Funciona melhor com programação em pares (para que seu par possa ter certeza de que você não está quebrando as regras) e um instrutor.

As regras são:

  1. Write exactly one new test, the smallest test you can that seems to point in the direction of a solution
  2. See it fail; compilation failures count as failures
  3. Make the test from (1) pass by writing the least implementation code you can in the test method.
  4. Refactor to remove duplication, and otherwise as required to improve the design. Be strict about using these moves:
    1. you want a new method—wait until refactoring time, then … create new (non-test) methods by doing one of these, and in no other way:
      • preferred: do Extract Method on implementation code created as per (3) to create a new method in the test class, or
      • if you must: move implementation code as per (3) into an existing implementation method
    2. you want a new class—wait until refactoring time, then … create non-test classes to provide a destination for a Move Method and for no other reason
    3. populate implementation classes with methods by doing Move Method, and no other way

Estas regras são destinadas ao exercício de TDD. Eles não são feitos para realmente fazer TDD em produção (embora nada impeça você de testá-lo). Eles podem se sentir frustrados porque às vezes parece que você faz milhares de pequenas etapas sem fazer nenhum progresso real.

    
por 08.06.2017 / 12:54
fonte
2

O TDD não está limitado ao que a comunidade tradicional de Testes de Software chama de "teste de unidade". Esse equívoco muito comum é o resultado da desafortunada sobrecarga de Kent Beck do termo "unidade" ao descrever sua prática de TDD. O que ele quis dizer com "teste de unidade" foi um teste que funciona de forma isolada. Não depende de outros testes. Cada teste deve configurar o estado de que precisa e fazer qualquer limpeza quando isso for feito. É nesse sentido que um teste unitário no sentido TDD é uma unidade. É auto-contido. Ele pode ser executado sozinho ou pode ser executado junto com qualquer outro teste unitário em qualquer ordem.

Referência : "Test Driven Development By Example", por Kent Beck

Kent Beck descreve o que ele quer dizer com “teste de unidade” no Capítulo 32 - Dominando o TDD

    
por 08.06.2017 / 20:08
fonte
1

Eu não li livros sobre isso, nem acompanho completamente as práticas "padrão" do TDD o tempo todo, mas na minha cabeça o ponto principal da filosofia do TDD, com o qual eu concordo completamente, é que você tem que definir sucesso primeiro. Isso é importante em todos os níveis de design, desde "Qual é o objetivo deste projeto?" para "Quais devem ser as entradas e saídas deste pequeno método?"

Existem várias maneiras de fazer essa definição de sucesso. Um útil, particularmente para os métodos de baixo nível com potencialmente muitos casos de borda, é escrever testes no código. Para alguns níveis de abstração, pode ser útil apenas escrever uma nota rápida sobre o objetivo do módulo ou qualquer outra coisa, ou mesmo apenas verificar mentalmente (ou pedir a um colega de trabalho) para ter certeza de que tudo faz sentido e está em um lugar lógico. Às vezes, é útil descrever um teste de integração no código (e, claro, isso ajuda a automatizá-lo), e às vezes é útil definir um plano de teste rápido razoável que você possa usar para garantir que todos os sistemas funcionem juntos. estão esperando.

Mas, independentemente das técnicas ou ferramentas específicas que você está usando, a principal coisa a ser tirada da filosofia do TDD é que definir o sucesso acontece primeiro. Caso contrário, você está jogando o dardo e depois pintando o alvo em volta onde quer que tenha acontecido.

    
por 08.06.2017 / 16:54
fonte
1

Na palestra Desenvolvimento Orientado a Testes: Não é isso que queremos dizer Steve Freeman mostra o seguinte slide do quadro geral do TDD (ver imagem abaixo resposta). Isso inclui uma etapa "Escrever um teste de ponta a ponta com falha" que é seguida por "Gravar um teste de unidade com falha". (Clique para ampliar, no canto superior direito)

Portanto, não no TDD, os testes nem sempre são testes unitários.

E sim, você pode (e talvez deva) começar com um teste de ponta a ponta de nível mais alto que falha antes de você escrever seu primeiro teste de unidade. Este teste descreve o comportamento que você deseja alcançar. Isso gera cobertura em mais níveis da pirâmide de testes . Adrian Sutton explica a experiência da LMAX que mostra que testes de ponta a ponta podem desempenhar um papel grande e valioso .

    
por 09.06.2017 / 11:10
fonte
-1

Não, não pode ser aplicado a outros tipos de testes, por uma simples razão prática: outros tipos de testes estão demorando muito para serem executados.

O ciclo TDD típico é: teste de falha de gravação, implementação, refatoração de código. Os passos intermediários são a criação e a execução de testes, e esses precisam ser muito rápidos. Se não forem, as pessoas começarão a pular etapas e você não fará mais TDD.

    
por 09.06.2017 / 12:06
fonte

Tags