package org.fluentlenium.integration.util.adapter; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.MultipleFailureException; import org.junit.runners.model.Statement; import org.junit.runners.model.TestClass; import java.util.ArrayList; import java.util.List; /** * Equivalent of {@link org.junit.rules.TestWatcher}, but stop process if exception occurs on * starting method call. * <p> * It also supports {@link After} annotations. */ class FluentTestRule implements TestRule { private final Object target; private final TestClass testClass; private final List<FrameworkMethod> afters; /** * Creates a new fluent test rule. * * @param target target of the rule. */ FluentTestRule(Object target) { this.target = target; testClass = new TestClass(target.getClass()); afters = testClass.getAnnotatedMethods(After.class); } @Override public Statement apply(Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { List<Throwable> errors = new ArrayList<>(); try { starting(description); base.evaluate(); succeeded(description); } catch (Throwable e) { errors.add(e); try { failed(e, description); } catch (Throwable failedException) { errors.add(failedException); } for (FrameworkMethod each : afters) { try { each.invokeExplosively(target); } catch (Throwable afterException) { errors.add(afterException); } } } finally { try { finished(description); } catch (Throwable failedException) { errors.add(failedException); } } MultipleFailureException.assertEmpty(errors); } }; } /** * Invoked when a test succeeds. * * @param description test description */ protected void succeeded(Description description) { //Do nothing. } /** * Invoked when a test fails * * @param e exception * @param description test description */ protected void failed(Throwable e, Description description) { //Do nothing. } /** * Invoked when a test is about to start * * @param description test description */ protected void starting(Description description) { //Do nothing. } /** * Invoked when a test method finishes (whether passing or failing) * * @param description test description */ protected void finished(Description description) { //Do nothing. } }