TinyFW.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. # Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http:#www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """ Interface for test cases. """
  15. import sys
  16. import os
  17. import time
  18. import traceback
  19. import inspect
  20. import functools
  21. import xunitgen
  22. import Env
  23. import DUT
  24. import App
  25. import Utility
  26. XUNIT_FILE_NAME = "XUNIT_RESULT.xml"
  27. XUNIT_RECEIVER = xunitgen.EventReceiver()
  28. XUNIT_DEFAULT_TEST_SUITE = "test-suite"
  29. class DefaultEnvConfig(object):
  30. """
  31. default test configs. There're 3 places to set configs, priority is (high -> low):
  32. 1. overwrite set by caller of test method
  33. 2. values set by test_method decorator
  34. 3. default env config get from this class
  35. """
  36. DEFAULT_CONFIG = {
  37. "app": App.BaseApp,
  38. "dut": DUT.BaseDUT,
  39. "env_tag": "default",
  40. "env_config_file": None,
  41. "test_suite_name": None,
  42. }
  43. @classmethod
  44. def set_default_config(cls, **kwargs):
  45. """
  46. :param kwargs: configs need to be updated
  47. :return: None
  48. """
  49. cls.DEFAULT_CONFIG.update(kwargs)
  50. @classmethod
  51. def get_default_config(cls):
  52. """
  53. :return: current default config
  54. """
  55. return cls.DEFAULT_CONFIG.copy()
  56. set_default_config = DefaultEnvConfig.set_default_config
  57. get_default_config = DefaultEnvConfig.get_default_config
  58. class TestResult(object):
  59. TEST_RESULT = {
  60. "pass": [],
  61. "fail": [],
  62. }
  63. @classmethod
  64. def get_failed_cases(cls):
  65. """
  66. :return: failed test cases
  67. """
  68. return cls.TEST_RESULT["fail"]
  69. @classmethod
  70. def get_passed_cases(cls):
  71. """
  72. :return: passed test cases
  73. """
  74. return cls.TEST_RESULT["pass"]
  75. @classmethod
  76. def set_result(cls, result, case_name):
  77. """
  78. :param result: True or False
  79. :param case_name: test case name
  80. :return: None
  81. """
  82. cls.TEST_RESULT["pass" if result else "fail"].append(case_name)
  83. get_failed_cases = TestResult.get_failed_cases
  84. get_passed_cases = TestResult.get_passed_cases
  85. MANDATORY_INFO = {
  86. "execution_time": 1,
  87. "env_tag": "default",
  88. }
  89. def test_method(**kwargs):
  90. """
  91. decorator for test case function.
  92. The following keyword arguments are pre-defined.
  93. Any other keyword arguments will be regarded as filter for the test case,
  94. able to access them by ``case_info`` attribute of test method.
  95. :keyword app: class for test app. see :doc:`App <App>` for details
  96. :keyword dut: class for current dut. see :doc:`DUT <DUT>` for details
  97. :keyword env_tag: name for test environment, used to select configs from config file
  98. :keyword env_config_file: test env config file. usually will not set this keyword when define case
  99. :keyword test_suite_name: test suite name, used for generating log folder name and adding xunit format test result.
  100. usually will not set this keyword when define case
  101. """
  102. def test(test_func):
  103. # get test function file name
  104. frame = inspect.stack()
  105. test_func_file_name = frame[1][1]
  106. case_info = MANDATORY_INFO.copy()
  107. case_info["name"] = test_func.__name__
  108. case_info.update(kwargs)
  109. # create env instance
  110. env_config = DefaultEnvConfig.get_default_config()
  111. for key in kwargs:
  112. if key in env_config:
  113. env_config[key] = kwargs[key]
  114. @functools.wraps(test_func)
  115. def handle_test(extra_data=None, **overwrite):
  116. """
  117. create env, run test and record test results
  118. :param extra_data: extra data that runner or main passed to test case
  119. :param overwrite: args that runner or main want to overwrite
  120. :return: None
  121. """
  122. env_config.update(overwrite)
  123. env_inst = Env.Env(**env_config)
  124. # prepare for xunit test results
  125. xunit_file = os.path.join(env_inst.app_cls.get_log_folder(env_config["test_suite_name"]),
  126. XUNIT_FILE_NAME)
  127. XUNIT_RECEIVER.begin_case(test_func.__name__, time.time(), test_func_file_name)
  128. try:
  129. Utility.console_log("starting running test: " + test_func.__name__, color="green")
  130. # execute test function
  131. test_func(env_inst, extra_data)
  132. # if finish without exception, test result is True
  133. result = True
  134. except Exception as e:
  135. # handle all the exceptions here
  136. traceback.print_exc()
  137. result = False
  138. # log failure
  139. XUNIT_RECEIVER.failure(str(e), test_func_file_name)
  140. finally:
  141. # do close all DUTs
  142. env_inst.close()
  143. # end case and output result
  144. XUNIT_RECEIVER.end_case(test_func.__name__, time.time())
  145. with open(xunit_file, "ab+") as f:
  146. f.write(xunitgen.toxml(XUNIT_RECEIVER.results(),
  147. XUNIT_DEFAULT_TEST_SUITE))
  148. if result:
  149. Utility.console_log("Test Succeed: " + test_func.__name__, color="green")
  150. else:
  151. Utility.console_log(("Test Fail: " + test_func.__name__), color="red")
  152. TestResult.set_result(result, test_func.__name__)
  153. return result
  154. handle_test.case_info = case_info
  155. handle_test.test_method = True
  156. return handle_test
  157. return test