Thursday, 27 January 2011

Runner de Junit

En el último post escribí sobre una comparativa de dos frameworks. En esa comparativa me interesaba también la velocidad en el proceso, y en vez de codificar el tiempo de inicio y de fin en el mismo test decidí crearme un "runner" de Junit.

Una clase que implemente org.junit.Runner es la encargada de correr los tests y notificar ciertos eventos de los tests como test-iniciado, test-finalizado...

Para la notificación a un Runner se le pueden agregar observadores o listeners. Esos listeners son los que permitieron establecer cuando se comenzaba un test o cuando terminaba pudiendo asi monitorizar tiempos.

El codigo del runner es:



public class PerformanceRunner extends BlockJUnit4ClassRunner{

private Map<String,Execution> testsExecutions = new HashMap<String, Execution>();

public PerformanceRunner(Class< ? > clazz) throws InitializationError {
super(clazz);
}

/* (non-Javadoc)
* @see org.junit.runner.Runner#getDescription()
*/
@Override
public Description getDescription() {
return Description.createTestDescription(PerformanceRunner.class,"Performance Runner");
}

/* (non-Javadoc)
* @see org.junit.runner.Runner#run(org.junit.runner.notification.RunNotifier)
*/
@Override
public void run(RunNotifier notifier) {
notifier.addListener(new RunListener(){
/* (non-Javadoc)
* @see org.junit.runner.notification.RunListener#testStarted(org.junit.runner.Description)
*/
@Override
public void testStarted(Description description) throws Exception {
String methodName = description.getMethodName();
Execution execution = new Execution();
execution.setName(methodName);
execution.setInit(System.currentTimeMillis());
testsExecutions.put(methodName,execution);
}

/* (non-Javadoc)
* @see org.junit.runner.notification.RunListener#testFinished(org.junit.runner.Description)
*/
@Override
public void testFinished(Description description) throws Exception {
String methodName = description.getMethodName();
Execution execution = testsExecutions.get(methodName);
execution.setEnd(System.currentTimeMillis());
}
});
super.run(notifier);
for (Execution ex : testsExecutions.values()){
System.out.println(ex);
}
}
}



Como se puede ver en el método run(RunNotifier) agregamos un listener que almacenara el inicio y cada fin de los eventos lanzados por los tests:



notifier.addListener(new RunListener(){...



Cuando un test se inicia registro su entrada



@Override
public void testStarted(Description description) throws Exception {
String methodName = description.getMethodName();
Execution execution = new Execution();
execution.setName(methodName);
execution.setInit(System.currentTimeMillis());
testsExecutions.put(methodName,execution);
}



Y lo mismo cuando un test termina:



@Override
public void testFinished(Description description) throws Exception {
String methodName = description.getMethodName();
Execution execution = testsExecutions.get(methodName);
execution.setEnd(System.currentTimeMillis());
}



Ya solo queda anotar una clase de tests con la anotación RunWith(...) :



@RunWith(PerformanceRunner.class)
public class LambdajTest {

/**
*
*/
@Test
public void testListByNameSong(){
List<Song> songsByNameContaining =
filter(
having(on(Song.class).getTitle(),containsString("en")),
Util.songs
);
TestCase.assertEquals(2,songsByNameContaining.size());
}
...



Y por ultimo ejecutar el test y ver que resultado tiene:



Test:testSortingByTwoProperties(0.0030s)
Test:testListByNameSong(0.135s)
Test:testAggregateYears(0.0040s)
Test:testListByYearRange(0.0050s)

No comments:

Post a Comment