run_requirement.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. #!/usr/bin/python3
  2. #
  3. # Copyright (C) 2019 Intel Corporation. All rights reserved.
  4. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  5. #
  6. import os
  7. import sys
  8. import argparse
  9. from typing import Dict, Tuple, List
  10. import importlib
  11. import inspect
  12. import csv
  13. REQUIREMENT_TESTS_DIR = "../../requirement-engineering"
  14. SUBREQUIREMENT_DESCRIPTIONS = {}
  15. # To use this empty function to do signature check
  16. def expected_build_func_template(verbose: bool) -> None:
  17. pass
  18. # To use this empty function to do signature check
  19. # The actual implementation of the return value should has following information:
  20. #
  21. def expected_run_func_template(
  22. output_dir: str, subrequirement_ids: List[int]
  23. ) -> Dict[int, Dict[Tuple[str, str], bool]]:
  24. pass
  25. def dynamic_import(requirement_dir: str):
  26. # Declare that we intend to modify the global variable
  27. global SUBREQUIREMENT_DESCRIPTIONS
  28. sys.path.append(requirement_dir)
  29. os.chdir(requirement_dir)
  30. try:
  31. build_module = importlib.import_module("build")
  32. build_function = getattr(build_module, "build")
  33. except AttributeError:
  34. raise ImportError("'build' function not found in the specified build.py file.")
  35. try:
  36. run_module = importlib.import_module("run")
  37. run_function = getattr(run_module, "run")
  38. SUBREQUIREMENT_DESCRIPTIONS = getattr(run_module, "SUBREQUIREMENT_DESCRIPTIONS")
  39. except AttributeError:
  40. raise ImportError(
  41. "'run' function or 'SUBREQUIREMENT_DESCRIPTIONS' not found in the specified run.py file."
  42. )
  43. # Do signature check
  44. expected_signature = inspect.signature(expected_build_func_template)
  45. actual_signature = inspect.signature(build_function)
  46. assert (
  47. actual_signature == expected_signature
  48. ), "The build function doesn't have the expected signature"
  49. expected_signature = inspect.signature(expected_run_func_template)
  50. actual_signature = inspect.signature(run_function)
  51. assert (
  52. actual_signature == expected_signature
  53. ), "The run function doesn't have the expected signature"
  54. # Check if the variable is a dictionary
  55. if not isinstance(SUBREQUIREMENT_DESCRIPTIONS, dict):
  56. raise TypeError("SUBREQUIREMENT_DESCRIPTIONS is not a dictionary")
  57. # Check the types of keys and values in the dictionary
  58. for key, value in SUBREQUIREMENT_DESCRIPTIONS.items():
  59. if not isinstance(key, int):
  60. raise TypeError("Key in SUBREQUIREMENT_DESCRIPTIONS is not an int")
  61. if not (
  62. isinstance(value, tuple)
  63. and len(value) == 2
  64. and all(isinstance(elem, str) for elem in value)
  65. ):
  66. raise TypeError(
  67. "Value in SUBREQUIREMENT_DESCRIPTIONS is not a Tuple[str, str]"
  68. )
  69. return build_function, run_function
  70. def cmd_line_summary(
  71. requirement_name: str, result_dict: dict, subrequirement_descriptions: dict
  72. ):
  73. # command line summary
  74. total, total_pass_nums, total_fail_nums = 0, 0, 0
  75. print(f"\n============ Start: Summary of {requirement_name} test ============")
  76. for subrequirement_id in result_dict.keys():
  77. sub_total = len(result_dict[subrequirement_id])
  78. pass_nums = len(
  79. [_ for _, result in result_dict[subrequirement_id].items() if result]
  80. )
  81. fail_nums = len(
  82. [_ for _, result in result_dict[subrequirement_id].items() if not result]
  83. )
  84. issue_number, subrequirement_description = subrequirement_descriptions.get(
  85. subrequirement_id, ""
  86. )
  87. print(f"\nTest Sub-requirement id: {subrequirement_id}")
  88. print(f"Issue Number: {issue_number}")
  89. print(f"Sub-requirement description: {subrequirement_description}")
  90. print(f"Number of test cases: {sub_total}")
  91. print(f"Pass: {pass_nums}")
  92. print(f"Fail: {fail_nums}\n")
  93. print(
  94. "----------------------------------------------------------------------------"
  95. )
  96. total += sub_total
  97. total_pass_nums += pass_nums
  98. total_fail_nums += fail_nums
  99. print(f"\nTotal Number of test cases: {total}")
  100. print(f"Pass: {total_pass_nums}")
  101. print(f"Fail: {total_fail_nums}\n")
  102. print(f"============= End: Summary of {requirement_name} test =============\n")
  103. def generate_report(output_filename: str, result_dict: dict):
  104. # create a list of column names
  105. column_names = [
  106. "subrequirement id",
  107. "issue number",
  108. "subrequirement description",
  109. "running mode",
  110. "test case name",
  111. "test case description",
  112. "test case executing result",
  113. ]
  114. # open the output file in write mode
  115. with open(output_filename + ".csv", "w") as output_file:
  116. # create a csv writer object
  117. csv_writer = csv.writer(output_file)
  118. # write the column names as the first row
  119. csv_writer.writerow(column_names)
  120. # loop through the result_dict
  121. for subrequirement_id, test_cases in result_dict.items():
  122. # get the subrequirement description from the subrequirement_descriptions dict
  123. issue_number, subrequirement_description = SUBREQUIREMENT_DESCRIPTIONS.get(
  124. subrequirement_id, ""
  125. )
  126. # loop through the test cases
  127. for test_case, result in test_cases.items():
  128. # unpack the test case name and description from the tuple
  129. test_case_name, test_case_description = test_case
  130. # convert the result to pass or fail
  131. result = "pass" if result else "fail"
  132. # create a list of values for the current row
  133. row_values = [
  134. subrequirement_id,
  135. issue_number,
  136. subrequirement_description,
  137. "AOT",
  138. test_case_name,
  139. test_case_description,
  140. result,
  141. ]
  142. # write the row values to the output file
  143. csv_writer.writerow(row_values)
  144. def run_requirement(
  145. requirement_name: str, output_dir: str, subrequirement_ids: List[int]
  146. ):
  147. requirement_dir = os.path.join(REQUIREMENT_TESTS_DIR, requirement_name)
  148. if not os.path.isdir(requirement_dir):
  149. print(f"No such requirement in directory {requirement_dir} exists")
  150. sys.exit(1)
  151. output_path = os.path.join(output_dir, requirement_name)
  152. build_requirement_func, run_requirement_func = dynamic_import(requirement_dir)
  153. build_requirement_func(verbose=False)
  154. result_dict = run_requirement_func(output_path, subrequirement_ids)
  155. cmd_line_summary(requirement_name, result_dict, SUBREQUIREMENT_DESCRIPTIONS)
  156. generate_report(output_path, result_dict)
  157. def main():
  158. parser = argparse.ArgumentParser(description="Process command line options.")
  159. # Define the '-o' option for output directory
  160. parser.add_argument(
  161. "-o", "--output_directory", required=True, help="Report output directory"
  162. )
  163. # Define the '-r' option for requirement name
  164. parser.add_argument(
  165. "-r", "--requirement_name", required=True, help="Requirement name"
  166. )
  167. # Define the subrequirement IDs as a list of integers
  168. parser.add_argument(
  169. "subrequirement_ids", nargs="*", type=int, help="Subrequirement IDs (optional)"
  170. )
  171. # Parse the arguments
  172. args = parser.parse_args()
  173. run_requirement(
  174. args.requirement_name, args.output_directory, list(args.subrequirement_ids)
  175. )
  176. if __name__ == "__main__":
  177. main()