Freitag, 20. Januar 2012

JUnit-Massentest mit Parameter aus CSV-File

Mit JUnit-Bordmitteln ist es möglich, JUnit-Tests zu parametrisieren und sie mit Testdaten abzufüllen. Die Testdaten kommen in diesem Beispiel aus einem CSV-File, das in einer H2-Datenbank zwischengespeichert wird.
Der Trick: 
Der spezielle JUnit-Runner Parametrized, der mit @RunWith angekickt wird, durchläuft die Testklasse n mal. Dabei werden die Instanzvariablen, hier aInput, bInput, pErwartet, n mal neu abgefüllt.
Die Daten dazu kommen aus der Methode, die mit @Parametrized annotiert ist. Die Magie dabei ist, dass die Methode eine Collection von Object-Arrays zurückgibt, wobei der Object-Array genau den Argumenten des Construktors der JUnit-Testklasse entspricht.

https://gist.github.com/2577376


Testklasse:


package ch.schumm.h2;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
/**
* JUnitDataProvider
* @author Rémy Schumm - 2010
*/
public class JUnitDataProvider {
private Connection conn;
/**
* @throws ClassNotFoundException
* @throws SQLException
*
*/
public JUnitDataProvider() throws ClassNotFoundException, SQLException {
Class.forName("org.h2.Driver");
conn = DriverManager.getConnection("jdbc:h2:mem:");
loadData();
}
private void loadData() throws SQLException {
Statement insertStatement = conn.createStatement();
String insert = "CREATE TABLE produkte(a int, b int, p int) AS SELECT * FROM CSVREAD('produkte.csv', NULL, NULL, ';')";
insertStatement.execute(insert);
}
/**
* liefert die Testdaten, die von JUnit in den Konstruktor
* ProduktTest(int a, int b, int p) abgefüllt werden.
* @return eine Collection von Object-Arrays der Form int a, int b, int p
* @throws SQLException
*/
public List<Object[]> getJUnitParameters() throws SQLException {
ArrayList<Object[]> ret = new ArrayList<Object[]>();
Statement suchStatement = conn.createStatement();
String suche = "Select * from produkte";
ResultSet resultSet = suchStatement.executeQuery(suche);
while (resultSet.next()){
int a = resultSet.getInt(resultSet.findColumn("a"));
int b = resultSet.getInt(resultSet.findColumn("b"));
int p = resultSet.getInt(resultSet.findColumn("p"));
//Object-Array der Form int a, int b, int p
//für den Konstruktor des JUnit-Tests.
ret.add(new Object[]{a, b, p});
}
System.out.println("Testdaten gelesen.");
return ret;
}
/**
* zu H2-Testzwecken.
* @param args
* @throws ClassNotFoundException
* @throws SQLException
*/
public static void main(String[] args) throws SQLException, ClassNotFoundException {
List<Object[]> jUnitParameters = new JUnitDataProvider().getJUnitParameters();
System.out.println(jUnitParameters.toString());
}
}
package ch.schumm.junit;
import static org.junit.Assert.assertEquals;
import java.sql.SQLException;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import ch.schumm.h2.JUnitDataProvider;
/**
* ProduktTest
* @author Rémy Schumm - 2010
*/
@RunWith(Parameterized.class)
public class ProduktTest {
private int aInput;
private int bInput;
private int pErwartet;
public ProduktTest(int a, int b, int p){
super();
this.aInput = a;
this.bInput = b;
this.pErwartet = p;
}
/**
* liefert die Testdaten, die von JUnit in den Konstruktor
* ProduktTest(int a, int b, int p) abgefüllt werden.
* @return eine Collection von Object-Arrays der Form int a, int b, int p
* @throws SQLException
* @throws ClassNotFoundException
*/
@Parameters
public static Collection<Object[]> holeProduktTestdaten() throws SQLException, ClassNotFoundException{
return new JUnitDataProvider().getJUnitParameters();
}
@Test
public void testProdukt(){
int produkt = aInput * bInput;
assertEquals("Falsches Produkt von " + aInput + " und " + bInput, pErwartet, produkt);
}
}





So ist es leicht möglich, mal rasch ein paar Tausend JUnit-Tests zu machen... Nur: wer testet die Testdaten?




Update JUnit 4.11

Benamste Parameter: 


Keine Kommentare:

Kommentar veröffentlichen