La solution de guerda est bonne. Voici ce que je fini par faire (c'est un mélange de recette de Luc Francl, que je lié avant, et quelques autres trucs que j'ai vu sur le net):
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);
}
}
}
J'annotées ma classe de test avec:
@RunWith(FilteredRunner.class)
public class MyTest {
et mettre ce qui suit dans ma fourmi buildfile:
<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 ligne clé étant là la balise sysproperty.
Et maintenant, je peux courir
ant runtest -Dtest=MyTest -Dtests=testFoo,testBar
comme vous le souhaitez. Cela fonctionne avec JUnit 4.1 --- 4.4, sous-classe de JUnit4ClassRunner, et dans 4.5 et plus tard, sous-classe de BlockJUnit4ClassRunner.
OK, c'est beaucoup plus élégant que ma solution :) – guerda
J'ai lutté avec ce même problème (ou au moins très similaire) pendant quelques jours et il y a une chose qui ne cesse de me déranger. Que faire si vous souhaitez utiliser votre FilteredRunner avec Powermock, qui nécessite également sa propre annotation @RunWith (PowermockRunner.class)? –
Bonne réponse, mais démodé maintenant. Je pense que BlockJUnit4ClassRunner doit être utilisé à la place de TestClassRunner – Illidanek