Pergunta

Isso pareceu despertar um pouco de conversa sobre outra pergunta e eu pensei que digno de giro em sua própria pergunta.

O princípio DRY parece ser a nossa arma de escolha para combater a manutenção problemas, mas que sobre a manutenção de código de teste ? Fazer as mesmas regras de ouro aplicar?

Alguns fortes vozes na comunidade testes de desenvolvedor são da opinião de que a instalação e desmontagem são prejudiciais e devem ser evitados ... para citar alguns:

Na verdade, xUnit.net retirou-os do quadro completamente por essa razão (Embora existam maneiras de contornar esta auto-imposta limitação ) .

Qual tem sido sua experiência? Fazer setup / mágoa desmontagem ou teste de ajuda manutenção?

Atualizar : fazer mais construções de grão fino, como aqueles disponíveis em JUnit4 ou TestNG (@BeforeClass, @BeforeGroups, etc.) fazer a diferença

Foi útil?

Solução

A maioria (se não todos) de válidos usos para os métodos de instalação e desmontagem pode ser escrita como métodos de fábrica que permite a DRY sem entrar em questões que parecem ser atormentado com a configuração / teardown paradigma .

Se você está implementando a desmontagem, Normalmente, isso significa que você não está fazendo um teste de unidade, mas sim um teste de integração. Um monte de pessoas usam isso como uma razão para não ter uma desmontagem, mas IMO deve haver tanto a integração e teste de unidade. Eu pessoalmente separá-los em conjuntos separados, mas acho que uma boa estrutura de teste deve ser capaz de suportar ambos os tipos de testes. Nem todos boa o teste vai ser o teste de unidade.

No entanto, com a configuração parece haver uma série de razões pelas quais você precisa para fazer as coisas antes de um teste é realmente executado. Por exemplo, a construção de estado do objecto a preparação para o teste (por exemplo a criação de um quadro de injecção de dependência). Esta é uma razão válida para a instalação, mas pode ser facilmente feito com uma fábrica.

Além disso, há uma distinção entre classe e nível de método setup / desmontagem. Que precisa ser mantido em mente quando se considera o que você está tentando fazer.

O meu maior problema que eu tive com o uso do programa de configuração / teardown paradigma é que meus testes nem sempre seguem o mesmo padrão. Isso tem me trazido para o uso de padrões de fábrica em vez disso, o que me permite ter DRY, ao mesmo tempo que é legível e não em tudo confuso para outros desenvolvedores. Indo a rota fábrica, eu fui capaz de ter o meu bolo e comê-lo a.

Outras dicas

Eles realmente ajudou com a nossa capacidade de manutenção de teste. Nossos testes de "Unidade" são realmente testes completos end-to-end de integração que escrever para o DB e verificar os resultados. Não é minha culpa, eles eram como que quando eu cheguei aqui, e eu estou trabalhando para mudar as coisas.

De qualquer forma, se um teste falhou, ele passou para a próxima, tentando entrar no mesmo usuário a partir do primeiro teste no DB, violar uma restrição de exclusividade, e as falhas apenas em cascata de lá. Movendo-se a criação de usuário / exclusão para o [dispositivo elétrico] [SetUp | TearDown]. Métodos nos permitiu ver a um teste que falhou sem tudo derem errado acontecendo, e fez a minha vida muito mais fácil e menos stabby

Eu acho que o princípio de DRY se aplica tanto para testes como faz para código, no entanto a sua aplicação é diferente. No código de ir para muito comprimentos maiores para literalmente não fazer a mesma coisa em duas partes diferentes do código. Em testes a necessidade de fazer isso (fazer um monte da mesma configuração) é certamente um cheiro, mas a solução não é necessariamente fator a duplicação em um método de configuração. Pode ser tornar o estado mais fácil de configurar na classe em si ou para isolar o código em teste por isso é menos dependente de esta quantidade de estado para ser significativo.

Dado o objetivo geral de apenas testando uma coisa por teste, ele realmente não é possível evitar fazendo um monte da mesma coisa uma e outra vez, em certos casos (como a criação de um objeto de um determinado tipo). Se você achar que você tem um monte de que, pode valer a pena repensar a abordagem de teste, tais como a introdução de testes parametrizadas e similares.

Eu acho que a instalação e desmontagem deve ser principalmente para estabelecer o ambiente (como injeções para tornar o ambiente um teste em vez de uma produção), e não deve conter medidas que fazem parte integrante do teste.

Eu concordo com tudo o que Joseph tem a dizer, especialmente a parte sobre tearDown sendo um sinal de escrever testes de integração (e 99% do tempo é o que eu usei-o para), mas, além de que eu diria que o uso de configuração é um bom indicador de quando os testes devem ser logicamente agrupados e quando eles devem ser dividida em várias classes de teste.

