Python Library Unittest
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

test.py 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. import logging
  5. logger = logging.getLogger('__unittest__')
  6. REPORT_LEVEL_FAIL = logging.ERROR
  7. REPORT_LEVEL_INSPECT = logging.WARNING
  8. REPORT_LEVEL_PASS = logging.INFO
  9. def __get_repr__(value, data_filter=repr):
  10. if type(value) == dict:
  11. return '{ ' + ', '.join(['%s: %s' % (repr(key), __get_repr__(value.get(key))) for key in value.keys()]) + ' }'
  12. elif type(value) == list:
  13. return '[ ' + ', '.join(['%s' % (__get_repr__(v)) for v in value]) + ' ]'
  14. else:
  15. return data_filter(value)
  16. def __report_result__(result, description, data_filter=repr):
  17. logger.debug('Result (%s): %s (%s)', description, __get_repr__(result, data_filter), repr(type(result)))
  18. def __report_expectation__(compare, expectation, description, data_filter=repr):
  19. logger.debug('Expectation (%s): result %s %s (%s)', description, compare, __get_repr__(expectation, data_filter), repr(type(expectation)))
  20. def __report_expectation_equivalency__(expectation, description, data_filter=repr):
  21. __report_expectation__("=", expectation, description, data_filter=repr)
  22. def __report_expectation_greater__(expectation, description, data_filter=repr):
  23. __report_expectation__(">", expectation, description, data_filter=repr)
  24. def __report_expectation_less__(expectation, description, data_filter=repr):
  25. __report_expectation__("<", expectation, description, data_filter=repr)
  26. def __report_expectation_inlist__(expectation, description, data_filter=repr):
  27. logger.debug('Expectation (%s): %s in result', description, __get_repr__(expectation, data_filter))
  28. def __report_expectation_range__(min_expectation, max_expectation, description):
  29. logger.debug('Expectation (%s): %s <= result <= %s', description, __get_repr__(min_expectation), __get_repr__(max_expectation))
  30. def __equivalent_dict__(result, expectation, report_comment_fail=None, dict_key='test_variable'):
  31. result_keys = set(result.keys())
  32. expect_keys = set(expectation.keys())
  33. #
  34. log_lvl = REPORT_LEVEL_PASS
  35. #
  36. # missing elements
  37. #
  38. missing_keys = expect_keys - result_keys
  39. if len(missing_keys) > 0:
  40. logger.error('Missing key(s) in dict (%s): %s.' + report_comment_fail, dict_key, ', '.join(['%s' % repr(key) for key in missing_keys]))
  41. log_lvl = REPORT_LEVEL_FAIL
  42. #
  43. # odd elements
  44. #
  45. odd_keys = result_keys - expect_keys
  46. if len(odd_keys) > 0:
  47. logger.error('Odd key(s) in dict (%s): %s.' + report_comment_fail, dict_key, ', '.join(['%s' % repr(key) for key in odd_keys]))
  48. log_lvl = REPORT_LEVEL_FAIL
  49. #
  50. # differences
  51. #
  52. common_keys = result_keys - missing_keys - odd_keys
  53. for key in common_keys:
  54. ll = __equivalent__(result[key], expectation[key], report_comment_fail=report_comment_fail, dict_key=dict_key + ('.' if dict_key != '' else '') + str(key))
  55. if log_lvl < ll:
  56. log_lvl = ll
  57. return log_lvl
  58. def __equivalent_list__(result, expectation, report_comment_fail=None, list_key='test_variable'):
  59. _odd_ = []
  60. _result_ = result[:]
  61. e_index = list(range(0, len(expectation)))
  62. log_lvl = REPORT_LEVEL_PASS
  63. r = 0
  64. while len(_result_) > 0:
  65. value = _result_.pop(0)
  66. just_type_diff = None
  67. for e in e_index:
  68. ll = __equivalent__(value, expectation[e], None)
  69. if ll == REPORT_LEVEL_PASS:
  70. e_index.pop(e_index.index(e))
  71. break
  72. elif ll == REPORT_LEVEL_INSPECT:
  73. just_type_diff = e
  74. else:
  75. if just_type_diff is None:
  76. _odd_.append(value)
  77. else:
  78. log_lvl = __equivalent__(value, expectation[just_type_diff], report_comment_fail, dict_key='%s[%d]' % (list_key, r))
  79. e_index.pop(e_index.index(just_type_diff))
  80. r += 1
  81. #
  82. # missing elements
  83. #
  84. if len(e_index) > 0:
  85. logger.error('Missing value(s) in list (%s): %s.' + report_comment_fail, list_key, ', '.join(['%s' % repr(expectation[e]) for e in e_index]))
  86. log_lvl = REPORT_LEVEL_FAIL
  87. #
  88. # odd elements
  89. #
  90. if len(_odd_) > 0:
  91. logger.error('Odd value(s) in list (%s): %s.' + report_comment_fail, list_key, ', '.join(['%s' % repr(v) for v in _odd_]))
  92. log_lvl = REPORT_LEVEL_FAIL
  93. return log_lvl
  94. def __equivalent__(result, expectation, report_comment_fail=None, dict_key='test_variable'):
  95. report_comment_fail = (' ' + report_comment_fail) if report_comment_fail is not None else ''
  96. log_lvl = REPORT_LEVEL_PASS
  97. if type(result) == dict and type(expectation) == dict:
  98. ll = __equivalent_dict__(result, expectation, report_comment_fail, dict_key)
  99. if log_lvl < ll:
  100. log_lvl = ll
  101. elif type(result) == list and type(expectation) == list:
  102. ll = __equivalent_list__(result, expectation, report_comment_fail, dict_key)
  103. if log_lvl < ll:
  104. log_lvl = ll
  105. else:
  106. if result != expectation:
  107. log_lvl = REPORT_LEVEL_FAIL
  108. logger.error('Content %s is incorrect' + (' for %s' % dict_key if dict_key != '' else '') + '.' + report_comment_fail, __get_repr__(result))
  109. if type(result) != type(expectation):
  110. if log_lvl < REPORT_LEVEL_INSPECT:
  111. log_lvl = REPORT_LEVEL_INSPECT
  112. logger.warning('Type %s is NOT %s%s (%s). ' + report_comment_fail.strip() or '', __get_repr__(type(result)), __get_repr__(type(expectation)), (' for %s' % dict_key if dict_key != '' else ''), __get_repr__(result))
  113. return log_lvl
  114. def __less__(result, expectation, report_comment_fail=None, dict_key='test_variable'):
  115. report_comment_fail = (' ' + report_comment_fail) if report_comment_fail is not None else ''
  116. log_lvl = REPORT_LEVEL_PASS
  117. if result >= expectation:
  118. log_lvl = REPORT_LEVEL_FAIL
  119. logger.error('Content %s is incorrect' + (' for %s' % dict_key if dict_key != '' else '') + '.' + report_comment_fail, __get_repr__(result))
  120. if type(result) != type(expectation):
  121. if log_lvl < REPORT_LEVEL_INSPECT:
  122. log_lvl = REPORT_LEVEL_INSPECT
  123. logger.warning('Type %s is NOT %s%s (%s). ' + report_comment_fail.strip() or '', __get_repr__(type(result)),
  124. __get_repr__(type(expectation)), (' for %s' % dict_key if dict_key != '' else ''), __get_repr__(result))
  125. return log_lvl
  126. def __greater__(result, expectation, report_comment_fail=None, dict_key='test_variable'):
  127. report_comment_fail = (' ' + report_comment_fail) if report_comment_fail is not None else ''
  128. log_lvl = REPORT_LEVEL_PASS
  129. if result <= expectation:
  130. log_lvl = REPORT_LEVEL_FAIL
  131. logger.error('Content %s is incorrect' + (' for %s' % dict_key if dict_key != '' else '') + '.' + report_comment_fail, __get_repr__(result))
  132. if type(result) != type(expectation):
  133. if log_lvl < REPORT_LEVEL_INSPECT:
  134. log_lvl = REPORT_LEVEL_INSPECT
  135. logger.warning('Type %s is NOT %s%s (%s). ' + report_comment_fail.strip() or '', __get_repr__(type(result)),
  136. __get_repr__(type(expectation)), (' for %s' % dict_key if dict_key != '' else ''), __get_repr__(result))
  137. return log_lvl
  138. def equivalency_chk(result, expectation, tcl, description='Variable', report_comment_fail=None, data_filter=repr):
  139. """
  140. Routine to check values for equivalency inside a test run and report to a testCaseLogger.
  141. :param result: The result of a test execution of a module
  142. :type result: All types are supported
  143. :param expectation: The expected value (shall be equivalent to result)
  144. :type expectation: All types are supported
  145. :param description: A descrition of the result. It will be reported like "xxx is correct." Example: descrition="stringrepresentation created by modulename"
  146. :type description: str
  147. :param report_comment_fail: Comment for a failed Testexecution. Will be added in brakets after the Result-Text.
  148. :type report_comment_fail: str
  149. """
  150. __report_result__(result, description, data_filter=data_filter)
  151. __report_expectation_equivalency__(expectation, description, data_filter=data_filter)
  152. report_level = __equivalent__(result, expectation, report_comment_fail=report_comment_fail, dict_key='result')
  153. if report_level == REPORT_LEVEL_PASS:
  154. tcl.log(report_level, description + ' is correct (Content %s and Type is %s).', data_filter(result), repr(type(result)))
  155. else:
  156. tcl.log(report_level, description + ' is NOT correct. See detailed log for more information.')
  157. return report_level
  158. def less_chk(result, expectation, tcl, description='Variable', report_comment_fail=None, data_filter=repr):
  159. """
  160. Routine to check result > expectation inside a test run and report to a testCaseLogger.
  161. :param result: The result of a test execution of a module
  162. :type result: All types are supported
  163. :param expectation: The expected value (shall be equivalent to result)
  164. :type expectation: All types are supported
  165. :param description: A descrition of the result. It will be reported like "xxx is correct." Example: descrition="stringrepresentation created by modulename"
  166. :type description: str
  167. :param report_comment_fail: Comment for a failed Testexecution. Will be added in brakets after the Result-Text.
  168. :type report_comment_fail: str
  169. """
  170. __report_result__(result, description, data_filter=data_filter)
  171. __report_expectation_less__(expectation, description, data_filter=data_filter)
  172. report_level = __less__(result, expectation, report_comment_fail=report_comment_fail, dict_key='result')
  173. if report_level == REPORT_LEVEL_PASS:
  174. tcl.log(report_level, description + ' is greater expectation (Content %s and Type is %s).', data_filter(result), repr(type(result)))
  175. else:
  176. tcl.log(report_level, description + ' is NOT correct. See detailed log for more information.')
  177. return report_level
  178. def greater_chk(result, expectation, tcl, description='Variable', report_comment_fail=None, data_filter=repr):
  179. """
  180. Routine to check result > expectation inside a test run and report to a testCaseLogger.
  181. :param result: The result of a test execution of a module
  182. :type result: All types are supported
  183. :param expectation: The expected value (shall be equivalent to result)
  184. :type expectation: All types are supported
  185. :param description: A descrition of the result. It will be reported like "xxx is correct." Example: descrition="stringrepresentation created by modulename"
  186. :type description: str
  187. :param report_comment_fail: Comment for a failed Testexecution. Will be added in brakets after the Result-Text.
  188. :type report_comment_fail: str
  189. """
  190. __report_result__(result, description, data_filter=data_filter)
  191. __report_expectation_greater__(expectation, description, data_filter=data_filter)
  192. report_level = __greater__(result, expectation, report_comment_fail=report_comment_fail, dict_key='result')
  193. if report_level == REPORT_LEVEL_PASS:
  194. tcl.log(report_level, description + ' is greater expectation (Content %s and Type is %s).', data_filter(result), repr(type(result)))
  195. else:
  196. tcl.log(report_level, description + ' is NOT correct. See detailed log for more information.')
  197. return report_level
  198. class equivalency_order_chk(object):
  199. def __init__(self, ordered_values, tcl, description='Variable', report_comment_fail=None):
  200. self._expected_values = ordered_values
  201. self._tcl = tcl
  202. self._description = description
  203. self._report_comment_fail = report_comment_fail
  204. self._reported_values = []
  205. def report_value(self, value):
  206. self._reported_values.append(value)
  207. def report(self):
  208. __report_result__(self._reported_values, self._description)
  209. __report_expectation_equivalency__(self._expected_values, self._description)
  210. report_lvl = REPORT_LEVEL_PASS
  211. for i in range(0, min(len(self._expected_values), len(self._reported_values))):
  212. report_lvl = max(report_lvl, equivalency_chk(self._reported_values[i], self._expected_values[i], logger, 'Submitted value number %d' % (i + 1), self._report_comment_fail))
  213. if report_lvl <= REPORT_LEVEL_PASS:
  214. self._tcl.log(report_lvl, self._description + ': Values and number of submitted values is correct. See detailed log for more information.')
  215. else:
  216. self._tcl.log(report_lvl, self._description + ': Values and number of submitted values is NOT correct. See detailed log for more information.')
  217. return report_lvl
  218. def report_range_check(self, minus_tollerance, plus_tollerance):
  219. __report_result__(self._reported_values, self._description)
  220. report_lvl = REPORT_LEVEL_PASS
  221. report_lvl = max(report_lvl, equivalency_chk(len(self._reported_values), len(self._reported_values), self._tcl, 'Number of submitted values', self._report_comment_fail))
  222. for i in range(0, min(len(self._expected_values), len(self._reported_values))):
  223. report_lvl = max(report_lvl, range_chk(self._reported_values[i], self._expected_values[i] - minus_tollerance, self._expected_values[i] + plus_tollerance, logger, 'Submitted value number %d' % (i + 1), self._report_comment_fail))
  224. if report_lvl <= REPORT_LEVEL_PASS:
  225. self._tcl.log(report_lvl, self._description + ': Valueaccuracy and number of submitted values is correct. See detailed log for more information.')
  226. else:
  227. self._tcl.log(report_lvl, self._description + ': Valueaccuracy and number of submitted values is NOT correct. See detailed log for more information.')
  228. return report_lvl
  229. def __range__(result, min_expectation, max_expectation, report_comment_fail):
  230. report_comment_fail = (' ' + report_comment_fail) if report_comment_fail is not None else ''
  231. log_lvl = REPORT_LEVEL_PASS
  232. if result < min_expectation or result > max_expectation:
  233. log_lvl = REPORT_LEVEL_FAIL
  234. logger.error('Content %s is incorrect.' + report_comment_fail, __get_repr__(result))
  235. if type(result) != type(min_expectation) or type(result) != type(max_expectation):
  236. if log_lvl < REPORT_LEVEL_INSPECT:
  237. log_lvl = REPORT_LEVEL_INSPECT
  238. logger.warning('Type %s is incorrect.' + report_comment_fail, __get_repr__(type(result)))
  239. return log_lvl
  240. def range_chk(result, min_expectation, max_expectation, tcl, description='Value', report_comment_fail=None):
  241. """
  242. Routine to check values to be in a range inside a test run and report to a testCaseLogger.
  243. :param result: The result of a test execution of a module
  244. :type result: All numeric types are supported
  245. :param min: The result shall be more or equal
  246. :type min: All numeric types are supported
  247. :param max: The result shall be less or equivalent
  248. :type max: All numeric types are supported
  249. :param description: A descrition of the result. It will be reported like "xxx is correct." Example: descrition="stringrepresentation created by modulename"
  250. :type description: str
  251. :param report_level_pass: The reporting level as defined in :class:`logging` (e.g.: logging.INFO)
  252. :param report_level_fail: The reporting level as defined in :class:`logging` (e.g.: logging.ERROR)
  253. :param report_comment_fail: Comment for a failed Testexecution. Will be added in brakets after the Result-Text.
  254. :type report_comment_fail: str
  255. """
  256. __report_result__(result, description)
  257. __report_expectation_range__(min_expectation, max_expectation, description)
  258. report_level = __range__(result, min_expectation, max_expectation, report_comment_fail=report_comment_fail)
  259. if report_level == REPORT_LEVEL_PASS:
  260. tcl.log(report_level, description + ' is correct (Content %s in [%s ... %s] and Type is %s).', repr(result), repr(min_expectation), repr(max_expectation), repr(type(result)))
  261. else:
  262. tcl.log(report_level, description + ' is NOT correct. See detailed log for more information.')
  263. return report_level
  264. def in_list_dict_chk(result_list, expectation_key, tcl, description='Value', report_comment_fail=None, data_filter=repr):
  265. """
  266. Routine to check values to be in a range inside a test run and report to a testCaseLogger.
  267. :param result_key: The result of a test execution of a module
  268. :type result_key: All types are supported
  269. :param expectation_list: The list or dict of allowed values
  270. :type expectation_list: A list of all types or a dict is supported
  271. :param description: A descrition of the result. It will be reported like "xxx is correct." Example: descrition="stringrepresentation created by modulename"
  272. :type description: str
  273. :param report_comment_fail: Comment for a failed Testexecution. Will be added in brakets after the Result-Text.
  274. :type report_comment_fail: str
  275. """
  276. __report_result__(result_list, description)
  277. __report_expectation_inlist__(expectation_key, description, data_filter=data_filter)
  278. if expectation_key in result_list:
  279. tcl.log(REPORT_LEVEL_PASS, description + ' is correct (%s is in the list or dict).', data_filter(expectation_key))
  280. return REPORT_LEVEL_PASS
  281. else:
  282. tcl.log(REPORT_LEVEL_FAIL, description + ' is NOT correct (%s is NOT in the list or dict).', data_filter(expectation_key))
  283. return REPORT_LEVEL_FAIL