Skip to content

Commit

Permalink
chore(ARQ-2172): merged the same runner and rule code to avoid code d…
Browse files Browse the repository at this point in the history
…uplication(#155)
  • Loading branch information
MatousJobanek authored and bartoszmajsak committed Jan 23, 2018
1 parent 9a2130f commit ac923bc
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 143 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.jboss.arquillian.junit;

import org.jboss.arquillian.test.spi.TestRunnerAdaptor;
import org.jboss.arquillian.test.spi.TestRunnerAdaptorBuilder;

abstract class AdaptorManager {

void initializeAdaptor() throws Exception {
// first time we're being initialized
if (!State.hasTestAdaptor()) {
// no, initialization has been attempted before and failed, refuse
// to do anything else
if (State.hasInitializationException()) {
// failed on suite level, ignore children
// notifier.fireTestIgnored(getFailureDescription());
handleSuiteLevelFailure(State.getInitializationException());
} else {
try {
// ARQ-1742 If exceptions happen during boot
TestRunnerAdaptor adaptor = TestRunnerAdaptorBuilder
.build();
// don't set it if beforeSuite fails
adaptor.beforeSuite();
State.testAdaptor(adaptor);
} catch (Exception e) {
// caught exception during BeforeSuite, mark this as failed
State.caughtInitializationException(e);
handleBeforeSuiteFailure(e);
}
}
}

if (State.hasTestAdaptor()) {
setAdaptor(State.getTestAdaptor());
}
}

void shutdown(TestRunnerAdaptor adaptor) {
State.runnerFinished();
try {
if (State.isLastRunner()) {
try {
if (adaptor != null) {
adaptor.afterSuite();
adaptor.shutdown();
}
} finally {
State.clean();
}
}
setAdaptor(null);
} catch (Exception e) {
throw new RuntimeException("Could not run @AfterSuite", e);
}
}

protected abstract void handleSuiteLevelFailure(Throwable initializationException);

protected abstract void handleBeforeSuiteFailure(Exception e) throws Exception;

protected abstract void setAdaptor(TestRunnerAdaptor testRunnerAdaptor);

protected abstract TestRunnerAdaptor getAdaptor();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.jboss.arquillian.junit;

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;

abstract class AdaptorManagerWithNotifier extends AdaptorManager {

private final RunNotifier notifier;

AdaptorManagerWithNotifier(RunNotifier notifier){
this.notifier = notifier;
}

void initializeAdaptor() {
try {
super.initializeAdaptor();
} catch (Exception e) {
// this never happens
}
}

void prepareDestroyAdaptorProcess(){
notifier.addListener(new RunListener() {
@Override
public void testRunFinished(Result result) throws Exception {
shutdown(getAdaptor());
}
});
}

protected void handleSuiteLevelFailure(Throwable initializationException) {
notifier.fireTestFailure(
new Failure(getFailureDescription(),
new RuntimeException(
"Arquillian initialization has already been attempted, but failed. See previous exceptions for cause",
initializationException)));
}

protected void handleBeforeSuiteFailure(Exception e) throws Exception {
notifier.fireTestFailure(new Failure(getFailureDescription(), e));
}

protected abstract Description getFailureDescription();
}
88 changes: 18 additions & 70 deletions junit/core/src/main/java/org/jboss/arquillian/junit/Arquillian.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,13 @@
import org.jboss.arquillian.test.spi.TestResult;
import org.jboss.arquillian.test.spi.TestResult.Status;
import org.jboss.arquillian.test.spi.TestRunnerAdaptor;
import org.jboss.arquillian.test.spi.TestRunnerAdaptorBuilder;
import org.jboss.arquillian.test.spi.execution.SkippedTestExecutionException;
import org.junit.internal.AssumptionViolatedException;
import org.junit.internal.runners.model.MultipleFailureException;
import org.junit.internal.runners.model.ReflectiveCallable;
import org.junit.internal.runners.statements.Fail;
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.runners.BlockJUnit4ClassRunner;
Expand Down Expand Up @@ -92,59 +91,26 @@ public void run(final RunNotifier notifier) {
if (State.isNotRunningInEclipse()) {
State.runnerStarted();
}
// first time we're being initialized
if (!State.hasTestAdaptor()) {
// no, initialization has been attempted before and failed, refuse to do anything else
if (State.hasInitializationException()) {
// failed on suite level, ignore children
//notifier.fireTestIgnored(getDescription());
notifier.fireTestFailure(
new Failure(getDescription(),
new RuntimeException(
"Arquillian initialization has already been attempted, but failed. See previous exceptions for cause",
State.getInitializationException())));
} else {
try {
// ARQ-1742 If exceptions happen during boot
TestRunnerAdaptor adaptor = TestRunnerAdaptorBuilder.build();
// don't set it if beforeSuite fails
adaptor.beforeSuite();
State.testAdaptor(adaptor);
} catch (Exception e) {
// caught exception during BeforeSuite, mark this as failed
State.caughtInitializationException(e);
notifier.fireTestFailure(new Failure(getDescription(), e));
}

AdaptorManagerWithNotifier adaptorManager = new AdaptorManagerWithNotifier(notifier) {
protected void setAdaptor(TestRunnerAdaptor testRunnerAdaptor) {
adaptor = testRunnerAdaptor;
}
}
notifier.addListener(new RunListener() {
@Override
public void testRunFinished(Result result) throws Exception {
State.runnerFinished();
shutdown();

protected TestRunnerAdaptor getAdaptor() {
return adaptor;
}

private void shutdown() {
try {
if (State.isLastRunner()) {
try {
if (adaptor != null) {
adaptor.afterSuite();
adaptor.shutdown();
}
} finally {
State.clean();
}
}
adaptor = null;
} catch (Exception e) {
throw new RuntimeException("Could not run @AfterSuite", e);
}
protected Description getFailureDescription() {
return getDescription();
}
});
};
adaptorManager.initializeAdaptor();
adaptorManager.prepareDestroyAdaptorProcess();


// initialization ok, run children
if (State.hasTestAdaptor()) {
adaptor = State.getTestAdaptor();
super.run(notifier);
}
}
Expand Down Expand Up @@ -335,9 +301,8 @@ protected Statement methodInvoker(final FrameworkMethod method, final Object tes
return new Statement() {
@Override
public void evaluate() throws Throwable {
TestResult result = adaptor.test(new TestMethodExecutor() {
@Override
public void invoke(Object... parameters) throws Throwable {
new MethodInvoker() {
void invokeMethod(Object... parameters) throws Throwable {
try {
method.invokeExplosively(test, parameters);
} catch (Throwable e) {
Expand All @@ -346,24 +311,7 @@ public void invoke(Object... parameters) throws Throwable {
throw e;
}
}

public Method getMethod() {
return method.getMethod();
}

public Object getInstance() {
return test;
}
});
Throwable throwable = result.getThrowable();
if (throwable != null) {
if (result.getStatus() == Status.SKIPPED) {
if (throwable instanceof SkippedTestExecutionException) {
result.setThrowable(new AssumptionViolatedException(throwable.getMessage()));
}
}
throw result.getThrowable();
}
}.invoke(adaptor, method, test);
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
import java.util.List;
import org.jboss.arquillian.junit.event.AfterRules;
import org.jboss.arquillian.junit.event.BeforeRules;
import org.jboss.arquillian.junit.event.RulesEnrichment;
import org.jboss.arquillian.test.spi.LifecycleMethodExecutor;
import org.jboss.arquillian.test.spi.TestMethodExecutor;
import org.jboss.arquillian.test.spi.TestResult;
import org.jboss.arquillian.test.spi.TestRunnerAdaptor;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
Expand Down Expand Up @@ -40,48 +39,39 @@ public ArquillianTest() {
}
}

public Statement apply(final Statement base, final FrameworkMethod method,
final Object target) {
public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
return new Statement() {
@Override
public void evaluate() throws Throwable {

final List<Throwable> errors = new ArrayList<Throwable>();

TestClass testClass = new TestClass(method.getDeclaringClass());
Method testMethod = method.getMethod();

adaptor.fireCustomLifecycle(
new RulesEnrichment(target, testClass, testMethod, LifecycleMethodExecutor.NO_OP));
adaptor.fireCustomLifecycle(
new BeforeRules(target, new TestClass(method.getDeclaringClass()), base, method.getMethod(),
LifecycleMethodExecutor.NO_OP));
new BeforeRules(target, testClass, base, testMethod, LifecycleMethodExecutor.NO_OP));

adaptor.before(target, method.getMethod(), LifecycleMethodExecutor.NO_OP);
adaptor.before(target, testMethod, LifecycleMethodExecutor.NO_OP);

try {
TestResult result = adaptor.test(new TestMethodExecutor() {
public void invoke(Object... parameters)
throws Throwable {
new MethodInvoker() {
void invokeMethod(Object... parameters) throws Throwable {
try {
base.evaluate();
} catch (Throwable e) {
errors.add(e);
}

}

public Method getMethod() {
return method.getMethod();
}

public Object getInstance() {
return target;
}
});
if (result.getThrowable() != null) {
throw result.getThrowable();
}
}.invoke(adaptor, method, target);
} finally {
adaptor.after(target, method.getMethod(),
adaptor.after(target, testMethod,
LifecycleMethodExecutor.NO_OP);
try {
adaptor.fireCustomLifecycle(
new AfterRules(target, method.getMethod(), LifecycleMethodExecutor.NO_OP));
new AfterRules(target, testMethod, LifecycleMethodExecutor.NO_OP));
} catch (Throwable e) {
errors.add(e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package org.jboss.arquillian.junit;

import org.jboss.arquillian.test.spi.LifecycleMethodExecutor;
import org.jboss.arquillian.test.spi.TestRunnerAdaptor;
import org.jboss.arquillian.test.spi.TestRunnerAdaptorBuilder;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
Expand All @@ -28,57 +26,21 @@ public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
State.runnerStarted();
// first time we're being initialized
if (!State.hasTestAdaptor()) {
// no, initialization has been attempted before and failed, refuse
// to do anything else
if (State.hasInitializationException()) {
// failed on suite level, ignore children
// notifier.fireTestIgnored(getDescription());
throw new RuntimeException(
"Arquillian initialization has already been attempted, but failed. See previous exceptions for cause",
State.getInitializationException());
} else {
try {
// ARQ-1742 If exceptions happen during boot
TestRunnerAdaptor adaptor = TestRunnerAdaptorBuilder
.build();
// don't set it if beforeSuite fails
adaptor.beforeSuite();
State.testAdaptor(adaptor);
} catch (Exception e) {
// caught exception during BeforeSuite, mark this as failed
State.caughtInitializationException(e);
State.runnerFinished();
if (State.isLastRunner()) {
State.clean();
}
throw e;
ArquillianTestClassLifecycleManager arquillian =
new ArquillianTestClassLifecycleManager() {
protected void setAdaptor(TestRunnerAdaptor testRunnerAdaptor) {
adaptor = testRunnerAdaptor;
}
}
}

// initialization ok, run children
if (State.hasTestAdaptor()) {
adaptor = State.getTestAdaptor();
}

adaptor.beforeClass(description.getTestClass(), LifecycleMethodExecutor.NO_OP);
protected TestRunnerAdaptor getAdaptor() {
return adaptor;
}
};
arquillian.beforeTestClassPhase(description.getTestClass());
try {
base.evaluate();
} finally {
adaptor.afterClass(description.getTestClass(), LifecycleMethodExecutor.NO_OP);
State.runnerFinished();
if (State.isLastRunner()) {
try {
adaptor.afterSuite();
adaptor.shutdown();
} finally {
State.clean();
}
}
adaptor = null;
arquillian.afterTestClassPhase(description.getTestClass());
}
}
};
Expand Down
Loading

0 comments on commit ac923bc

Please sign in to comment.