Tool to generate test case info names and tags from suite.

Change-Id: I5c4e3bd2483ebda67641b5e90927b03140753efb
Signed-off-by: George Keishing <gkeishin@in.ibm.com>
diff --git a/bin/generate_testsuite_info.py b/bin/generate_testsuite_info.py
new file mode 100755
index 0000000..d14ca86
--- /dev/null
+++ b/bin/generate_testsuite_info.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+
+r"""
+Use robot framework API to extract test data from test suites.
+Refer to https://robot-framework.readthedocs.io/en/3.0.1/autodoc/robot.parsing.html
+"""
+
+import sys
+import os
+from robot.parsing.model import TestData
+sys.path.append(os.path.join(os.path.dirname(__file__), "../lib"))
+
+from gen_arg import *
+from gen_print import *
+from gen_valid import *
+
+# Set exit_on_error for gen_valid functions.
+set_exit_on_error(True)
+
+valid_options = ['name', 'tags', 'doc', 'all']
+
+parser = argparse.ArgumentParser(
+    usage='%(prog)s [OPTIONS]',
+    description=";%(prog)s will print test suite information to stdout. This \
+                  information consists of any and/or all of the following: \
+                  the suite name, test case names, tag names and doc strings. \
+                  Example for generated test case names \
+                  tests/test_basic_poweron.robot \
+                  Verify Front And Rear LED At Standby \
+                  Power On Test \
+                  Check For Application Failures \
+                  Verify Uptime Average Against Threshold \
+                  Test SSH And IPMI Connections",
+    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+    prefix_chars='-+')
+
+parser.add_argument(
+    '--source_path',
+    '-s',
+    help='The robot test file or directory path.')
+
+parser.add_argument(
+    '--option',
+    '-o',
+    default="name",
+    help='Test case attribute name.  This may be any one of the following:\n'
+    + sprint_var(valid_options))
+
+# Populate stock_list with options we want.
+stock_list = [("test_mode", 0), ("quiet", 0), ("debug", 0)]
+
+
+def exit_function(signal_number=0,
+                  frame=None):
+    r"""
+    Execute whenever the program ends normally or with the signals that we
+    catch (i.e. TERM, INT).
+    """
+
+    dprint_executing()
+
+    dprint_var(signal_number)
+
+    qprint_pgm_footer()
+
+
+def signal_handler(signal_number,
+                   frame):
+    r"""
+    Handle signals.  Without a function to catch a SIGTERM or SIGINT, the
+    program would terminate immediately with return code 143 and without
+    calling the exit_function.
+    """
+
+    # Our convention is to set up exit_function with atexit.register() so
+    # there is no need to explicitly call exit_function from here.
+
+    dprint_executing()
+
+    # Calling exit prevents us from returning to the code that was running
+    # when the signal was received.
+    exit(0)
+
+
+def validate_parms():
+    r"""
+    Validate program parameters, etc.  Return True or False (i.e. pass/fail)
+    accordingly.
+    """
+
+    valid_path(source_path)
+
+    valid_value(option, valid_values=valid_options)
+
+    gen_post_validation(exit_function, signal_handler)
+
+
+def parse_test_suites(source_path, option):
+    r"""
+    Parse the robot files and extract test data output.
+
+    Description of argument(s):
+    source_path   The path to a robot file or a directory of robot files.
+    option        Test case attribute instances such as "name",
+                  "tags" or "doc".
+    """
+    if os.path.isfile(source_path):
+        file_paths = [source_path]
+    else:
+        file_paths = [os.path.join(path, file)
+                      for (path, dirs, files) in os.walk(source_path)
+                      for file in files]
+
+    for file_path in file_paths:
+        print (file_path)
+        if "__init__.robot" in file_path:
+            continue
+        test_suite_obj = TestData(parent=None, source=file_path)
+        parse_test_file(test_suite_obj, option)
+
+
+def parse_test_file(test_suite_obj, option):
+    r"""
+    Extract test information from test suite object and print it to stdout in
+    the following format:
+
+    <Test Case name>
+    <Test Tags name>
+    <Test Documentation>
+
+    Description of argument(s):
+    test_suite_obj    Test data suite object.
+    option            Test case attribute instances such as "name",
+                      "tags" or "doc".
+    """
+
+    for testcase in test_suite_obj.testcase_table:
+        if option == "name":
+            print (testcase.name)
+        elif option == "tags":
+            print (testcase.tags)
+        elif option == "doc":
+            print (testcase.doc)
+        elif option == "all":
+            print (testcase.name)
+            print (testcase.tags)
+            print (testcase.doc)
+
+
+def main():
+
+    gen_get_options(parser, stock_list)
+
+    validate_parms()
+
+    qprint_pgm_header()
+
+    parse_test_suites(source_path, option)
+
+    return True
+
+
+# Main
+main()