Não tenho nenhum problema com grandes métodos de configuração ao aplicar testes para código legado, mas a configuração deve ser comum a todos os testes na suíte . Quando você encontrar-se com o método de configuração realmente fazendo vários bits de configuração, então é hora de dividir os testes em vários casos.

Seguindo os exemplos em "Test Driven" , o método de configuração vem sobre de eliminação de duplicações nos casos de teste.

Eu uso a configuração é bastante frequente em Java e Python, freqüentemente para configurar colaboradores (real ou teste, dependendo). Se o objeto sob teste não tem construtores ou apenas os colaboradores como construtores vou criar o objeto. Para uma classe de valor simples que normalmente não se preocupam com eles.

Eu uso desmontagem muito raramente em Java. Em Python foi usado mais frequentemente, porque eu era mais propensos a mudar de estado global (em particular, macaco patching módulos para que os usuários desses módulos em teste). Nesse caso, eu quero uma subdivisão que irá garantido para ser chamado se um teste falhou.

testes de integração e testes funcionais (que muitas vezes usam o framework xUnit) são mais propensos a configuração necessidade e desmontagem.

O ponto a lembrar é pensar sobre luminárias , não só DRY.

Eu não tenho um problema com a instalação e desmontagem métodos de teste em si.

A questão para mim é que se você tiver uma configuração de teste e desmontagem método, isso implica que o mesmo objeto de teste está sendo reutilizado para cada teste. Este é um vetor potencial de erro, como se você esquecer de limpar algum elemento de estado entre os testes, os resultados dos testes podem tornar-se dependentes de ordem. O que realmente queremos é testes que não compartilham qualquer estado.

xUnit.Net se livrar de instalação / desmontagem, porque cria um novo objeto para cada teste que é executado. Em essência, o construtor torna-se o método de configuração, e o finalizador torna-se o método de desmontagem. Não há (objeto de nível) afirmam realizada entre os testes, eliminando esse potencial vector de erro.

A maioria dos testes que eu escrevo tem uma certa quantidade de configuração, mesmo que seja apenas criar as simulações que eu preciso e fiação do objeto que está sendo testado até as simulações. O que eles não fazer é compartilhar qualquer estado entre os testes. Desmontagem é apenas ter certeza que eu não compartilhar esse estado.

Eu não tive tempo para ler tanto do que você postou, mas, em especial, gostaram este comentário:

cada teste é forçado a fazer a inicialização para o que ele precisa ser executado.

Configuração e desgaste são os métodos de conveniência - eles não devem tentar fazer muito mais do que inicializar uma classe usando seu construtor padrão, etc. código comum que três testes precisa em uma classe de cinco teste não deve aparecer lá - cada um os três testes devem chamar esse código diretamente. Isso também mantém testes de pisar no pé do outro e quebrar um monte de testes só porque você mudou uma rotina initalization comum. O principal problema é que este será chamado antes de todos os testes - não apenas testes específicos. A maioria dos testes deve ser simples, e os mais complexos terão código de inicialização, mas é mais fácil de ver a simplicidade dos testes simples quando você não tem que rastrear através de uma inicialização complexa em configurar e complexo destruição em lágrima para baixo, enquanto pensar sobre o que o teste é realmente deveria realizar.

Pessoalmente, eu encontrei a instalação e desmontagem nem sempre são maus, e que esta linha de raciocínio é um pouco dogmático. Mas eu não tenho nenhum problema chamando-os de cheiro código para testes de unidade. Eu sinto a sua utilização deve ser justificada, por alguns motivos:

    código
  1. Test é processual, por sua natureza. Em geral, instalação / desmontagem do tendem a reduzir teste de leitura / foco.
  2. métodos de configuração tendem a iniciar mais do que o que é necessário para um único teste. Quando abusado eles podem se tornar inviável. Mães objeto, teste Construtores de dados, talvez frameworks como FactoryGirl parecem melhor em inicializar dados de teste.
  3. Eles encorajam "inchaço contexto" - quanto maior o contexto de teste se torna, menos sustentável ele será
  4. .

Na medida em que a minha configuração / teardown não faz isso, eu acho que o seu uso se justifica. Haverá sempre alguma duplicação de testes. Neal Ford afirma isso como "Os testes podem ser molhada mas não encharcada ..." Além disso, eu acho que seu uso é mais justificada quando não estamos a falar de testes de unidade especificamente, mas os testes de integração de forma mais ampla.

Trabalho em meu próprio, este nunca foi realmente um problema. Mas eu achei muito difícil de manter conjuntos de testes em um ambiente de equipe, e isso tende a ser porque nós não entender o código do outro imediatamente, ou não querem ter que passo por ele para compreendê-lo. De uma perspectiva de teste, eu encontrei permitindo alguma duplicação em testes alivia esse fardo.

Eu adoraria ouvir como outros se sentem sobre isso, porém.

Se você precisar de instalação e desmontagem para tornar a sua testes unitários de trabalho, talvez o que você realmente necessidade é objetos mock?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top