pessoal como vocês realizam os testes unitários de operações CRUD ? Alguém tem alguma referência que fale sobre isso ? Ou alguém pode relatar como é feito ?
Por exemplo, como vocês manipulam a base de dados ? Diretamente na mão ou via teste também, exemplo: na operação de consulta, devo no mesmo teste incluir os registros e depois buscá-lo ? Como vocês criam as classes de Teste ? Uma para cada entidade ? Por exemplo a entidade Cliente, vocês colocam todos os testes referentes a clientes nessa classe ?
Quanto faço testes unitários de métodos que envolvem persistencia eu uso mocks pros objetos relativos a persistencia como DAOs, Hibernate Session, etc.
Um teste que acessa o banco de dados não é unitario.
Para testar uma inserção insiro o objeto, pego o id faço uma busca e verifico se inseriu.
Para fazer uma consulta simples insiro uma ou mais objetos dependentes, sei os valores inseridos, preencho o filtro e verifico se foram retornados x objetos em uma consulta. A parte de carga pode ser feita pelo DBUnit mas não vejo muito ganho, nesse caso prefiro java a xml.
Os testes não são realmente unitário mas para testar isso tem que ser em métodos diferentes mesmo…
Manipulo a base toda no testes inserindo e busco tudo nos testes.
É tudo transacional e posso rodar os testes sempre…
Você pode escolher usar o DBUnit também. Você dá uma carga no banco usando XML e pode contar com esses dados durante os testes unitários.
É uma questão de escolha.
Usar reflexão para inserir valores no objeto que está sendo testado facilita muito o teste.
ObjetoTestado inserido = dao.insert(filllTO(new ObjetoTestado()));//usa introspecção mas não seta o id.
assertNotNull("O id do objeto inserido não foi setado",inserido.getId());
ObjetoTestado procurado = dao.getById(inserido.getId());
assertNotNull("Não foi encontrado objeto",procurado);
assertEquals("O filtro não está correto",inserido.getId(), procurado.getId());
Os relacionamentos de um objeto com outras tabelas devem ser setados “na mão” mas só de preencher todas as propriedades obrigatórias e testar inserção em todas as colunas já ajuda.
Para testar classes com regras de negócio uso o EasyMock e não acesso o banco.
Quando usar um banco eh absolutamente e estritamente necessario (ou seja, vc ta testando a camada mais funda do sistema, nao uma regra de negocios qualquer), usar um banco em memoria (HSQL eh o que a gente usa direto aqui) vai bem.
Mas so deve ser usado numa parte da aplicacao que normalmente acaba sendo testada por testes funcionais, anyway… faz sentido ter certeza que a configuracao do Hibernate ta certa num teste unitario?
Hum, testes que usam banco não são unitários? Os testes que eu faço nos EJBs com o DBUnit para ver se os finders estão fazendo as buscas corretamente ou se os métodos de negócio estão certo não são unitários?
Não, por que o resultado de teste unitário deve depender exclusivamente da unidade que está sendo testada e ele deve ser robusto e consistente: sempre fornecer o mesmo resultado para a mesma implementação de uma classe. Ficaria muito difícil confiar em testes que dizem uma coisa hoje e amanhã dizem outra diferente, e usar banco de dados em testes unitários leva a isso.
Sim, é justamente esse ponto, o teste unitário não deve ‘atrapalhar’ outros testes, é isso que quero entender como fazer na melhor maneira possível, porque antes de executar os testes unitários , a base de dados deve estar num formato X, e depois de executar os testes o banco deve retornar ao estado X, ou não ?
Como vocês fazem? Deixam uma instância do banco pra cada desenvolvedor ?
O HSQL não pode esconder alguns erros ? Pois se como eu uso outro banco … ficaria complicado testar no HSQL.
Vou dar uma olhada no dbunit.
Outra coisa também quando vocês na mesma suite de testes, testam inclusões, vocÊs no mesmo teste, obtém para verificar se foi incluída corretamente, e depois do método de teste vcs excluem os registros incluídos ? É que aí estaria testando os métodos de inclusão, consulta, e exclusão…
Nope. Podem ser testes funcionais ou de integracao, mas por definicao nao podem ser unitarios. Testes unitarios testam uma unidade de cada vez - se vc ta usando um banco de dados, quer dizer que tem mais de uma classe envolvida (nem que seja uma Connection jdbc).
[quote=cv]
Nope. Unitarios so testam uma classe.[/quote]
Você está dizendo que se estou testando um método de uma classe e este por sua vez invoca outras classes, o teste não é mais unitário?
Pelo que eu sei, testes de unidade servem pra “exercitar” uma pequena porção de código (normalmente um método isolado), independente do que esta porção faz.
Se eu entendi errado (sua afirmação ou o conceito) por favor me corrija
Se a classe invoca outras classes, ta na hora de usar mocks ou stubs
A ideia de testes unitarios eh que vc quer testar o menor pedaco possivel de codigo de cada vez. Assim, quando a coisa toda desanda, eh mais facil saber onde ta algum problema.
A princípio então um teste unitário parece idiota, porque pelo que você disse vai acabar testando coisas ridículas, que não sei se realmente vale a pena testar.
Pensa assim, num mundo perfeito, condições normais de temperatura e pressão, superfícies sem atrito, etc, você só precisaria criar testes unitários. Afinal, se houver um bug no software, ele está em algum lugar que é coberto por testes específicos. Se o bug for na interação entre elementos, isso significa que um ou os dois elementos está com defeitos (que deveriam ser descobertos pelos respectivos testes unitários).
Na vida real eles não bastam, porque os testes são por definção incompletos e testar explícitamente as interações aumenta a probabilidade de encontrar os bugs. Mas note que, depois de encontrados, eles estão em algum lugar e um teste unitário pode (e deve) ser escrito para testar que o comportamento foi corrigido.