Accept multiple parameters for parameterized tests
Previously Atest only splits test name and methods with comma, which
leads unexpected parsing result when giving is multiple parameters like
test_method1[[2,3],15],test_method2[2,3],test_method[0]
This change resolves the parsing problem.
Bug: 260183137
Test: atest com.google.android.camera.pts.MultiCamera2022Test#testBasicPhysicalCameraPairConcurrentStreaming[[2,3],37]
Change-Id: Iccbd8dc3fb4a3093e248e22d122a72c91a535c7c
diff --git a/atest/atest_error.py b/atest/atest_error.py
index 7ab8b5f..30afad3 100644
--- a/atest/atest_error.py
+++ b/atest/atest_error.py
@@ -35,6 +35,9 @@
class TooManyMethodsError(TestDiscoveryException):
"""Raised when input string contains more than one # character."""
+class MoreThanOneClassError(TestDiscoveryException):
+ """Raised when multiple classes given in 'classA,classB' pattern."""
+
class MethodWithoutClassError(TestDiscoveryException):
"""Raised when method is appended via # but no class file specified."""
diff --git a/atest/test_finders/test_finder_utils.py b/atest/test_finders/test_finder_utils.py
index 2be0261..3e56959 100644
--- a/atest/test_finders/test_finder_utils.py
+++ b/atest/test_finders/test_finder_utils.py
@@ -173,7 +173,6 @@
_VTS_BINARY_SRC_DELIM_RE = re.compile(r'.*::(?P<target>.*)$')
_VTS_OUT_DATA_APP_PATH = 'DATA/app'
-# pylint: disable=inconsistent-return-statements
def split_methods(user_input):
"""Split user input string into test reference and list of methods.
@@ -196,16 +195,39 @@
class1#method,class2#method
path1#method,path2#method
"""
+ error_msg = (
+ 'Too many "{}" characters in user input:\n\t{}\n'
+ 'Multiple classes should be separated by space, and methods belong to '
+ 'the same class should be separated by comma. Example syntaxes are:\n'
+ '\tclass1 class2#method1 class3#method2,method3\n'
+ '\tclass1#method class2#method')
+ if not '#' in user_input:
+ if ',' in user_input:
+ raise atest_error.MoreThanOneClassError(
+ error_msg.format(',', user_input))
+ return user_input, frozenset()
parts = user_input.split('#')
- if len(parts) == 1:
- return parts[0], frozenset()
- if len(parts) == 2:
- return parts[0], frozenset(parts[1].split(','))
- raise atest_error.TooManyMethodsError(
- 'Too many methods specified with # character in user input: %s.'
- '\n\nOnly one class#method combination supported per positional'
- ' argument. Multiple classes should be separated by spaces: '
- 'class#method class#method')
+ if len(parts) > 2:
+ raise atest_error.TooManyMethodsError(
+ error_msg.format('#', user_input))
+ # (b/260183137) Support parsing multiple parameters.
+ parsed_methods = []
+ brackets = ('[', ']')
+ for part in parts[1].split(','):
+ count = {part.count(p) for p in brackets}
+ # If brackets are in pair, the length of count should be 1.
+ if len(count) == 1:
+ parsed_methods.append(part)
+ else:
+ # The front part of the pair, e.g. 'method[1'
+ if re.compile(r'^[a-zA-Z0-9]+\[').match(part):
+ parsed_methods.append(part)
+ continue
+ # The rear part of the pair, e.g. '5]]', accumulate this part to
+ # the last index of parsed_method.
+ else:
+ parsed_methods[-1] += f',{part}'
+ return parts[0], frozenset(parsed_methods)
# pylint: disable=inconsistent-return-statements
diff --git a/atest/test_finders/test_finder_utils_unittest.py b/atest/test_finders/test_finder_utils_unittest.py
index 96bd7e4..193be76 100755
--- a/atest/test_finders/test_finder_utils_unittest.py
+++ b/atest/test_finders/test_finder_utils_unittest.py
@@ -129,6 +129,10 @@
self.assertRaises(
atest_error.TooManyMethodsError, test_finder_utils.split_methods,
'class.name#Method,class.name.2#method')
+ self.assertRaises(
+ atest_error.MoreThanOneClassError, test_finder_utils.split_methods,
+ 'class.name1,class.name2,class.name3'
+ )
# Path
unittest_utils.assert_strict_equal(
self,
@@ -138,6 +142,11 @@
self,
test_finder_utils.split_methods('foo/bar/class.java#Method'),
('foo/bar/class.java', {'Method'}))
+ # Multiple parameters
+ unittest_utils.assert_strict_equal(
+ self,
+ test_finder_utils.split_methods('Class.Name#method[1],method[2,[3,4]]'),
+ ('Class.Name', {'method[1]', 'method[2,[3,4]]'}))
@mock.patch.object(test_finder_utils, 'has_method_in_file',
return_value=False)