Skip to content

Commit cb6e52f

Browse files
Support filtering parameterized tests with arbitrary parameter names.
Previously, TestRequestBuilder only stripped numeric suffixes (e.g. [0]) when matching test method names. Update the parameterized suffix pattern to support arbitrary parameter names, allowing custom-named parameterized tests to be filtered by their root method name. PiperOrigin-RevId: 988075477
1 parent 66d6412 commit cb6e52f

3 files changed

Lines changed: 77 additions & 6 deletions

File tree

‎runner/android_junit_runner/CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
* Catch LinkageError when loading annotation classes (b/536117227)
1010

11+
* Support filtering parameterized tests with arbitrary (non-numeric) parameter names by their root method name. (b/564761639)
12+
1113
**New Features**
1214

1315
* Make perfetto trace sections for tests more identifiable by prefixing with "test:" and using fully qualified class name. (b/204992764)

‎runner/android_junit_runner/java/androidx/test/internal/runner/TestRequestBuilder.java‎

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import java.util.List;
4747
import java.util.Map;
4848
import java.util.Set;
49+
import java.util.regex.Matcher;
4950
import java.util.regex.Pattern;
5051
import org.junit.runner.Description;
5152
import org.junit.runner.Request;
@@ -364,6 +365,17 @@ public void removeMethod(String className, String methodName) {
364365
/** A {@link Filter} used to filter out desired test methods from a given class */
365366
private static class MethodFilter extends AbstractFilter {
366367

368+
/**
369+
* Matches a parameterized test method name, capturing the root method name.
370+
*
371+
* <p>Parameterized runners name tests as {@code methodName[<params>]}, where {@code <params>}
372+
* is arbitrary text, e.g. {@code [0]}, {@code [0: 1 + 2 = 3]}, {@code [dryRun=true,retries=2]}
373+
* or {@code [[1, 2]]}. Since a JVM method name cannot contain {@code '['}, everything before
374+
* the first {@code '['} is the root method name.
375+
*/
376+
private static final Pattern PARAMETERIZED_SUFFIX_PATTERN =
377+
Pattern.compile("^([^\\[]+)\\[.*\\]$", Pattern.DOTALL);
378+
367379
private final String className;
368380
private Set<String> includedMethods = new HashSet<>();
369381
private Set<String> excludedMethods = new HashSet<>();
@@ -408,12 +420,9 @@ public boolean evaluateTest(Description description) {
408420
}
409421

410422
// Strips out the parameterized suffix if it exists
411-
private String stripParameterizedSuffix(String name) {
412-
Pattern suffixPattern = Pattern.compile(".+(\\[[0-9]+\\])$");
413-
if (suffixPattern.matcher(name).matches()) {
414-
name = name.substring(0, name.lastIndexOf('['));
415-
}
416-
return name;
423+
private static String stripParameterizedSuffix(String name) {
424+
Matcher matcher = PARAMETERIZED_SUFFIX_PATTERN.matcher(name);
425+
return matcher.matches() ? matcher.group(1) : name;
417426
}
418427

419428
public void addInclusionMethod(String methodName) {

‎runner/android_junit_runner/javatests/androidx/test/internal/runner/TestRequestBuilderTest.java‎

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,30 @@ public static Collection<Object[]> data() {
338338
public void testParameterized() {}
339339
}
340340

341+
/**
342+
* Parameterized test fixture whose generated names have non-numeric parameter suffixes, e.g.
343+
* {@code testFoo[0: a b]}, {@code testFoo[1: [1, 2]]}, {@code testFoo[2: key=value (Integer)]}
344+
* and a multiline {@code testFoo[3: multi\nline]}.
345+
*/
346+
@RunWith(value = Parameterized.class)
347+
public static class NamedParameterizedTest {
348+
349+
public NamedParameterizedTest(String data) {}
350+
351+
@Parameterized.Parameters(name = "{index}: {0}")
352+
public static Collection<Object[]> data() {
353+
Object[][] data =
354+
new Object[][] {{"a b"}, {"[1, 2]"}, {"key=value (Integer)"}, {"multi\nline"}};
355+
return Arrays.asList(data);
356+
}
357+
358+
@Test
359+
public void testFoo() {}
360+
361+
@Test
362+
public void testBar() {}
363+
}
364+
341365
/** Test fixture for verifying support for suite() methods */
342366
public static class JUnit3Suite {
343367
public static junit.framework.Test suite() {
@@ -1009,6 +1033,42 @@ public void testParameterizedMethods() throws Exception {
10091033
Assert.assertEquals(3, result.getRunCount());
10101034
}
10111035

1036+
/** Test including a parameterized method by root name with non-numeric parameter names. */
1037+
@Test
1038+
public void testNamedParameterizedMethods_include() {
1039+
Request request =
1040+
builder.addTestMethod(NamedParameterizedTest.class.getName(), "testFoo").build();
1041+
JUnitCore testRunner = new JUnitCore();
1042+
Result result = testRunner.run(request);
1043+
Assert.assertEquals(4, result.getRunCount());
1044+
}
1045+
1046+
/** Test excluding a parameterized method by root name with non-numeric parameter names. */
1047+
@Test
1048+
public void testNamedParameterizedMethods_exclude() {
1049+
Request request =
1050+
builder
1051+
.addTestClass(NamedParameterizedTest.class.getName())
1052+
.removeTestMethod(NamedParameterizedTest.class.getName(), "testFoo")
1053+
.build();
1054+
JUnitCore testRunner = new JUnitCore();
1055+
Result result = testRunner.run(request);
1056+
Assert.assertEquals(4, result.getRunCount());
1057+
}
1058+
1059+
/** Test including a single parameterized instance by its full name. */
1060+
@Test
1061+
public void testNamedParameterizedMethods_includeFullName() {
1062+
Request request =
1063+
builder
1064+
.addTestMethod(NamedParameterizedTest.class.getName(), "testFoo[1: [1, 2]]")
1065+
.addTestMethod(NamedParameterizedTest.class.getName(), "testBar[3: multi\nline]")
1066+
.build();
1067+
JUnitCore testRunner = new JUnitCore();
1068+
Result result = testRunner.run(request);
1069+
Assert.assertEquals(2, result.getRunCount());
1070+
}
1071+
10121072
/** Verify adding a class method and removing same class leaves no tests. */
10131073
@Test
10141074
public void testFilterClassAddMethod() {

0 commit comments

Comments
 (0)