No trabalho, um dos meus projetos trata principalmente de pegar dados passados de um cliente externo e persistir em um banco de dados. É um aplicativo corporativo Java usando JPA e a maior parte de nossa lógica gira em torno das operações CRUD.
A maioria dos nossos erros envolve JPA de uma maneira ou de outra.
- Exemplo 1: Se você clicar no botão Salvar duas vezes, o JPA poderá tentar inserir a mesma entidade no banco de dados uma segunda vez, causando uma violação da chave primária.
- Exemplo 2: você recupera uma entidade do banco de dados, edita-a e tenta atualizar seus dados. A JPA pode tentar criar uma nova instância em vez de atualizar a antiga.
Muitas vezes, a solução precisa adicionar / remover / alterar uma anotação JPA. Outras vezes, tem a ver com a modificação da lógica do DAO.
Não consigo descobrir como obter confiança em nosso código usando testes de unidade e TDD. Não tenho certeza se é porque os testes de unidade e o TDD são inadequados ou se estou abordando o problema errado.
Os testes de unidade parecem um ajuste inadequado porque só consigo descobrir esses problemas em tempo de execução e preciso implantar em um servidor de aplicativos para reproduzir os problemas. Geralmente, o banco de dados precisa estar envolvido, o que considero estar fora da definição de um teste de unidade: estes são testes de integração.
O TDD parece um ajuste inadequado, porque o loop de feedback de implantação e teste é tão lento que me deixa muito improdutivo. O ciclo de feedback deploy + test leva mais de 3 minutos, e é apenas se eu executar os testes especificamente sobre o código que estou escrevendo. Para executar todos os testes de integração, leva mais de 30 minutos.
Há código fora deste molde e eu sempre teste unitário sempre que posso. Mas a maioria dos nossos bugs e os maiores sumidouros de tempo sempre envolvem o JPA ou o banco de dados.
Há outra pergunta semelhante , mas se eu seguisse o conselho, estaria agrupando a parte mais instável do meu código (o JPA) e testando tudo, menos ele. No contexto da minha pergunta, eu estaria na mesma situação ruim. Qual é o próximo passo após agrupar o JPA? A IMO que pergunta é (talvez) um passo para responder à minha pergunta, mas não uma resposta para ela.
fonte
unit testing != TDD
)Respostas:
Uma opção é usar um banco de dados de teste na memória, como H2 ; tende a ser cerca de 10x mais rápido que um banco de dados padrão em uso de disco e com tempos de inicialização / desmontagem mais baixos.
Se isso ajudará depende em grande parte se os problemas de JPA que você está tendo são gerais o suficiente para que ainda falhem em bancos de dados diferentes. Não faz muito sentido executar testes mais rapidamente se eles perderem a maior parte dos problemas.
Mas se você puder fazer 10 corridas com H2 para cada uma com o sistema completo, isso poderá valer a pena.
fonte
Os bancos de dados podem ser muito fáceis para o teste de unidade - você precisa de procedimentos e transações armazenados.
É o que a Microsoft diz sobre o teste de unidade de banco de dados . Você também pode executar testes de unidade em um banco de dados, gravando seus testes em Java ou C # configurando uma conexão com o banco de dados, iniciando uma transação, gravando no banco de dados todos os dados que deseja usar para o teste, executando os testes e depois revertendo. Nenhum dano ao banco de dados se você estivesse usando um para o qual também implantou e você obtém testes totalmente isolados.
Espero que isso possa lhe dar algumas dicas de como fazê-lo em sua estrutura.
fonte
Outras pessoas responderam com "Mock out your DB!" - mas qual é o objetivo de zombar da camada de banco de dados se você realmente precisa testar como ela interage com seu código?
O que você procura são testes de integração e / ou testes automatizados de interface do usuário. Você mencionou que o problema ocorre quando:
A única maneira de testar isso é escrever um teste de interface do usuário automatizado para clicar no botão duas vezes. Talvez dê uma olhada no Selenium.
Provavelmente, você também precisará de um banco de dados de teste de unidade e, para os seus testes, aponte para isso. Uma dor para manter, mas bem-vindo ao TDD no mundo real.
fonte
No exemplo apresentado na sua pergunta, você não pode testar a unidade / TDD para entrar na situação de clicar duas vezes no botão para causar um erro com muita facilidade. Mas o que você pode fazer no teste de unidade é que, no código que é chamado quando você clica no botão, se você receber uma exceção da camada de persistência, manipula-a adequadamente (zombando da camada de persistência ou usando um banco de dados na memória como foi sugerido em outras respostas) - repetindo novamente ou exibindo um erro ou o que for.
Você está certo de que o TDD pode começar a falhar quando você precisa executar testes que não são adequados para um teste de unidade (isto é, testes de integração / sistema) - isso formou bastante a discussão no recente "Is TDD Morto?" debates entre Kent Beck, Martin Fowler e David Heinemeier Hansson: http://martinfowler.com/articles/is-tdd-dead/
fonte