Os testes de unidade HSQLDB são um anti-padrão?


9

O HSQLDB é ótimo. Ele (também) possui um modo incorporado (não é necessário um servidor dedicado), que permite a rápida criação de protótipos de coisas como Prova de Conceitos, e também pode ser ótimo em aplicativos prontos para produção, como um armazenamento rápido e simples de vários dados.

No entanto, pelo menos 90% dos projetos em que trabalhei nos últimos anos, se eles lidarem de alguma forma com um banco de dados SQL, inevitavelmente terão testes de unidade que usam um HSQLDB incorporado.

Certamente, esses projetos (que usam a estrutura padrão do Maven na maioria das vezes) têm uma tonelada de "testes de unidade" (ou, pelo menos, algum tipo de teste, mas que estão localizados na área "teste de unidade" do projeto (como "src / test / java")) que usa uma ou mais instâncias incorporadas do HSQLDB para executar algumas operações CRUD e verificar os resultados.

Minha pergunta é: isso é um anti-padrão? O fato de o HSQLDB ser fácil de integrar e o servidor incorporado ser muito leve faz com que seja negligenciado como "mock-up" de um banco de dados real, quando não deveria ser o caso? Esses testes não deveriam ser tratados mais como testes de integração (já que cada um deles é composto por "algo" E essa integração de "algo" com um servidor de banco de dados)? Ou estou faltando alguma coisa na definição de "teste de unidade" e podemos dizer que o uso do HSQLDB como esse simplesmente adere à "simulação das dependências e testa apenas a parte" unitária "da definição de" teste unitário "?


3
Isso não é apenas zombaria aplicada à camada Banco de Dados? Eu não diria que era um anti-padrão, desde que seja uma maneira simples e apropriada de obter os módulos que dependem dele testados em unidade.
Kilian Foth

2
@KilianFoth sim, mas ainda está zombando quando o "mock" (o banco de dados) realmente desempenha um papel ativo no processo de teste? Por exemplo, quando você tem uma classe com alguma dependência (obrigatória para a instanciação da classe), se você deseja testar a unidade nessa classe, você zomba dessa dependência, mas simplesmente testa os métodos da classe, não importo mais sobre a dependência escarnecido, ele não tem um papel tão grande em toda a unidade de testes da coisa classe, como HSQLDB tem neste tipo de testes de unidade ...
Shivan Dragão


1
@gnat bem, eu pessoalmente vejo essa outra pergunta como "como testar coisas na camada de acesso a dados acima - devemos zombar da camada de acesso a dados ou o quê", enquanto a minha é "como testar a unidade? na camada de acesso a dados em si, é HSQLD e como uma forma válida para as coisas simulados "...?
Shivan Dragão

Respostas:


8

Considero usar algo como HSQLDB (ou DBUnit) ao testar meus DAOs como uma etapa necessária para garantir a qualidade do código que escrevo ao tocar em uma camada de dados. Como já apontado, não é uma solução à prova de balas, mas em combinação com seus dialetos, pode cobrir uma parte razoável de seus casos.

Meu único argumento seria: tenhamos cuidado quando falamos de testes de unidade . Quando testo uma classe que interage com um componente externo que está fora do meu controle (ou seja, pode produzir comportamento não determinístico), considero-a automaticamente como um teste de integração.

Supondo que você tenha fatorado a lógica na qual interage diretamente com seu armazenamento de dados (via drivers JDBC, ORM etc.) em uma classe concreta oculta por uma interface, um teste de unidade adequado para o seu DAO seria desenvolvido passando para ele uma implementação zombada concreta da interface que retorna um conjunto de valores conhecidos contra os quais você a testará.


5

OMI:

  • Se um teste requer DB, não é o teste de unidade. É um teste de integração ou aceitação.
  • Para evitar a necessidade de usar DB em um teste, devo seguir o princípio da inversão de controle usando injeção de dependência (ou localizador de serviço).
  • Se eu precisar testar algo com o DB, devo criar uma VM com banco de dados real (com dados reais ou falsos, dependendo da tarefa). Vagrant e Docker são ótimas ferramentas para o trabalho.
  • Zombar do banco de dados é uma prática ruim. É o mesmo que fazer errado (zombando do banco de dados) e depois refazê-lo corretamente (fazendo com que funcione com o banco de dados real).
  • Não há problema em projetos de prova de conceito, mas ainda é seguido por refazer (se o conceito for comprovado).
  • É perfeitamente bom usar o HSQLDB (ou qualquer outra coisa) por si só, se for uma ferramenta adequada para o trabalho.

4

Use o mesmo banco de dados para testes (de unidade) que você está usando em seu ambiente de produção.

O motivo é simples: os bancos de dados se comportam de maneira diferente. Cada banco de dados tem suas próprias funções proprietárias. Mesmo se você usar uma camada ORM para acesso ao banco de dados, seu banco de dados poderá se comportar de maneira diferente, também em termos de desempenho.

Obviamente, a vantagem de um banco de dados incorporado para testes de unidade é que você não precisa configurar nada. Mas instalar um banco de dados em cada máquina do desenvolvedor e configurá-lo para ser usado para testes de unidade não é tão difícil.

Eu tive a mesma situação em um projeto há algum tempo. Usamos o JDBC para executar instruções SQL no banco de dados. Quando decidimos escrever testes para nosso aplicativo, usamos um banco de dados incorporado. Isso leva a situações em que alguns erros não podem ser reproduzidos com testes de unidade e algumas partes do aplicativo não podem ser testadas porque o banco de dados incorporado não suporta as funções do nosso banco de dados de produção. Portanto, todo desenvolvedor instalou o mesmo banco de dados que também usamos no ambiente de produção no PC para executar os testes, que funcionaram muito melhor.


