
Aqui na empresa, temos clientes que apenas mandam executar um projeto segundo a arquitetura definida por eles. Algumas vezes é frustante trabalhar neste tipo de projeto, afinal, nem sempre conseguimos seguir nossas convicções e utilizar plenamente nossos conhecimentos e experiência na definição da melhor solução para o problema. Em um desses projetos, fui convocado para auxiliar a equipe que estava consumindo muito tempo na implementação dos testes.
O Cenário:O sistema utiliza
EJB 2 e
Hibernate 2. O cliente exige implementação de testes dos métodos da
fachada utilizando
JUnit e
DbUnit.
Problemas:A montagem dos cenários é complexa. O DbUnit entende apenas o modelo relacional, isto significa que o engenheiro tem que fazer um "desmapeamento hibernate" na cabeça dele para montar as tabelas e colunas com os valores necessários. Veja um exemplo:
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<employee employee_uid="1"
start_date="2001-01-01"
first_name="Drew"
ssn="333-29-9999"
last_name="Smith" />
<employee employee_uid="2"
start_date="2002-04-04"
first_name="Nick"
ssn="222-90-1111"
last_name="Marquiss" />
<employee employee_uid="3"
start_date="2003-06-03"
first_name="Jose"
ssn="111-67-2222"
last_name="Whitson" />
</dataset>
Claro que esse é um modelo relacional simples, agora imagine modelos de classes complexos, com heranças, relacionamentos, etc. Neste caso, dá bastante trabalho.
Além da dificuldade em produzir a massa de dados, existe um problema muito grave. Dentro das classes de teste é necessário fazer validações contra os valores do arquivo xml (por exemplo em métodos de consulta). Neste caso podemos fazer as validações com valores hard coded, como neste exemplo:
assertEquals(employee.getFirstName(), "Jose");
Que é uma péssima idéia, pois viola o
princípio DRY (Don't Repeat Yourself). Outra saída é obter os valores do xml através da API do DbUnit, que vai dar uma trabalheira danada, ainda mais se você quiser montar o objeto para fazer comparações deste tipo:
assertEquals(employeeActual, employeeExpected);
Já imaginou? Vai ter que construir outro hibernate só para pegar cada valor das tabelas e colunas do arquivo XML e remontar os objetos novamente.
Como Resolver?O grande problema dessa abordagem é o fato do DbUnit entender apenas de tabelas e colunas. E se existisse um HibernateUnit? No hipotético HibernateUnit eu poderia especificar meus dados na forma de objetos. Além disso, poderia utilizar um formato mais legível e que pudesse ser transformado diretamente para objetos dentro do seu código. Esse formato pode ser o
YAML. Veja como ficaria:
departaments:
- &engineering
id : 1
name : Engineering
employees:
- id : 1
startDate : 2001-01-01
firstName : Drew
lastName : Smith
ssn : 333-29-9999
departament : *engineering
- id : 2
startDate : 2002-04-04
firstName : Nick
lastName : Marquiss
ssn : 222-90-1111
departament : *engineering
- id : 3
startDate : 2003-06-03
firstName : Jose
lastName : Whitson
ssn : 111-67-2222
departament : *engineering
Inclui um relacionamento para employee só para ficar um pouco mais rico. A vantagem dessa abordagem é que além de ficar mais legível, existem frameworks que serializam e deserializam esse formato para objetos. Com esse recurso, seria possível obter os objetos diretamente do arquivo e em seguida fazer comparações com objetos obtidos no banco. Legal, hein?
Acho que uma solução deste tipo poderia trazer muitos benefícios para o nosso problema. Estou fazendo uma pesquisa e se não existir nada semelhante, devo implementar essa solução como um projeto open source.
Pena que nosso cliente EXIGE que usemos o DbUnit.