Skip to content

Instantly share code, notes, and snippets.

@rherrmann
Last active May 11, 2021 10:34
Show Gist options
  • Save rherrmann/7447571 to your computer and use it in GitHub Desktop.
Save rherrmann/7447571 to your computer and use it in GitHub Desktop.
JUnit rule to conditionally ignore test cases (see also http://www.codeaffine.com/2013/11/18/a-junit-rule-to-conditionally-ignore-tests/)
/*******************************************************************************
* Copyright (c) 2013,2014 Rüdiger Herrmann
* 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:
* Rüdiger Herrmann - initial API and implementation
* Matt Morrissette - allow to use non-static inner IgnoreConditions
******************************************************************************/
package com.codeaffine.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Modifier;
import org.junit.Assume;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
public class ConditionalIgnoreRule implements MethodRule {
public interface IgnoreCondition {
boolean isSatisfied();
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface ConditionalIgnore {
Class<? extends IgnoreCondition> condition();
}
@Override
public Statement apply( Statement base, FrameworkMethod method, Object target ) {
Statement result = base;
if( hasConditionalIgnoreAnnotation( method ) ) {
IgnoreCondition condition = getIgnoreContition( target, method );
if( condition.isSatisfied() ) {
result = new IgnoreStatement( condition );
}
}
return result;
}
private static boolean hasConditionalIgnoreAnnotation( FrameworkMethod method ) {
return method.getAnnotation( ConditionalIgnore.class ) != null;
}
private static IgnoreCondition getIgnoreContition( Object target, FrameworkMethod method ) {
ConditionalIgnore annotation = method.getAnnotation( ConditionalIgnore.class );
return new IgnoreConditionCreator( target, annotation ).create();
}
private static class IgnoreConditionCreator {
private final Object target;
private final Class<? extends IgnoreCondition> conditionType;
IgnoreConditionCreator( Object target, ConditionalIgnore annotation ) {
this.target = target;
this.conditionType = annotation.condition();
}
IgnoreCondition create() {
checkConditionType();
try {
return createCondition();
} catch( RuntimeException re ) {
throw re;
} catch( Exception e ) {
throw new RuntimeException( e );
}
}
private IgnoreCondition createCondition() throws Exception {
IgnoreCondition result;
if( isConditionTypeStandalone() ) {
result = conditionType.newInstance();
} else {
result = conditionType.getDeclaredConstructor( target.getClass() ).newInstance( target );
}
return result;
}
private void checkConditionType() {
if( !isConditionTypeStandalone() && !isConditionTypeDeclaredInTarget() ) {
String msg
= "Conditional class '%s' is a member class "
+ "but was not declared inside the test case using it.\n"
+ "Either make this class a static class, "
+ "standalone class (by declaring it in it's own file) "
+ "or move it inside the test case using it";
throw new IllegalArgumentException( String.format ( msg, conditionType.getName() ) );
}
}
private boolean isConditionTypeStandalone() {
return !conditionType.isMemberClass() || Modifier.isStatic( conditionType.getModifiers() );
}
private boolean isConditionTypeDeclaredInTarget() {
return target.getClass().isAssignableFrom( conditionType.getDeclaringClass() );
}
}
private static class IgnoreStatement extends Statement {
private final IgnoreCondition condition;
IgnoreStatement( IgnoreCondition condition ) {
this.condition = condition;
}
@Override
public void evaluate() {
Assume.assumeTrue( "Ignored by " + condition.getClass().getSimpleName(), false );
}
}
}
@navnathkarche
Copy link

I tried this solution with Espresso but doesn't work.

Following is my observation:
If I have four test cases: A(), B(), C(), D() and I applied @ConditionalIgnore on B() method, then C() and D() also ignored.

Can you please help me on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment