Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for handling additional Exceptions with PendingFeature ... #528

Merged
merged 1 commit into from
Sep 16, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.spockframework.runtime.extension.builtin;

import org.junit.AssumptionViolatedException;

/**
* @author Leonard Brünings
*/
public class PendingFeatureBaseInterceptor {
protected final Class<? extends Throwable>[] expectedExceptions;

public PendingFeatureBaseInterceptor(Class<? extends Throwable>[] expectedExceptions) {
this.expectedExceptions = expectedExceptions;
}

protected boolean isExpected(Throwable e) {
for (Class<? extends Throwable> exception : expectedExceptions) {
if(exception.isInstance(e)) {
return true;
}
}
return false;
}
protected AssertionError featurePassedUnexpectedly() {
return new AssertionError("Feature is marked with @PendingFeature but passes unexpectedly");
}

protected AssumptionViolatedException assumptionViolation() {
return new AssumptionViolatedException("Feature not yet implemented correctly.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ public class PendingFeatureExtension extends AbstractAnnotationDrivenExtension<P
@Override
public void visitFeatureAnnotation(PendingFeature annotation, FeatureInfo feature) {
if (feature.isParameterized()) {
feature.addInterceptor(new PendingFeatureIterationInterceptor());
feature.addInterceptor(new PendingFeatureIterationInterceptor(annotation.exceptions()));
} else {
feature.getFeatureMethod().addInterceptor(new PendingFeatureInterceptor());
feature.getFeatureMethod().addInterceptor(new PendingFeatureInterceptor(annotation.exceptions()));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
package org.spockframework.runtime.extension.builtin;

import org.junit.AssumptionViolatedException;
import org.spockframework.runtime.extension.IMethodInterceptor;
import org.spockframework.runtime.extension.IMethodInvocation;

/**
* @author Leonard Brünings
*/
class PendingFeatureInterceptor implements IMethodInterceptor {
class PendingFeatureInterceptor extends PendingFeatureBaseInterceptor implements IMethodInterceptor {

public PendingFeatureInterceptor(Class<? extends Throwable>[] handledExceptions) {
super(handledExceptions);
}

@Override
public void intercept(IMethodInvocation invocation) throws Throwable {
try {
invocation.proceed();
} catch (AssertionError e) {
throw new AssumptionViolatedException("Feature not yet implemented correctly.");
throw assumptionViolation();
} catch (Throwable e) {
if (isExpected(e)) {
throw assumptionViolation();
} else {
throw e;
}
}
throw new AssertionError("Feature is marked with @PendingFeature but passes unexpectedly");
throw featurePassedUnexpectedly();
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.spockframework.runtime.extension.builtin;

import org.junit.AssumptionViolatedException;
import org.spockframework.runtime.extension.IMethodInterceptor;
import org.spockframework.runtime.extension.IMethodInvocation;

Expand All @@ -9,24 +8,30 @@
/**
* @author Leonard Brünings
*/
class PendingFeatureIterationInterceptor implements IMethodInterceptor {
class PendingFeatureIterationInterceptor extends PendingFeatureBaseInterceptor implements IMethodInterceptor {

public PendingFeatureIterationInterceptor(Class<? extends Throwable>[] expectedExceptions) {
super(expectedExceptions);
}

@Override
public void intercept(IMethodInvocation invocation) throws Throwable {

AtomicBoolean pass = new AtomicBoolean(false);
invocation.getFeature().getFeatureMethod().addInterceptor(new InnerIterationInterceptor(pass));
invocation.getFeature().getFeatureMethod().addInterceptor(new InnerIterationInterceptor(pass, expectedExceptions));
invocation.proceed();
if (pass.get()) {
throw new AssumptionViolatedException("Feature not yet implemented correctly.");
throw assumptionViolation();
} else {
throw new AssertionError("Feature is marked with @PendingFeature but passes unexpectedly");
throw featurePassedUnexpectedly();
}
}

private static class InnerIterationInterceptor implements IMethodInterceptor {
private static class InnerIterationInterceptor extends PendingFeatureBaseInterceptor implements IMethodInterceptor {
private final AtomicBoolean pass;

public InnerIterationInterceptor(AtomicBoolean pass) {
public InnerIterationInterceptor(AtomicBoolean pass, Class<? extends Throwable>[] expectedExceptions) {
super(expectedExceptions);
this.pass = pass;
}

Expand All @@ -36,6 +41,12 @@ public void intercept(IMethodInvocation invocation) throws Throwable {
invocation.proceed();
} catch (AssertionError e) {
pass.set(true);
} catch (Throwable e) {
if (isExpected(e)) {
pass.set(true);
} else {
throw e;
}
}
}
}
Expand Down
9 changes: 8 additions & 1 deletion spock-core/src/main/java/spock/lang/PendingFeature.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@


import org.spockframework.runtime.extension.ExtensionAnnotation;
import org.spockframework.runtime.extension.builtin.IgnoreExtension;
import org.spockframework.runtime.extension.builtin.PendingFeatureExtension;
import org.spockframework.util.Beta;

Expand Down Expand Up @@ -40,4 +39,12 @@
@Target({ElementType.METHOD})
@ExtensionAnnotation(PendingFeatureExtension.class)
public @interface PendingFeature {
/**
* Configures which types of Exceptions are expected in the pending feature.
*
* Subclasses are included if their parent class is listed.
*
* @return array of Exception classes to ignore.
*/
Class<? extends Throwable>[] exceptions() default {Exception.class};
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,42 @@ class Foo extends Specification {
result.ignoreCount == 0
}

def "@PendingFeature marks feature that fails with exception as skipped"() {
when:
def result = runner.runWithImports("""

class Foo extends Specification {
@PendingFeature
def bar() {
expect:
throw new Exception()
}
}
""")

then:
noExceptionThrown()
result.runCount == 1
result.failureCount == 0
result.ignoreCount == 0
}
def "@PendingFeature rethrows non handled exceptions"() {
when:
def result = runner.runWithImports("""

class Foo extends Specification {
@PendingFeature(exceptions=[IndexOutOfBoundsException])
def bar() {
expect:
throw new IllegalArgumentException()
}
}
""")

then:
thrown(IllegalArgumentException)
}

def "@PendingFeature marks passing feature as failed"() {
when:
runner.runWithImports("""
Expand Down