xref: /openbmc/openbmc-test-automation/bin/generate_testsuite_info.py (revision 8e8654854aaedac64562bae86dbac6c276339457)
1#!/usr/bin/env python3
2
3r"""
4Use robot framework API to extract test data from test suites.
5Refer to https://robot-framework.readthedocs.io/en/latest/autodoc/robot.running.html
6"""
7
8import os
9import sys
10
11from robot.api import SuiteVisitor, TestSuiteBuilder
12
13sys.path.append(os.path.join(os.path.dirname(__file__), "../lib"))
14
15from gen_arg import *  # NOQA
16from gen_print import *  # NOQA
17from gen_valid import *  # NOQA
18
19# Set exit_on_error for gen_valid functions.
20set_exit_on_error(True)
21
22valid_options = ["name", "tags", "doc", "all"]
23
24parser = argparse.ArgumentParser(
25    usage="%(prog)s [OPTIONS]",
26    description=(
27        ";%(prog)s will print test suite information to stdout. This          "
28        "         information consists of any and/or all of the following:    "
29        "               the suite name, test case names, tag names and doc"
30        " strings.                   Example for generated test case names    "
31        "               tests/test_basic_poweron.robot                  "
32        " Verify Front And Rear LED At Standby                   Power On Test"
33        "                   Check For Application Failures                  "
34        " Verify Uptime Average Against Threshold                   Test SSH"
35        " And IPMI Connections"
36    ),
37    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
38    prefix_chars="-+",
39)
40
41parser.add_argument(
42    "--source_path", "-s", help="The robot test file or directory path."
43)
44
45parser.add_argument(
46    "--option",
47    "-o",
48    default="name",
49    help="Test case attribute name.  This may be any one of the following:\n"
50    + sprint_var(valid_options),
51)
52
53# Populate stock_list with options we want.
54stock_list = [("test_mode", 0), ("quiet", 0), ("debug", 0)]
55
56
57class TestPrint(SuiteVisitor):
58
59    def __init__(self, option):
60        self.option = option
61
62    def visit_test(self, test):
63        r"""
64        Print the test data from suite test object from option specified.
65        """
66        if self.option == "name":
67            print(test.name)
68        elif self.option == "tags":
69            print(test.tags)
70        elif self.option == "doc":
71            print(test.doc)
72        elif self.option == "all":
73            print(test.name)
74            print(test.tags)
75            print(test.doc)
76
77
78def exit_function(signal_number=0, frame=None):
79    r"""
80    Execute whenever the program ends normally or with the signals that we
81    catch (i.e. TERM, INT).
82    """
83
84    dprint_executing()
85
86    dprint_var(signal_number)
87
88    qprint_pgm_footer()
89
90
91def signal_handler(signal_number, frame):
92    r"""
93    Handle signals.  Without a function to catch a SIGTERM or SIGINT, the
94    program would terminate immediately with return code 143 and without
95    calling the exit_function.
96    """
97
98    # Our convention is to set up exit_function with atexit.register() so
99    # there is no need to explicitly call exit_function from here.
100
101    dprint_executing()
102
103    # Calling exit prevents us from returning to the code that was running
104    # when the signal was received.
105    exit(0)
106
107
108def validate_parms():
109    r"""
110    Validate program parameters, etc.  Return True or False (i.e. pass/fail)
111    accordingly.
112    """
113
114    valid_path(source_path)
115
116    valid_value(option, valid_values=valid_options)
117
118    gen_post_validation(exit_function, signal_handler)
119
120
121def parse_test_suites(source_path, option):
122    r"""
123    Parse the robot files and extract test data output.
124
125    Description of argument(s):
126    source_path   The path to a robot file or a directory of robot files.
127    option        Test case attribute instances such as "name",
128                  "tags" or "doc".
129    """
130    if os.path.isfile(source_path):
131        file_paths = [source_path]
132    else:
133        file_paths = [
134            os.path.join(path, file)
135            for (path, dirs, files) in os.walk(source_path)
136            for file in files
137        ]
138
139    for file_path in file_paths:
140        print(file_path)
141        if "__init__.robot" in file_path:
142            continue
143        test_suite_obj = TestSuiteBuilder().build(file_path)
144        parse_test_file(test_suite_obj, option)
145
146
147def parse_test_file(test_suite_obj, option):
148    r"""
149    Extract test information from test suite object and print it to stdout in
150    the following format:
151
152    <Test Case name>
153    <Test Tags name>
154    <Test Documentation>
155
156    Description of argument(s):
157    test_suite_obj    Test data suite object.
158    option            Test case attribute instances such as "name",
159                      "tags" or "doc".
160    """
161
162    test_suite_obj.visit(TestPrint(option))
163
164
165def main():
166    gen_get_options(parser, stock_list)
167
168    validate_parms()
169
170    qprint_pgm_header()
171
172    parse_test_suites(source_path, option)
173
174    return True
175
176
177# Main
178main()
179