Created
October 27, 2022 09:49
-
-
Save Tattoo/509fc564207fa99916fa6e6997bab838 to your computer and use it in GitHub Desktop.
Script to parse changed Robot Framework tests from git diff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
$ git diff --unified=0 path/to/robot | python differ.py | |
''' | |
import re | |
import sys | |
from collections import defaultdict | |
from pathlib import Path | |
from robot.api import SuiteVisitor, TestSuiteBuilder | |
CURDIR = Path.cwd() | |
def get_absolute_filepath(fp): | |
return CURDIR / fp | |
def parse(gitdiff): | |
changed_files = defaultdict(set) | |
current_suite_file = '' | |
test_case_name = '' | |
for line in gitdiff: | |
if line.startswith('+++'): | |
_, current_suite_file = line.split('b/', 1) | |
current_suite_file = get_absolute_filepath(current_suite_file.strip()) | |
continue | |
if line.startswith('@@'): | |
_, test_case_name = line.rsplit('@@', 1) | |
if re.match('^\+\w', line) != None: | |
test_case_name = line[1:] | |
changed_files[current_suite_file].add(test_case_name.strip()) | |
# if there is an entry where they key is empty string, remove it | |
changed_files.pop('') | |
return changed_files | |
def get_actual_tcs(filepaths): | |
class TestCaseExtractor(SuiteVisitor): | |
def __init__(self): | |
self.data = defaultdict(list) | |
def start_test(self, test): | |
self.data[Path(test.parent.source)].append(test.name) | |
extractor = TestCaseExtractor() | |
suites = [TestSuiteBuilder().build(fp) for fp in filepaths] | |
for s in suites: | |
s.visit(extractor) | |
return extractor.data | |
def filter_out_non_testcases(changed_files, actual_test_cases): | |
retval = {} | |
for suitepath, tests in changed_files.items(): | |
retval[suitepath] = [t for t in tests if t in actual_test_cases[suitepath]] | |
return retval | |
def format_(changed_files): | |
retval = [] | |
for changed_file, changed_tests in changed_files.items(): | |
suite_name = str(changed_file).replace(f'{CURDIR}/', '') | |
# needs to end in slash, otherwise suite_name is '/foo/bar' instead | |
# of 'foo/bar' | |
suite_name = suite_name.replace('/', '.') | |
suite_name, _ = suite_name.rsplit('.robot', 1) | |
for test in changed_tests: | |
t = test.replace(' ', '') | |
retval.append(f'--suite {suite_name} --test {t}') | |
return retval | |
def main(gitdiff): | |
changed_files = parse(gitdiff) | |
actual_test_cases = get_actual_tcs(changed_files.keys()) | |
changed_files = filter_out_non_testcases(changed_files, actual_test_cases) | |
robot_args = format_(changed_files) | |
print('\n'.join(robot_args)) | |
if __name__ == '__main__': | |
main(sys.stdin.readlines()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment