Isolamento e ordem de execução em testes funcionais
16/11/2012 17:27
1
Estou utilizando o Geb (com o plugin de integração com Grails) para executar testes funcionais em um projeto.

Notei que o os dados persistidos em um teste passam a ser acessíveis para outro teste, diferente do que ocorre com testes de integração. Pensando bem, isso é de se esperar, já que os testes são executados contra uma instancia da aplicação deployada como se fosse em produção.

Mas aí tem um problema por que o JUnit oficialmente não garante a ordem de execução dos testes, então ao escrever um teste eu não posso fazer qualquer assunção a respeito do estado do banco de dados no inicio de um teste especifico (O banco de dados pode estar limpo, ou cheio de dados gerados por N outros testes)

Como vocês lidam com isso?
Tags: testes funcionais


0
Oi Magno, excelente problema, e inclusive postei no Twitter pra popularizar este tópico.

A razão pela qual o JUnit não garante a sequência de execução dos testes (temos algum controle quando criamos suites, noe ntanto) é porque os testes devem ser escritos de tal forma que um seja isolado do outro sempre. No entanto, quando a gente lida com testes funcionais, a coisa pode ficar mais complicada mesmo.

O que eu costumo fazer pra resolver o problema é preparar o banco de dados antes do teste, seja no evento before ou então escrevendo um método só para gerar os dados que preciso que estejam presentes no banco de dados. É um processo bastante trabalhoso, mas há ferramentas que podem te auxiliar nesta tarefa, como por exemplo o DBUnit.

(mas na prática sempre vai ser meio chato mesmo)


1
E para não deixar a sujeira usar o after :-)
16/11/2012 18:57


0
Kico, no caso você gera um conjunto de dados apenas uma vez, no inicio da rotina de testes, ou a cada teste individual?

No meu caso, uso o próprio recurso de Bootstrap do Grails para gerar alguns dados, mas o problema é que no inicio de cada teste eu não tenho como saber qual será o estado do banco de dados.

Por exemplo, imaginem um software para video locadoras. Antes da execução dos testes eu cadastro alguns clientes e alguns títulos para locação.

Então tenho o teste da rotina de locação, onde eu gero uma locação do filme X para o cliente Y

Depois tenho um teste para a rotina de devolução, quando entro neste teste eu não tenho como saber se o filme X está ou não disponível, pois o teste de locação pode ou não ter sido executado.


0
Oi Magno, varia muito de acordo com a situação.
Há casos em que um setup inicial resolve 90% dos casos, mas sempre há um ou outro no qual eu preciso executar a preparação do teste antes que ele seja executado.


0
Acho que neste caso, sendo um teste de integração para a suposta rotina de devolução, você mesmo teria que garantir dados de uma locação completa, e para poder fazer o teste, não dá pra contar com estes dados de um outro Local(bootstrap) pois se estiver usando banco pode ser que os dados tenham sido alterados já, então para ter um teste com dados mais "confiáveis" teria que ser assim.

Minha opinião, que acha ?
16/11/2012 19:41


0
Pedro Henrique, o que você sugere é que a cada teste eu gere todos os dados necessarios para aquele teste?


0
Nos de integração eu faço isso, quando eu quero realmente garantir que os testes tenham aquele estado esperado, ou é isso ou ter os dados em algum "lugar", e como você mesmo mencionou, não dá pra garantir a ordem de execução então como fazer para ter os dados no estado esperado pelo teste ?

No caso de testes unitários é mais simples pois só testamos as funcionalidades especificamente daquele algoritmo e se precisa de algo externo mocka, se mocka de mais é um mau sinal, ao menos é isso que se diz por aí :-)
16/11/2012 20:14


0
Opa, farei alguns testes com o DBUnit, obrigado a todos


0
Se você quizer pode ter classes que geram os dados que você precisa nos testes, "Test Data Builders", e/ou fazer asserts que garantam o estado inicial dos dados do seu teste, é outra opção.
18/11/2012 20:26


1
Comecei a aplicar o DBUnit e consegui o que queria.
Olhei um plugin já existente para Grails mas não serve para mim, pois só aplica os dadasets uma vez no inicio da suíte de testes.

Se alguem se interessar, implementei isto na superclasse dos meus testcases:
class TestBase extends GebReportingTest {

@Before
public void setUp() {
def field = this.class.declaredFields.find { it.name.equals("datasets") }

if (field) {
field.accessible = true
def nomesdatasets = field.get(null)
def datasets = []
nomesdatasets.each {
def res = this.class.classLoader.getResourceAsStream("datasets/${it}.xls")
if (!res)
fail "Dataset ${it} nao encontrado"

datasets << new XlsDataSet(res)
}

def jdbc = DriverManager.getConnection(<url jdbc>, <usuario>, <senha>)
def connection = new DatabaseConnection(jdbc)
def composite = new FilteredDataSet(new DatabaseSequenceFilter(connection), new CompositeDataSet((IDataSet[])datasets.toArray()))

DatabaseOperation.CLEAN_INSERT.execute(connection, composite)
}


E agora declarando meus testcases assim:
class XptoTests extends TestBase {
static datasets = ["dataset1", "dataset2", "dataset3"]
def testXyz() {
}

def testFoo() {
}
}


Os datasets que eu selecionar são aplicados no inicio de cada teste, sempre limpando os registros já existentes nas tabelas. Usei o formato xls para os datasets pois posso editar visualmente no OpenOffice ou Excel.

A estrutura de arquivos fica assim:
\Projeto
..\grails-app
..\test
..\test\functional
..\test\functional\datasets\
..\test\functional\datasets\dataset1.xls
..\test\functional\datasets\dataset2.xls
..\test\functional\datasets\dataset3.xls


0
Poxa, bacana isto em Magno.
Tem blog? Se tiver, tá aí um belo post pra divulgar aqui na comunidade, por que muita gente passa por problemas similares.


0
Até tenho, mas está parado há um tempasso.
Mas vou seguir a idéia e postar lá para tirar as teias de aranha rs, depois ponho o link aqui



Ainda não faz parte da comunidade???

Para se registrar, clique aqui.


Aprenda Groovy e Grails com a Formação itexto!

Newsletter Semana Groovy

Assinar

Envie seu link!


Livro de Grails


/dev/All

Os melhores blogs de TI (e em português) em um único lugar!

 
Creative Commons
RSS Grails Brasil é mantido por itexto Consultoria.
Em caso de problemas contacte Henrique Lobo Weissmann (Kico) por e-mail: kico@itexto.com.br
Todo o conteúdo presente neste site adota o Creative Commons como licença padrão.
Ver: 4.14.0
itexto