package net.thucydides.junit.listeners;
import net.thucydides.core.model.FailureCause;
import net.thucydides.core.model.TestOutcome;
import net.thucydides.core.steps.BaseStepListener;
import net.thucydides.core.steps.StepEventBus;
import net.thucydides.core.steps.StepListener;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import java.io.File;
import java.util.List;
/**
* Intercepts JUnit events and reports them to Thucydides.
*/
public class JUnitStepListener extends RunListener {
private BaseStepListener baseStepListener;
private StepListener[] extraListeners;
private Class<?> testClass;
private boolean testStarted;
public static JUnitStepListenerBuilder withOutputDirectory(File outputDirectory) {
return new JUnitStepListenerBuilder(outputDirectory);
}
protected JUnitStepListener(Class<?> testClass, BaseStepListener baseStepListener, StepListener... listeners) {
testStarted = false;
this.baseStepListener = baseStepListener;
this.extraListeners = listeners;
this.testClass = testClass;
registerThucydidesListeners();
}
public void registerThucydidesListeners() {
StepEventBus.getEventBus().registerListener(baseStepListener);
for(StepListener listener : extraListeners) {
StepEventBus.getEventBus().registerListener(listener);
}
}
public BaseStepListener getBaseStepListener() {
return baseStepListener;
}
@Override
public void testRunStarted(Description description) throws Exception {
super.testRunStarted(description);
}
@Override
public void testRunFinished(Result result) throws Exception {
StepEventBus.getEventBus().testRunFinished();
super.testRunFinished(result);
}
/**
* Called when a test starts. We also need to start the test suite the first
* time, as the testRunStarted() method is not invoked for some reason.
*/
@Override
public void testStarted(final Description description) {
if (testingThisTest(description)) {
startTestSuiteForFirstTest(description);
StepEventBus.getEventBus().clear();
StepEventBus.getEventBus().testStarted(description.getMethodName(),
description.getTestClass());
startTest();
}
}
private void startTestSuiteForFirstTest(Description description) {
if (!getBaseStepListener().testSuiteRunning()) {
StepEventBus.getEventBus().testSuiteStarted(description.getTestClass());
}
}
@Override
public void testFinished(final Description description) throws Exception {
if (testingThisTest(description)) {
StepEventBus.getEventBus().testFinished();
endTest();
}
}
@Override
public void testFailure(final Failure failure) throws Exception {
if (testingThisTest(failure.getDescription())) {
startTestIfNotYetStarted(failure.getDescription());
StepEventBus.getEventBus().testFailed(failure.getException());
endTest();
}
}
private void startTestIfNotYetStarted(Description description) {
if (!testStarted) {
testStarted(description);
}
}
@Override
public void testIgnored(final Description description) throws Exception {
if (testingThisTest(description)) {
StepEventBus.getEventBus().testIgnored();
endTest();
}
}
public List<TestOutcome> getTestOutcomes() {
return baseStepListener.getTestOutcomes();
}
public FailureCause getError() {
return baseStepListener.getTestFailureCause();
}
public boolean hasRecordedFailures() {
return baseStepListener.aStepHasFailed();
}
public void dropListeners() {
StepEventBus.getEventBus().dropListener(baseStepListener);
for(StepListener listener : extraListeners) {
StepEventBus.getEventBus().dropListener(listener);
}
}
private void startTest() {
testStarted = true;
}
private void endTest() {
testStarted = false;
}
private boolean testingThisTest(Description description) {
return description.getTestClass().equals(testClass);
}
protected Class<?> getTestClass() {
return testClass;
}
}