La solución de guerda es buena. Esto es lo que terminé haciendo (que es una mezcla de la receta de Lucas Francl, que he vinculado antes, y algunas otras cosas que vi en la red):
import org.junit.runner.manipulation.Filter;
import org.junit.runner.Description;
public final class AntCLFilter extends Filter {
private static final String TEST_CASES = "tests";
private static final String ANT_PROPERTY = "${tests}";
private static final String DELIMITER = "\\,";
private String[] testCaseNames;
public AntCLFilter() {
super();
if (hasTestCases()) testCaseNames = getTestCaseNames();
}
public String describe() {
return "Filters out all tests not explicitly named in a comma-delimited list in the system property 'tests'.";
}
public boolean shouldRun(Description d) {
String displayName = d.getDisplayName();
// cut off the method name:
String testName = displayName.substring(0, displayName.indexOf('('));
if (testCaseNames == null) return true;
for (int i = 0; i < testCaseNames.length; i++)
if (testName.equals(testCaseNames[i]))
return true;
return false;
}
/**
* Check to see if the test cases property is set. Ignores Ant's
* default setting for the property (or null to be on the safe side).
**/
public static boolean hasTestCases() {
return
System.getProperty(TEST_CASES) == null ||
System.getProperty(TEST_CASES).equals(ANT_PROPERTY) ?
false : true;
}
/**
* Create a List of String names of test cases specified in the
* JVM property in comma-separated format.
*
* @return a List of String test case names
*
* @throws NullPointerException if the TEST_CASES property
* isn't set
**/
private static String[] getTestCaseNames() {
if (System.getProperty(TEST_CASES) == null) {
throw new NullPointerException("Test case property is not set");
}
String testCases = System.getProperty(TEST_CASES);
String[] cases = testCases.split(DELIMITER);
return cases;
}
}
import org.junit.internal.runners.*;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.NoTestsRemainException;
public class FilteredRunner extends TestClassRunner {
public FilteredRunner(Class<?> clazz) throws InitializationError {
super(clazz);
Filter f = new AntCLFilter();
try {
f.apply(this);
} catch (NoTestsRemainException ex) {
throw new RuntimeException(ex);
}
}
}
Entonces anotado mi clase de prueba con:
@RunWith(FilteredRunner.class)
public class MyTest {
y poner el siguiente en mi BuildFile hormiga:
<target name="runtest"
description="Runs the test you specify on the command line with -Dtest="
depends="compile, ensure-test-name">
<junit printsummary="withOutAndErr" fork="yes">
<sysproperty key="tests" value="${tests}" />
<classpath refid="classpath" />
<formatter type="plain" usefile="false" />
<batchtest>
<fileset dir="${src}">
<include name="**/${test}.java" />
</fileset>
</batchtest>
</junit>
</target>
la línea clave de estar allí la etiqueta sysproperty.
Y ahora puedo correr
ant runtest -Dtest=MyTest -Dtests=testFoo,testBar
lo deseas. Esto funciona con JUnit 4.1 --- en 4.4, subclase de JUnit4ClassRunner, y en 4.5 y posterior, subclase de BlockJUnit4ClassRunner.
OK, eso es mucho más elegante que mi solución :) – guerda
He estado luchando con este mismo problema (o al menos muy similar) durante unos días y hay una cosa que no deja de molestarme. ¿Qué sucede si quieres usar tu FilteredRunner con Powermock, que también requiere su propia anotación @RunWith (PowermockRunner.class)? –
Gran respuesta, pero obsoleta ahora. Creo que se necesita usar BlockJUnit4ClassRunner en lugar de TestClassRunner – Illidanek