Here is a solution that could be further improved based on exact requirements. The steps:
- Create a
--name-only
git diff and filter out the files that do not contain test cases. This is done by the get_changed_robot_files
function.
- Next step is to retrieve all test cases names from the collected files. This is done by the
get_list_of_all_tests_in_files
function which parses the .robot files recursively using the collect_tests_from_suite
function. This utilizes Robot Framework API so you do not have to reinvent the wheel here.
- Get a full git diff and check which test cases are present in it. This is done with
get_changed_tests
. Now this is not 100% accurate some test cases will show up that has not been changed but the ones that have been change will be included. You can improve the diff analysis if needed. This gave the best results with the least effort right now.
- Last step is to launch the affected tests utilizing the
robot.run.run_cli(arguments=None, exit=True)
Robot Framework API call in run_changed_tests
.
import subprocess
import os
from robot.api import TestData
from robot import run_cli
def collect_tests_from_suite(suite, tests):
for test in suite.testcase_table:
tests.append(test.name)
for child in suite.children:
collect_tests_from_suite(child, tests)
def get_changed_robot_files():
result = subprocess.run(["git", "diff", "--name-only", "HEAD~1", "HEAD"], capture_output=True, text=True)
files = result.stdout
return [f for f in files.split('
') if ('.robot' in f) and ('__init__' not in f)]
def get_git_diff():
result = subprocess.run(["git", "diff", "HEAD~1", "HEAD", '--unified=0'], capture_output=True, text=True)
return result.stdout
def get_list_of_all_tests_in_files(files):
tests = []
for f in files:
suite = TestData(source=f)
collect_tests_from_suite(suite, tests)
return tests
def get_changed_tests(tests):
list_of_changed_tests = []
diff = get_git_diff()
for test in tests:
if test in diff:
list_of_changed_tests.append(test)
return list_of_changed_tests
def run_changed_tests(tests):
args = []
for test in tests:
args.append('--test')
args.append(test)
args.append('.')
rc = run_cli(args, exit=False)
# -------------------------------------------------- #
files = get_changed_robot_files()
tests = get_list_of_all_tests_in_files(files)
changed_tests = get_changed_tests(tests)
print(f'Files changed: {len(files)}')
print(f'Tests found: {len(tests)}')
print(f'Tests changed: {len(changed_tests)}')
run_changed_tests(changed_tests)
Improvement ideas:
- Detect changed
__init__.robot
files and execute every suite below them.
- Detect changed
.resource
files and execute every .robot
file that imports them.
- Improve diff parsing to exclude unchanged test cases.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…