Avaliando se deve escrever testes de unidade ou testes de integração primeiro em projetos de céu azul / protótipo


11

Algo que notei recentemente é quando estou executando os seguintes tipos de projetos:

  • Ao iniciar um projeto
  • Trabalhando em um MVP / protótipo
  • Adicionando recursos que não estão totalmente definidos
  • Trabalhando em um projeto de menor escala

Para referência, estou trabalhando em um projeto Python agora que atualmente possui ~ 1k linhas de código, incluindo alguns comentários e todos os espaços em branco.

Acho imensamente mais fácil primeiro escrever testes de integração, trabalhar no código e , depois que a API estiver um pouco reforçada, realmente trabalharemos na adição de testes de unidade. Os tipos de testes que eu posso executar na minha mainfunção, por assim dizer, e são mais "de ponta a ponta" do que qualquer outra coisa.

Isso ocorre porque os testes de unidade são realmente irritantes quando uma API está mudando rapidamente, o que geralmente acontece quando se trabalha em um projeto que corresponde a algum ou à maioria dos critérios acima.

Essa abordagem é uma boa abordagem e quais critérios devem ser considerados ao tomar a decisão de começar com testes de unidade ou integração primeiro para esses tipos de projetos? Estou perdendo o valor do teste de unidade desses tipos de projetos antes que as APIs sejam mais solidificadas?


6
Faça o que for melhor para você. Não dê ouvidos às pessoas que dizem que você deve trabalhar de uma certa maneira para ser eficiente: você sabe quando é eficiente e quando não é. Se você escreve os testes de integração primeiro ou os testes de unidade primeiro, isso realmente não importa. Para alguns projetos, um caminho pode ser mais fácil e, para outros, o outro. O que você está descrevendo pode ser a diferença entre o design de cima para baixo e o de baixo para cima. Ambos são úteis, mas de cima para baixo geralmente produz melhores designs.
21817 Frank Hileman #

@FrankHileman, de fato, essa é a minha abordagem. Mas, como estou curioso, quero ter certeza de que estou fazendo a abordagem correta , caso esteja perdendo alguma coisa.
Enderland

Concentre-se nas especificações primeiro: as partes que não são de código. Quais são os invariantes do sistema? Ao fazer isso, você pode descobrir o primeiro nível baixo ou o primeiro nível alto. Depende de onde os algoritmos mais críticos ou de risco estão localizados. Tente tirá-los do caminho primeiro. Isso é gerenciamento básico de riscos.
21717 Frank Hileman

1
No caso de trabalhar no protótipo, não há problema em escrever testes. O objetivo do protótipo é verificar a ideia de trabalho. A implementação do protótipo ajudará a reconhecer o design esperado do aplicativo.
Fabio

É chamado de desenvolvimento externo. Você pode querer verificar o seguinte livro, que faz exatamente isso: amazon.com/dp/0321503627
Eternal21

Respostas:


7

Estou perdendo o valor do teste de unidade desses tipos de projetos antes que as APIs sejam mais solidificadas?

Não. Você está bem.

Os dois grandes objetivos do TDD são:

  • Definindo interfaces pelo uso real, e não pela implementação interna 1
  • Maximizando a cobertura do teste

A cobertura do teste pode ser bastante bem maximizada de qualquer maneira. Ou seja, independentemente de você testar primeiro unidades pequenas e isoladas ou unidades grandes e "integradas", você tem a opção de escrever seus testes antes de suas implementações.

O que você ganha ao escrever testes de nível superior ("integração") primeiro, como você está fazendo, é a garantia de que suas interfaces e interações de nível superior também são definidas principalmente de acordo com o uso delas, e não pelas implementações internas.

O mesmo efeito pode ser alcançado em grande parte com algumas boas "arquiteturas" e diagramas. Porém, esses testes de alto nível geralmente podem revelar coisas que você perdeu nos diagramas - ou que acabou de errar no trabalho de "arquitetura".


Se você não está realmente fazendo TDD (ou algo parecido), a ordem em que você escreve os testes não importa muito. As interfaces já existem no momento do teste, portanto é muito menos provável que seus testes alterem qualquer coisa - eles servirão apenas para proteger contra alterações específicas.

Mas, se você estiver preocupado em construir a implementação de cima para baixo versus de cima para baixo, o primeiro ponto ainda se aplica em grande parte. O código de alto nível ajuda a definir interfaces de baixo nível. Considerando que, se as interfaces de baixo nível forem escritas primeiro (ou já existirem), o código de alto nível estará à sua mercê ...


1. Este também se aplica mesmo se você não estiver fazendo TDD completo. Mesmo se você estiver apenas escrevendo 1 ou 2 testes antes da sua implementação, esses 1 ou 2 testes podem ajudá-lo a definir ou refinar suas interfaces antes que seja tarde demais!


1

Eu trabalhei do jeito que você está trabalhando. E eu não vou lhe dizer que você não pode. Vou avisá-lo sobre algo que você pode encontrar.

Quando todo teste de unidade é simplesmente uma atualização, é difícil aprender a torná-lo flexível. Eles tendem a ser nada mais que testes de regressão. Como você nunca os usou para ajudá-lo a refatorar, é muito fácil escrever os tipos de testes que tornam a refatoração mais difícil. Isso tende a sair do controle até você perder toda a fé no TDD.

No entanto, você já está trabalhando em algo. Eu não vou dizer para você parar. Eu direi que pode valer a pena começar outra coisa que você tem tempo para explorar e seguir o ciclo do refator verde vermelho desde o início. Certifique-se de usar os testes para ajudá-lo a refatorar. Até você dominar essa maneira de trabalhar, use-a com moderação em algo que importa. Essa é uma maneira muito diferente de codificar e de se acostumar. Fazer isso no meio do caminho não fará bem a ninguém.

Dito isto

Acho imensamente mais fácil primeiro escrever testes de integração, trabalhar no código e, depois que a API estiver um pouco reforçada, realmente trabalharemos na adição de testes de unidade. Os tipos de testes que eu posso executar na minha função principal, por assim dizer, e são mais "de ponta a ponta" do que qualquer outra coisa.

Entenda que um teste de unidade NÃO é simplesmente um teste que atua em uma classe. Desde que a API em que você esteja trabalhando possa ser testada sem executar um dos procedimentos a seguir, você estará executando o teste de unidade muito bem:

  • Ele fala com o banco de dados
  • Ele se comunica através da rede
  • Toca no sistema de arquivos
  • Ele não pode ser executado ao mesmo tempo que qualquer outro teste de unidade
  • Você precisa fazer coisas especiais no seu ambiente (como editar arquivos de configuração) para executá-lo.

Michael Feathers: um conjunto de regras de teste de unidade

Portanto, se seu teste de ponta a ponta envolver mais de um objeto, tudo bem. Este é um teste de unidade, não um objeto.

Assim como os métodos privados não precisam mais ser testados, eles são testados através do teste dos métodos públicos que os utilizam, os objetos não precisam ser desenvolvidos inicialmente sob seu próprio equipamento de teste. Somente quando os objetos estão sendo considerados para uso independente da história de ponta a ponta é que eles realmente precisam ser tratados como se tivessem sua própria interface e comportamento para confirmar. Se você está sendo cuidadoso, é quando você torna esses objetos públicos. Dessa forma, você não faz promessas que não testou.

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.