java - unitaria - Un observador de prueba para informar los resultados de las pruebas individuales en JUnit Suite
prueba unitaria con junit (2)
Uso una implementación RunListener, que registra los resultados en un archivo. Primero, tengo una clase de corredor de prueba a la que se llama para cada conjunto de pruebas:
public Result run(String suite) {
Class<?> suiteClass = null;
try {
suiteClass = Class.forName(suite);
} catch (ClassNotFoundException ex) {
return null;
}
JUnitCore core = new JUnitCore();
this.testRun = new TestRun(testLogging, suite);
core.addListener(new TestRunListener(testLogging, testRun));
Result result = core.run(suiteClass);
return(result);
}
La clase TestRun es una clase personalizada que simplemente cuenta el número de pruebas que tienen: iniciado, aprobado, no aprobado, ignorado.
TestRunListener implementa org.junit.runner.notification.RunListener y realiza un seguimiento de la información sobre el estado de la prueba, en función de las devoluciones de llamadas (por ejemplo, testFailure (), testFinished (), etc.).
@Override
public void testFailure(Failure failure) throws Exception {
classLogger.log(Level.CONFIG, failure.getMessage());
classLogger.log(Level.CONFIG, failure.getTestHeader());
classLogger.log(Level.CONFIG, failure.getTrace());
classLogger.log(Level.CONFIG, failure.getDescription().getDisplayName());
if (failure.getException() != null) {
classLogger.log(Level.CONFIG, failure.getException().getMessage());
}
super.testFailure(failure);
Description description = failure.getDescription();
Test test = processTestResult(TestStatus.FAIL, description);
if (test == null) {
classLogger.log(Level.SEVERE, "TEST IS NULL:" + description.getDisplayName());
return;
}
classLogger.log(Level.CONFIG, failure.getMessage()+ " " + description.getDisplayName());
test.setFailureMessage(description.getDisplayName());
test.setFailureException(failure.getException());
LogRecord record = new LogRecord(Level.CONFIG, failure.getMessage());
record.setParameters(new Object[] { test, failure });
testFailuresLogger.log(record);
}
Entonces tengo una suite, algo como esto:
@RunWith(Suite.class)
@Suite.SuiteClasses({TestClass1.class, TestClass2.class, TestClass3.class})
public class TestSuite {
static List<ExtentTest> extentTestList = new ArrayList<>();
@ClassRule
public static ExtentWatcher extentWatcher = new ExtentWatcher() {
@Override
protected void starting(Description description) {
extentTestList.addAll(extentWatcher.getTests());
}
@Override
protected void finished(Description description) {
extentWatcher.flushReports(extentTestList);
}
};
}
El código anterior funciona, pero el problema es que mi Watcher informa los resultados de la Suite, no las pruebas individuales. Además, si una prueba falla, el conjunto de aplicaciones sigue informando como se aprobó. My Watcher es algo como esto:
public class ExtentWatcher extends TestWatcher {
// A little set up to give the report a date in the file name
private DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
private Date date = new Date();
private String fileDate = dateFormat.format(date);
private String reportName = "./Test_Report_" + fileDate + ".html";
public ExtentReports extent;
ArrayList<ExtentTest> testList = new ArrayList<>();
public ExtentWatcher() {
extent = createReport();
}
// If test passed, watcher will record this with Extent Reports
@Override
protected void succeeded(Description description) {
ExtentTest test = extent.startTest(description.getDisplayName());
test.log(LogStatus.PASS, "Test Run Successful");
testList.add(test);
}
// Likewise in case of failure
@Override
protected void failed(Throwable e, Description description) {
ExtentTest test = extent.startTest(description.getDisplayName());
test.log(LogStatus.FAIL, "Test Failure: " + e.toString());
testList.add(test);
}
/**
* These methods do the legwork - this file is based off of an example I found @ www.kieftsoft.nl/?p=81
* Eventually we can add some screenshot logic here, but just a clean test report and version info will do
*/
private ExtentReports createReport() {
// Create the report - Extent just needs a little config
ExtentReports extent = new ExtentReports(reportName, false);
extent.config().reportName("Test Report: " + fileDate);
return extent;
}
public void flushReports(List<ExtentTest> testList) {
// This ends the test and then sends (flushes) everything to the html document
for(ExtentTest test : testList) extent.endTest(test);
extent.flush();
}
public List<ExtentTest> getTests() {
return testList;
}
}
Este código funciona bien anotado como @Rule para una prueba individual (con un informe para cada prueba individualmente, no es deseable), pero como se indicó anteriormente, esto no funciona en un nivel Suite y realmente no estoy seguro de cómo hacerlo trabajo. Estaba pensando que podría recopilar una lista de todas las pruebas, y en la suite, finalizar las pruebas y eliminarlas, lo que permitirá a ExtentReport darme un informe de todas las pruebas. Sin embargo, no puedo obtener específicamente los resultados de las pruebas individuales. Recibiré una prueba nuevamente, con displayName () = el nombre de la Suite.
¿Cómo puedo rastrear las pruebas individuales, luego las dejo cuando todas hayan terminado y deje que el ExtentWatcher se encargue de pasar / reprobar prueba por prueba, en lugar de solo una vez para la suite?
El código anterior funciona, pero el problema es que mi Watcher informa los resultados de la Suite, no las pruebas individuales.
ClassRule
especificados en la clase TestSuite se ejecutan en el nivel de clase y no se pueden ejecutar para cada prueba individual. Por lo tanto, su observador no está informando para pruebas individuales.
Como está interesado en enumerar el evento para cada nivel de prueba individual, puede usar org.junit.runner.notification.RunListener
(en lugar de Watcher). Para evitar especificar el oyente en cada clase de prueba, puede implementar su propio corrector de prueba Suite que registrará el RunListener personalizado automáticamente.
Por ejemplo:
public class SuiteRunner extends Suite {
public SuiteRunner(Class<?> klass) throws InitializationError {
super(klass, new JUnit4Builder());
}
@Override
public void run(RunNotifier notifier) {
notifier.addFirstListener(new RunListener() {
@Override
public void testRunStarted(Description description) throws Exception {
// add to watcher
}
@Override
public void testFailure(Failure failure) throws Exception {
// add to watcher
}
});
super.run(notifier);
}
}
Y especifique este corredor en su clase Test Suite
@RunWith(SuiteRunner.class)
@Suite.SuiteClasses({ MyTest.class , MyTest2.class })
public class TestSuite {
@ClassRule
public static ExtentWatcher watcher = new ExtentWatcher();
}
Espero eso ayude.