/*******************************************************************************
* Copyright (c) 2016 SWTBot Committers and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Thomas Wolf - initial API and implementation (Bug 372209).
*******************************************************************************/
package org.eclipse.swtbot.swt.finder.junit.internal;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.swtbot.swt.finder.junit.ScreenshotCaptureListener;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
import org.junit.runner.notification.StoppedByUserException;
/**
* A {@link RunNotifier} that wraps another existing {@link RunNotifier} and
* augments it by taking at most one screenshot upon a test failure.
*/
public class ScreenshotCaptureNotifier extends RunNotifier {
private final ScreenshotCaptureListener screenshotCreator = new ScreenshotCaptureListener();
private final RunNotifier delegate;
private final AtomicBoolean screenshotTakenForTest = new AtomicBoolean();
private Failure testFailure;
public ScreenshotCaptureNotifier(RunNotifier notifier) {
delegate = notifier;
super.addListener(screenshotCreator);
}
/**
* Capture a screenshot if none had been captured yet.
*
* @param failure
* that occurred
*/
public void captureScreenshot(Failure failure) {
if (!screenshotTakenForTest.getAndSet(true)) {
super.fireTestFailure(failure);
}
}
@Override
public void fireTestStarted(Description description) throws StoppedByUserException {
screenshotTakenForTest.set(false);
testFailure = null;
delegate.fireTestStarted(description);
}
@Override
public void fireTestFailure(Failure failure) {
testFailure = failure;
captureScreenshot(failure);
delegate.fireTestFailure(failure);
}
@Override
public void fireTestFinished(Description description) {
delegate.fireTestFinished(description);
if (testFailure == null) {
// Test didn't fail after all -- perhaps some rule let the test
// pass even though it had raised an exception. Remove a previously
// taken screenshot, if any.
screenshotCreator.removeScreenshot(description);
}
testFailure = null;
}
// Every other public method just delegates to the original notifier
@Override
public void addListener(RunListener listener) {
delegate.addListener(listener);
}
@Override
public void removeListener(RunListener listener) {
delegate.removeListener(listener);
}
@Override
public void fireTestRunStarted(Description description) {
delegate.fireTestRunStarted(description);
}
@Override
public void fireTestRunFinished(Result result) {
delegate.fireTestRunFinished(result);
}
@Override
public void fireTestAssumptionFailed(Failure failure) {
delegate.fireTestAssumptionFailed(failure);
}
@Override
public void fireTestIgnored(Description description) {
delegate.fireTestIgnored(description);
}
@Override
public void pleaseStop() {
delegate.pleaseStop();
}
@Override
public void addFirstListener(RunListener listener) {
// This is actually an operation internal to JUnit according to its
// javadoc. It's only used in another JUnit method marked as
// "Do not use. For testing purposes only."
delegate.addFirstListener(listener);
}
}