São muitas as instâncias do Oracle que você está sugerindo instalar em alguns ambientes - nem um pouco baratas. Não esqueça também o servidor de compilação.

@ MichaelT Eu sei, mas qual é a alternativa?
Uooo 12/02

2
Pode-se usar HSQLDB trabalhar com um dialeto Oracle (ver sql.syntax_oraem hsqldb.org/doc/guide/dbproperties-chapt.html ) - não é perfeito, mas é bom o suficiente para a maioria das coisas. Como você observa, a solução não é tudo, mas resolve os problemas de várias licenças necessárias e permite compilações independentes que não dependem de outro serviço em execução. Outra abordagem seria dbunit . De fato, existem trocas com cada abordagem.

@MichaelT O Oracle é gratuito para desenvolvimento / teste. Portanto, não há custo para instalar outra instância do Oracle para teste. Obviamente, existe o custo de instalar mais hardware para executar todas essas instâncias.
jwenting

2
Eu não considero isso um teste de unidade se ele estava acessando um não-incorporado DB
herman

4

Eu encontrei e corrigi alguns problemas muito ruins e acelerou bastante o meu desenvolvimento testando no banco de dados HSQL. Freqüentemente, o nível mais baixo de classes de adaptadores (ou seja, seus DAOs) pode não ser testado nos testes de unidade, pois pode ser difícil separá-los de uma viagem de ida e volta real para um banco de dados ativo. Eu zombei dos artefatos Connection e JDBC no passado, mas na verdade era muito mais difícil do que testar em um banco de dados na memória.

Em um projeto, desenvolvi e testei contra o HSQL, executei localmente no MySql e implantei na produção no SQL-Server. Surpreendentemente, funcionou muito bem. O maior problema de integração que encontrei foi devido ao meu próprio mal-entendido sobre as especificações (segundos x milissegundos, risos).

Embora a estrutura de persistência possa mascarar o banco de dados subjacente (como o Hibernate), a própria estrutura de persistência pode adicionar semânticas complicadas o suficiente para que exercê-lo isoladamente possa eliminar muitas peculiaridades antes de você realizar o teste de integração completo.

Considere o caso em que você está usando o Hibernate ou JPA para criar um conjunto de resultados complicado com muitas junções. Se for desagradável e precisar de muitas tentativas, você poderá desenvolver e testar isso em um banco de dados ativo. Mas você também pode desenvolvê-lo e testá-lo em um banco de dados na memória com menos sobrecarga. Você também não precisa se preocupar com scripts de configuração / desmontagem para os equipamentos de seu banco de dados ou coordenar testes e compilações com outras pessoas. E se você testar no banco de dados da memória, desfrutará dos benefícios de ter esses testes para regressão, assim como outros testes de unidade.

Eu ouvi o termo "Teste de componentes" para testes que são mais do que testes de unidade, mas ainda são feitos isoladamente.

Testes de unidade, testes de componentes (se esse é realmente o nome deles) e testes de integração fornecem valor. As equipes podem dispensar uma ou outra (sim, muitas equipes não fazem testes de unidade e dependem apenas dos testes de integração), mas se você fizer isso, estará perdendo os benefícios que as outras camadas de teste trazem.

No caso de testes isolados devido à integração na memória, o benefício é a rápida validação do código e a rápida regressão - os benefícios do teste isolado e a necessidade de instalações, licenças ou hardware adicionais. Ele permite que você valide mais níveis de código isoladamente do que se você apenas testasse seus DAOs até que o banco de dados fosse provisionado.

Portanto, há um valor prático. Não é necessário, mas fiquei mais feliz do que menos quando o fiz.


3

Eu uso abordagens como essa no passado, não tenho certeza se isso é um "antipadrão" (algumas pessoas tentam elevar seus sentimentos ou experiências pessoais a regras universais, não), mas prefiro outra abordagem:

  • Para teste de unidade, o teste de unidade real não usa coisas externas, como um banco de dados na memória (não é realmente leve se você comparar com um hashMap ou um stub usando alguma biblioteca de stub). Se você usa DI e padrões simples como Repository ou DAO para acesso a dados, isso é muito fácil de obter. Meu objetivo é ter muitos testes de unidade que executam muito rápido, e com o rápido estou pensando no teste de 3k em menos de um minuto.

  • Para teste de integração, eu prefiro usar o software de armazenamento de dados real neste teste, o objetivo deste teste é provar a integração entre o meu software e o armazenamento de dados real, usar um armazenamento de dados diferente, aqui quebra a intenção disso teste. Tento escrever o menor teste de integração possível para demonstrar essa integração e, geralmente, esse teste é executado fora da compilação normal (por exemplo, apenas em compilações noturnas)

Às vezes, uso o HSQLDB para criar demonstrações simples ou provas de conceitos, é uma ótima ferramenta, mas não vejo mais qual é o lugar dessa ferramenta no meu fluxo de trabalho de desenvolvimento normal.


0

Para produtos de acesso a dados de teste de unidade como o MyBatis, testes usando o HSQLDB incorporado são perfeitamente adequados na minha opinião (e eu sei que pelo menos no MyBatis eles estão usando o HSQLDB exatamente para isso).

Para a maioria dos outros projetos, eu consideraria esse exagero. Eu faria alguns testes simples de integração (esses são testes que potencialmente têm efeitos colaterais em outros testes) que acessam o banco de dados real, garantindo que cada consulta / instrução seja usada pelo menos uma vez. Deve haver muito menos testes de integração do que testes de unidade no projeto.

Para os testes de unidade, eu zombaria do DAO ou de qualquer outro acesso ao DB (o 'adaptador').

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.