diff --git a/launchable/test_runners/maven.py b/launchable/test_runners/maven.py index deb87ccf5..1c6ddd754 100644 --- a/launchable/test_runners/maven.py +++ b/launchable/test_runners/maven.py @@ -1,6 +1,7 @@ import glob import os -from typing import Dict, List, Optional +import re +from typing import Dict, List, Optional, Tuple import click @@ -60,9 +61,24 @@ def is_file(f: str) -> bool: is_flag=True, help="Scan testCompile/default-testCompile/createdFiles.lst for *.lst files generated by `mvn compile` and use them as test inputs.", # noqa: E501 ) +@click.option( + '--exclude', + 'exclude_rules', + required=False, + multiple=True, + help="Exclude tests matching the given Python regular expression pattern. Can be specified multiple times.", +) @click.argument('source_roots', required=False, nargs=-1) @launchable.subset -def subset(client, source_roots, test_compile_created_file, is_scan_test_compile_lst): +def subset(client, source_roots, test_compile_created_file, is_scan_test_compile_lst, exclude_rules: Tuple[str, ...]): + + # Compile exclude rules + compiled_exclude_rules = [] + for rule in exclude_rules: + try: + compiled_exclude_rules.append(re.compile(rule)) + except re.error as e: + raise click.BadParameter("Invalid regular expression '{}': {}".format(rule, e)) def file2class_test_path(f: str) -> List[Dict[str, str]]: # remove extension @@ -74,7 +90,13 @@ def file2class_test_path(f: str) -> List[Dict[str, str]]: def file2test(f: str) -> Optional[List]: if is_file(f): - return file2class_test_path(f) + test_path = file2class_test_path(f) + + for pattern in compiled_exclude_rules: + if pattern.search(test_path[0]["name"]): + return None + + return test_path else: return None diff --git a/tests/data/maven/java/test/src/java/com/launchableinc/rocket_car_maven/e2e/E2ETest.java b/tests/data/maven/java/test/src/java/com/launchableinc/rocket_car_maven/e2e/E2ETest.java new file mode 100644 index 000000000..e69de29bb diff --git a/tests/data/maven/subset_by_absolute_time_result.json b/tests/data/maven/subset_by_absolute_time_result.json index ae1326481..b3db4f46d 100644 --- a/tests/data/maven/subset_by_absolute_time_result.json +++ b/tests/data/maven/subset_by_absolute_time_result.json @@ -4,7 +4,10 @@ {"type": "class", "name": "com.launchableinc.rocket_car_maven.App2Test"} ], [ - { "type": "class", "name": "com.launchableinc.rocket_car_maven.AppTest"} + {"type": "class", "name": "com.launchableinc.rocket_car_maven.AppTest"} + ], + [ + {"type": "class", "name": "com.launchableinc.rocket_car_maven.e2e.E2ETest"} ]], "testRunner": "maven", "session": { diff --git a/tests/data/maven/subset_by_confidence_result.json b/tests/data/maven/subset_by_confidence_result.json index bd8a82506..631022342 100644 --- a/tests/data/maven/subset_by_confidence_result.json +++ b/tests/data/maven/subset_by_confidence_result.json @@ -4,7 +4,10 @@ {"type": "class", "name": "com.launchableinc.rocket_car_maven.App2Test"} ], [ - { "type": "class", "name": "com.launchableinc.rocket_car_maven.AppTest"} + {"type": "class", "name": "com.launchableinc.rocket_car_maven.AppTest"} + ], + [ + {"type": "class", "name": "com.launchableinc.rocket_car_maven.e2e.E2ETest"} ]], "testRunner": "maven", "session": { diff --git a/tests/data/maven/subset_result.json b/tests/data/maven/subset_result.json index 2b38e44f3..4f47aed85 100644 --- a/tests/data/maven/subset_result.json +++ b/tests/data/maven/subset_result.json @@ -4,7 +4,10 @@ {"type": "class", "name": "com.launchableinc.rocket_car_maven.App2Test"} ], [ - { "type": "class", "name": "com.launchableinc.rocket_car_maven.AppTest"} + {"type": "class", "name": "com.launchableinc.rocket_car_maven.AppTest"} + ], + [ + {"type": "class", "name": "com.launchableinc.rocket_car_maven.e2e.E2ETest"} ]], "testRunner": "maven", "goal": {"type": "subset-by-percentage", "percentage": 0.1}, diff --git a/tests/data/maven/subset_with_exclude_rules_result.json b/tests/data/maven/subset_with_exclude_rules_result.json new file mode 100644 index 000000000..f0ff6f5a8 --- /dev/null +++ b/tests/data/maven/subset_with_exclude_rules_result.json @@ -0,0 +1,17 @@ +{ + "testPaths": [ + [ + {"type": "class", "name": "com.launchableinc.rocket_car_maven.App2Test"} + ], + [ + {"type": "class", "name": "com.launchableinc.rocket_car_maven.AppTest"} + ]], + "testRunner": "maven", + "goal": {"type": "subset-by-percentage", "percentage": 0.1}, + "ignoreNewTests": false, + "session": { + "id": "16" + }, + "getTestsFromGuess": false, + "getTestsFromPreviousSessions": false +} diff --git a/tests/test_runners/test_maven.py b/tests/test_runners/test_maven.py index c61c413bd..aa6669e6a 100644 --- a/tests/test_runners/test_maven.py +++ b/tests/test_runners/test_maven.py @@ -208,6 +208,25 @@ def default_path_builder(case, suite, report_file): str(self.test_files_dir) + "/maven/reports/TEST-nested.xml") self.assert_success(result) + @responses.activate + @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) + def test_subset_with_exclude(self): + # Invalid regexp case + result = self.cli('subset', '--target', '10%', '--session', + self.session, 'maven', + '--exclude', r'[invalid', + str(self.test_files_dir.joinpath('java/test/src/java/').resolve())) + self.assertNotEqual(result.exit_code, 0) + self.assertIn("Invalid regular expression", result.output) + + # Success case + result = self.cli('subset', '--target', '10%', '--session', + self.session, 'maven', + '--exclude', r'\.e2e\.', + str(self.test_files_dir.joinpath('java/test/src/java/').resolve())) + self.assert_success(result) + self.assert_subset_payload('subset_with_exclude_rules_result.json') + def test_glob(self): for x in [ 'foo/BarTest.java',