anti-padrão : deve haver pelo menos dois elementos-chave presentes para distinguir formalmente um anti-padrão real de um simples mau hábito, má prática ou má idéia:
- Algum padrão repetido de ação, processo ou estrutura que inicialmente parece ser benéfico, mas que em última análise produz mais más conseqüências do que resultados benéficos, e
- Uma solução refatorada que está claramente documentada, comprovada na prática real e repetível.
Vote no anti-padrão TDD que você já viu "em estado selvagem" uma vez demais.
A postagem do blog de James Carr e a discussão relacionada no yahoogroup testdrivendevelopment
Se você encontrou um 'sem nome', poste-o também. Uma postagem por anti-padrão, por favor, para fazer valer os votos de alguma coisa.
Meu interesse é encontrar o subconjunto top-n para que eu possa discuti-los em uma lanchonete no futuro próximo.
unit-testing
tdd
anti-patterns
Gishu
fonte
fonte
Respostas:
Cidadãos de segunda classe - o código de teste não é tão refatorado quanto o código de produção, contendo muito código duplicado, dificultando a manutenção dos testes.
fonte
The Free Ride / Piggyback - James Carr, Tim Ottinger
Em vez de escrever um novo método de caso de teste para testar outro / recurso / funcionalidade distinta , uma nova asserção (e suas ações correspondentes, por exemplo, executar etapas do AAA) é executada em um caso de teste existente .
fonte
true
após cada chamada possível do mutador. Portanto, você deve verificar se todas as invariantes estãotrue
após cada combinação de dados do mutador e de entrada que você está testando. Mas você deseja reduzir a duplicação e garantir a verificação de todos os invariantes, incluindo aqueles que atualmente não causam falhas no teste. Então você coloca todos eles em umacheckInvariants()
função de verificação e a usa em todos os testes. O código muda e outra invariante é adicionada. Você coloca isso na função também, é claro. Mas é um freerider.Caminho feliz
O teste permanece em caminhos felizes (ou seja, resultados esperados) sem testar limites e exceções.
Antipatterns JUnit
fonte
O herói local
Um caso de teste que depende de algo específico para o ambiente de desenvolvimento em que foi gravado para ser executado. O resultado é que o teste passa nas caixas de desenvolvimento, mas falha quando alguém tenta executá-lo em outro lugar.
A dependência oculta
Intimamente relacionado ao herói local, um teste de unidade que exige que alguns dados existentes tenham sido preenchidos em algum lugar antes da execução do teste. Se esses dados não foram preenchidos, o teste falhará e deixará pouca indicação para o desenvolvedor o que ele queria, ou por quê ... forçando-os a vasculhar acres de código para descobrir de onde os dados que estavam usando deveriam vir.
Tristemente visto isso muitas vezes com .dlls antigas que dependem de arquivos .ini nebulosos e variados, que estão constantemente fora de sincronia em qualquer sistema de produção, e muito menos em sua máquina, sem uma consulta extensa com os três desenvolvedores responsáveis por essas dlls. Suspiro.
fonte
Gangue das correntes
Alguns testes que devem ser executados em uma determinada ordem, ou seja, um teste altera o estado global do sistema (variáveis globais, dados no banco de dados) e o (s) próximo (s) teste (s) dependem disso.
Você costuma ver isso nos testes do banco de dados. Em vez de fazer uma reversão
teardown()
, os testes confirmam suas alterações no banco de dados. Outra causa comum é que as alterações no estado global não são agrupadas em blocos try / finalmente, que são limpos se o teste falhar.fonte
A
zombaria Às vezes, zombar pode ser bom e prático. Mas, às vezes, os desenvolvedores podem se perder e em seu esforço para zombar do que não está sendo testado. Nesse caso, um teste de unidade contém tantas zombarias, stubs e / ou falsificações que o sistema sob teste nem sequer está sendo testado, mas os dados retornados das zombarias são o que está sendo testado.
Fonte: publicação de James Carr.
fonte
O Apanhador Silencioso - Kelly?
Um teste que passa se uma exceção é lançada. Mesmo que a exceção que realmente ocorre seja diferente da que o desenvolvedor pretendia.
Veja também: Apanhador Secreto
fonte
O Inspetor
Um teste de unidade que viola o encapsulamento em um esforço para obter 100% de cobertura de código, mas sabe tanto sobre o que está acontecendo no objeto que qualquer tentativa de refatorar interromperá o teste existente e exigirá que qualquer alteração seja refletida na unidade teste.
'como testar minhas variáveis de membro sem torná-las públicas ... apenas para teste de unidade?'
fonte
Configuração excessiva - James Carr
Um teste que requer uma configuração enorme para iniciar o teste. Às vezes, várias centenas de linhas de código são usadas para preparar o ambiente para um teste, com vários objetos envolvidos, o que pode dificultar realmente a verificação do que é testado devido ao "ruído" de toda a instalação em andamento. (Src: publicação de James Carr )
fonte
Sonda Anal
Um teste que precisa usar maneiras insanas, ilegais ou prejudiciais para executar sua tarefa, como: Ler campos privados usando setAccessible (true) do Java ou estender uma classe para acessar campos / métodos protegidos ou ter que colocar o teste em um determinado pacote para acessar empacotar campos / métodos globais.
Se você vir esse padrão, as classes em teste usarão muitos dados ocultos.
A diferença entre isso e o Inspetor é que a classe em teste tenta ocultar até o que você precisa testar. Portanto, seu objetivo não é atingir 100% de cobertura de teste, mas ser capaz de testar qualquer coisa. Pense em uma classe que possui apenas campos particulares, um
run()
método sem argumentos e sem getters. Não há como testar isso sem violar as regras.Comentário de Michael Borgwardt: Este não é realmente um antipadrão de teste, é pragmatismo lidar com deficiências no código que está sendo testado. É claro que é melhor corrigir essas deficiências, mas isso pode não ser possível no caso de bibliotecas de terceiros.
Aaron Digulla: Eu meio que concordo. Talvez essa entrada seja realmente mais adequada para um wiki "JUnit HOWTO" e não para um antipadrão. Comentários?
fonte
O teste sem nome - Nick Pellow
O teste adicionado para reproduzir um erro específico no rastreador de erros e cujo autor acha que não garante um nome próprio. Em vez de aprimorar um teste que falta, é criado um novo teste chamado testForBUG123.
Dois anos depois, quando esse teste falhar, talvez seja necessário primeiro tentar encontrar o BUG-123 no rastreador de bugs para descobrir a intenção do teste.
fonte
O puxão lento
Um teste de unidade que é incrivelmente lento. Quando os desenvolvedores começam, eles têm tempo para ir ao banheiro, fumar um cigarro ou, pior ainda, iniciar o teste antes de voltarem para casa no final do dia. (Src: publicação de James Carr )
aka os testes que não serão executados com a frequência que deveriam
fonte
A borboleta
Você precisa testar algo que contém dados que mudam o tempo todo, como uma estrutura que contém a data atual, e não há como fixar o resultado em um valor fixo. A parte feia é que você não se importa com esse valor. Isso apenas torna seu teste mais complicado sem agregar nenhum valor.
O bastão de sua asa pode causar um furacão do outro lado do mundo. - Edward Lorenz, O Efeito Borboleta
fonte
System.DateTime.Now
, além de ter testes de unidade mais simples ou mais determinísticos?toString()
um objeto que não sobrescreva o método. Isso fornecerá o ID do objeto que depende do endereço da memória. OutoString()
contém a chave primária do objeto e isso muda toda vez que você executa o teste. Existem três maneiras de corrigir isso: 1. Altere o código que você está testando, 2. usando o regexp para remover as partes variáveis dos resultados do teste ou 3. use ferramentas poderosas para substituir os serviços do sistema e fazê-los retornar resultados previsíveis.O teste de cintilação (fonte: Romilly Cocking)
Um teste que apenas falha ocasionalmente, não em horários específicos, e geralmente é devido às condições da corrida dentro do teste. Geralmente ocorre ao testar algo assíncrono, como JMS.
Possivelmente um super set para o antipadrão ' Wait and See ' e o antipadrão ' The Sleeper '.
A construção falhou, tudo bem, basta executar a construção novamente. - Desenvolvedor Anônimo
fonte
Espere e veja
Um teste que executa algum código de configuração e precisa "aguardar" uma quantidade específica de tempo antes de poder "ver" se o código em teste funcionou como esperado. Um testMethod que usa Thread.sleep () ou equivalente é certamente um teste "Aguarde e veja".
Normalmente, você pode ver isso se o teste estiver testando código que gera um evento externo ao sistema, como um email, uma solicitação http ou grava um arquivo no disco.
Esse teste também pode ser um Herói Local, pois falhará quando executado em uma caixa mais lenta ou em um servidor de IC sobrecarregado.
O anti-padrão Wait and See não deve ser confundido com The Sleeper .
fonte
Dispositivo
elétrico compartilhado de forma inadequada - Tim Ottinger Vários casos de teste no dispositivo de teste nem usam nem precisam de configuração / desmontagem. Em parte devido à inércia do desenvolvedor para criar um novo equipamento de teste ... é mais fácil adicionar mais um caso de teste à pilha
fonte
O gigante
Um teste de unidade que, embora esteja testando validamente o objeto em teste, pode abranger milhares de linhas e conter muitos casos de teste. Isso pode ser um indicador de que o sistema em teste é um objeto de Deus (post de James Carr).
Um sinal claro para este é um teste que abrange mais de algumas linhas de código. Freqüentemente, o teste é tão complicado que começa a conter erros de comportamento próprio ou escamoso.
fonte
Acredito nisso quando vejo algumas GUIs intermitentes
Uma obsessão / fixação doentia em testar o aplicativo por meio da GUI 'exatamente como um usuário real'
"Você deve entender que ver é acreditar, mas também saber que acreditar é ver." - Denis Waitley
fonte
O dorminhoco, também conhecido como Monte Vesúvio - Nick Pellow
Um teste destinado a FAIL em alguma hora e data específica no futuro. Isso geralmente é causado pela verificação incorreta dos limites ao testar o código que usa um objeto Data ou Calendário. Às vezes, o teste pode falhar se for executado em um horário muito específico do dia, como meia-noite.
'O dorminhoco' não deve ser confundido com o antipadrão ' Esperar e ver '.
Esse código será substituído muito antes do ano 2000 - Muitos desenvolvedores em 1960
fonte
A árvore morta
Um teste no qual um stub foi criado, mas o teste não foi realmente escrito.
Na verdade, eu vi isso em nosso código de produção:
Eu nem sei o que pensar sobre isso.
fonte
hoje ficou pouco com isso:
Piso úmido :
o teste cria dados que são mantidos em algum lugar, mas o teste não é limpo quando concluído. Isso faz com que os testes (o mesmo teste ou possivelmente outros testes) falhem nas execuções de teste subsequentes .
No nosso caso, o teste deixou um arquivo no diretório "temp", com permissões do usuário que executou o teste pela primeira vez. Quando um usuário diferente tentou testar na mesma máquina: boom. Nos comentários no site de James Carr, Joakim Ohlrogge se referiu a isso como o "Sloppy Worker", e foi parte da inspiração para "Generous Leftovers". Gosto mais do meu nome (menos ofensivo, mais familiar).
fonte
The Cuckoo - Frank Carver
Um teste de unidade que fica em um caso de teste com vários outros e desfruta do mesmo processo de instalação (potencialmente demorado) que os outros testes no caso de teste, mas descarta alguns ou todos os artefatos da instalação e cria o seu próprio.
Sintoma avançado de: dispositivo elétrico compartilhado inadequadamente
fonte
The Secret Catcher - Frank Carver
Um teste que, à primeira vista, parece não estar sendo testado, devido à ausência de afirmações. Mas "O diabo está nos detalhes" .. o teste realmente depende de uma exceção a ser lançada e espera que a estrutura de teste capture a exceção e a relate ao usuário como uma falha.
fonte
Assert.DoesNotThrow(SomeDelegateType act)
asserção de estilo que pode ser usada especificamente em casos como este. Acho isso menos nojento do que ter um caso de teste que é bem-sucedido quando um construtor retorna não nulo, mas falha quando o construtor lança. Um construtor nunca retornará nulo. (Nota: só se aplica às línguas em que um construtor é garantida para retornar não-null)O vândalo ambiental
Um teste de 'unidade' que, para vários 'requisitos', começa a se espalhar em seu ambiente, usando e configurando variáveis / portas de ambiente. A execução de dois desses testes simultaneamente causará exceções 'porta indisponível' etc.
Esses testes serão intermitentes e deixarão os desenvolvedores dizendo coisas como 'apenas execute novamente'.
Uma solução que eu vi é selecionar aleatoriamente um número de porta a ser usado. Isso reduz a possibilidade de um conflito, mas claramente não resolve o problema. Portanto, se você puder, sempre simule o código para que ele não aloque o recurso não compartilhável.
fonte
O Teste de Turing
Um caso de teste gerado automaticamente por alguma ferramenta cara que possui muitas, muitas declarações coletadas da classe em teste usando uma análise de fluxo de dados muito inteligente pela metade. Lulls desenvolvedores em um falso senso de confiança de que seu código é bem testado, absolvendo-os da responsabilidade de projetar e manter testes de alta qualidade. Se a máquina pode escrever os testes para você, por que não pode puxar o dedo e escrever o aplicativo em si!
Olá estúpido. - O computador mais inteligente do mundo para o novo aprendiz (de uma história em quadrinhos antiga da Amiga).
fonte
O teste de poste de quarenta pés
Com medo de se aproximarem demais da classe que estão tentando testar, esses testes agem à distância, separados por inúmeras camadas de abstração e milhares de linhas de código da lógica que estão verificando. Como tal, são extremamente frágeis e suscetíveis a todos os tipos de efeitos colaterais que ocorrem na jornada épica de e para a classe de interesse.
fonte
Sósia
Para testar algo, você precisa copiar partes do código em teste para uma nova classe com o mesmo nome e pacote e usar a magia do caminho de classe ou um carregador de classes personalizado para garantir que seja visível primeiro (para que sua cópia seja escolhida acima).
Esse padrão indica uma quantidade não saudável de dependências ocultas que você não pode controlar em um teste.
Eu olhei para o rosto dele ... meu rosto! Era como um espelho, mas fez meu sangue congelar.
fonte
The Mother Hen - Frank Carver
Uma configuração comum que faz muito mais do que os casos de teste reais precisam. Por exemplo, a criação de todos os tipos de estruturas de dados complexas preenchidas com valores aparentemente importantes e únicos quando os testes apenas afirmam a presença ou ausência de algo.
Sintoma avançado de: dispositivo elétrico compartilhado inadequadamente
Não sei o que faz ... estou adicionando mesmo assim, só por precaução.- Desenvolvedor Anônimo
fonte
O Teste Tudo
Não acredito que isso não tenha sido mencionado até agora, mas os testes não devem quebrar o Princípio da Responsabilidade Única .
Eu já me deparei com isso tantas vezes, os testes que quebram essa regra são, por definição, um pesadelo para manter.
fonte
Lançador de linha
À primeira vista, os testes abrangem tudo e as ferramentas de cobertura de código confirmam 100%, mas, na realidade, os testes apenas atingem o código sem nenhuma análise de saída.
código de cobertura vs alcançável
fonte