Eu sigo TDD religiosamente. Meus projetos normalmente têm 85% ou mais de cobertura de teste, com casos de teste significativos.
Faço muito trabalho com o HBase , e a principal interface do cliente, HTable, é uma verdadeira chatice. Demoro 3 ou 4 vezes mais para escrever meus testes de unidade do que para escrever testes que usam um endpoint ativo.
Sei que, filosoficamente, os testes que usam zombarias devem ter prioridade sobre os testes que usam um endpoint ativo. Mas zombar do HTable é uma dor séria, e não tenho muita certeza de que ele ofereça uma grande vantagem sobre o teste em uma instância do HBase ao vivo.
Todos na minha equipe executam uma instância do HBase de nó único em suas estações de trabalho e temos instâncias do HBase de nó único em execução nas nossas caixas Jenkins, portanto, não é um problema de disponibilidade. Obviamente, os testes de endpoint ao vivo demoram mais tempo do que os testes que usam simulações, mas não nos importamos com isso.
No momento, escrevo testes de endpoint em tempo real e testes baseados em simulação para todas as minhas classes. Adoraria abandonar a zombaria, mas não quero que a qualidade diminua como resultado.
O que vocês acham?
fonte
Respostas:
Minha primeira recomendação seria não zombar de tipos que você não possui . Você mencionou que o HTable é uma verdadeira chatice de zombar - talvez você deva encapsulá-lo em um Adaptador que exponha os 20% dos recursos de HTable necessários e zombe do invólucro quando necessário.
Dito isto, vamos supor que estamos falando de tipos que todos vocês possuem. Se seus testes baseados em simulação são focados em cenários de caminhos felizes, onde tudo corra bem, você não os perderá, porque seus testes de integração provavelmente já estão testando exatamente os mesmos caminhos.
No entanto, testes isolados se tornam interessantes quando você começa a pensar em como o sistema em teste deve reagir a tudo o que pode acontecer conforme definido no contrato do colaborador, independentemente do objeto concreto real com o qual está falando. Isso faz parte do que alguns chamam de correção básica . Pode haver muitos desses pequenos casos e muitas mais combinações deles. É aqui que os testes de integração começam a ficar ruins, enquanto os testes isolados permanecem rápidos e gerenciáveis.
Para ser mais concreto, o que acontece se um dos métodos do seu adaptador HTable retornar uma lista vazia? E se retornar nulo? E se lançar uma exceção de conexão? Deve ser definido no contrato do Adaptador se alguma dessas coisas pode acontecer e qualquer um de seus consumidores deve estar preparado para lidar com essas situações , daí a necessidade de testes para elas.
Resumindo: você não verá nenhum declínio na qualidade removendo seus testes baseados em simulação se eles testarem exatamente as mesmas coisas que seus testes de integração . No entanto, tentar imaginar testes isolados adicionais (e testes de contrato ) pode ajudá-lo a pensar em suas interfaces / contratos extensivamente e aumentar a qualidade, resolvendo defeitos que seriam difíceis de pensar e / ou lentos para testar com testes de integração.
fonte
Eu acho que, no mínimo, esse é um ponto de controvérsia atual entre os defensores do TDD.
Minha visão pessoal vai além disso, para dizer que um teste baseado em simulação é principalmente uma maneira de representar uma forma de contrato de interface ; idealmente, ele quebra (ou seja, falha) se e somente se você alterar a interface . E, como tal, em linguagens razoavelmente fortemente tipadas como Java, e ao usar uma interface definida explicitamente, é quase inteiramente supérfluo: o compilador já terá lhe informado se você mudou a interface.
A principal exceção é quando você está usando uma interface muito genérica, talvez baseada em anotações ou reflexões, que o compilador não é capaz de policiar de maneira útil automaticamente. Mesmo assim, você deve verificar se há uma maneira de fazer a validação programaticamente (eq uma biblioteca de verificação de sintaxe SQL), e não manualmente, usando zombarias.
É nesse último caso que você está realizando ao testar com um banco de dados local 'ativo'; a implementação htable entra em ação e aplica uma validação muito mais abrangente do contrato interfacve do que você jamais imaginaria escrever manualmente.
Infelizmente, um uso muito mais comum de testes baseados em simulação é o teste que:
É claro que esses testes devem ser excluídos à vista.
fonte
Quanto tempo leva para executar um teste baseado em terminal do que um teste baseado em simulação? Se for significativamente mais longo, sim, vale a pena o investimento do seu tempo para escrever testes para tornar os testes de unidade mais rápidos - porque você precisará executá-los muitas e muitas vezes. Se não for significativamente mais longo, mesmo que os testes baseados em pontos de extremidade não sejam testes de unidade "puros", desde que eles estejam fazendo um bom trabalho de teste da unidade, não há razão para ser religioso sobre isso.
fonte
Concordo totalmente com a resposta de guillaume31, nunca zombe de tipos que você não possui!
Normalmente, uma dor no teste (zombando de uma interface complexa) reflete um problema no seu design. Talvez você precise de alguma abstração entre seu modelo e seu código de acesso a dados; exemplo de formulário, usando uma arquitetura hexagonal e um padrão de repositório, é a maneira mais comum de resolver esse tipo de problema.
Se você deseja fazer um teste de integração para verificar as coisas, faça um teste de integração, se você quiser fazer um teste de unidade, porque você está testando sua lógica, faça um teste de unidade e isole a persistência. Mas, ao fazer um teste de integração, porque você não sabe como isolar sua lógica de um sistema externo (ou porque isolar uma dor) é um grande cheiro, você está escolhendo a integração em vez da unidade para limitar o design, não para uma necessidade real para testar a integração.
Dê uma olhada nesta palestra de Ian Cooper: http://vimeo.com/68375232 , ele fala sobre arquitetura hexagonal e testes, ele fala sobre quando e o que zombar, um discurso realmente inspirado que resolve muitas perguntas como a sua sobre o TDD real .
fonte
TL; DR - Na minha opinião, depende de quanto esforço você gasta nos testes e se seria melhor gastar mais no sistema atual.
Versão longa:
Algumas boas respostas aqui, mas minha opinião é diferente: o teste é uma atividade econômica que precisa se compensar e se o tempo que você gasta não é devolvido no desenvolvimento e na confiabilidade do sistema (ou qualquer outra coisa que você deseja obter) de testes), então você pode estar fazendo um mau investimento; você está no negócio de construir sistemas, não escrevendo testes. Portanto, reduzir o esforço para escrever e manter testes é crucial.
Por exemplo, alguns valores principais que ganho com testes são:
Os testes em relação a um endpoint ativo ainda devem fornecê-los.
Algumas desvantagens do teste em um terminal ativo:
Se eu estivesse nessa situação, e as desvantagens não parecessem um problema, ao zombar consideravelmente do ponto de extremidade que retardava consideravelmente a escrita dos meus testes, eu testaria contra um ponto de extremidade ativo em um piscar de olhos, desde que eu tivesse certeza de que verifique novamente depois de um tempo para ver se os inconvenientes não se tornam um problema na prática.
fonte
De uma perspectiva de teste, existem alguns requisitos que são uma necessidade absoluta:
Esse é um grande desafio ao se conectar a qualquer fonte que mantenha o estado fora dos seus testes. Não é um TDD "puro", mas a equipe do Ruby on Rails resolveu esse problema de uma maneira que pode ser adaptada para seus propósitos. A estrutura de teste do rails funcionou desta maneira:
Todo esse trabalho foi incorporado ao equipamento de teste e funciona razoavelmente bem. Há muito mais, mas o básico é suficiente para esta conversa.
Nas diferentes equipes com as quais trabalhei ao longo do tempo, faríamos escolhas que promovessem o teste do código, mesmo que esse não fosse o caminho mais correto. Idealmente, agruparíamos todas as chamadas para um armazenamento de dados com o código que controlamos. Em teoria, se algum desses projetos antigos obtivesse novo financiamento, poderíamos voltar e transferi-los de vinculados ao banco de dados para o Hadoop, concentrando nossa atenção em apenas algumas classes.
Os aspectos importantes não são para mexer com os dados de produção e verifique se você está realmente testando o que pensa estar testando. É realmente importante poder redefinir o serviço externo para uma linha de base conhecida sob demanda - mesmo a partir do seu código.
fonte