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 "?
fonte
Respostas:
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á.
fonte
OMI:
fonte
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.
fonte
sql.syntax_ora
em 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.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.
fonte
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.
fonte
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').
fonte