Python Library Unittest
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. import json
  5. import os
  6. import subprocess
  7. import fstools
  8. from unittest.output import STATUS_AVAILABLE, STATUS_CHANGED, STATUS_CLEAN, STATUS_EXISTS, STATUS_FAILED, STATUS_IN_WORK, STATUS_MISSING, STATUS_OLD, STATUS_RELEASED, STATUS_UNKNOWN
  9. JSONLOG_FNAME = 'unittest.json'
  10. #
  11. # MAIN KEYS
  12. #
  13. MAIN_KEY_COVERAGE_INFO = 'coverage_information'
  14. MAIN_KEY_LOST_SOULS = "lost_souls"
  15. MAIN_KEY_SPECIFICATION = 'specification'
  16. MAIN_KEY_SYSTEM_INFO = 'system_information'
  17. MAIN_KEY_TESTOBJECT_INFO = 'testobject_information'
  18. MAIN_KEY_TESTRUNS = 'testrun_list'
  19. MAIN_KEY_UNITTEST_INFO = 'unittest_information'
  20. #
  21. # SUBKEYS FOR MAIN_KEY_COVERAGE_INFO
  22. #
  23. COVI_KEY_NAME = 'name'
  24. COVI_KEY_FILEPATH = 'filepath'
  25. COVI_KEY_LINE_COVERAGE = 'line_coverage'
  26. COVI_KEY_BRANCH_COVERAGE = 'branch_coverage'
  27. COVI_KEY_FILES = 'files'
  28. #
  29. # SUBKEYS FOR MAIN_KEY_LOST_SOULS
  30. #
  31. LOST_ITEMLIST = "item_list"
  32. LOST_TESTCASELIST = "testcase_list"
  33. #
  34. # SUBKEYS FOR MAIN_KEY_SPECIFICATION
  35. #
  36. SPEC_ITEM_DICT = 'item_dict'
  37. #
  38. # SUBKEYS FOR MAIN_KEY_SYSTEM_INFO
  39. #
  40. SYSI_ARCHITECTURE = "Architecture"
  41. SYSI_DISTRIBUTION = "Distribution"
  42. SYSI_HOSTNAME = "Hostname"
  43. SYSI_KERNEL = "Kernel"
  44. SYSI_MACHINE = "Machine"
  45. SYSI_PATH = "Path"
  46. SYSI_SYSTEM = "System"
  47. SYSI_USERNAME = "Username"
  48. #
  49. # SUBKEYS FOR MAIN_KEY_TESTOBJECT_INFO
  50. #
  51. TOBI_DEPENDENCIES = "Dependencies"
  52. TOBI_DESCRIPTION = "Description"
  53. TOBI_NAME = "Name"
  54. TOBI_STATE = "State"
  55. TOBI_STATE_RELEASED = 'Released'
  56. TOBI_STATE_IN_DEVELOPMENT = 'In development'
  57. TOBI_SUPP_INTERP = "Supported Interpreters"
  58. TOBI_VERSION = "Version"
  59. #
  60. # SUBKEYS FOR MAIN_KEY_TESTRUNS
  61. #
  62. TRUN_TESTCASES = 'testcases'
  63. #
  64. # SUBKEYS FOR MAIN_KEY_UNITTEST_INFO
  65. #
  66. UTEI_VERSION = TOBI_VERSION
  67. def get_lib_folder(ut_folder):
  68. return os.path.join(ut_folder, 'pylibs', os.path.basename(ut_folder))
  69. def get_ut_config(ut_folder):
  70. return os.path.join(get_ut_src_folder(ut_folder), 'config.py')
  71. def get_ut_testcase_folder(ut_folder):
  72. return os.path.join(get_ut_src_folder(ut_folder), 'tests')
  73. def get_ut_testresult_folder(ut_folder):
  74. return os.path.join(get_ut_subfolder(ut_folder), 'testresults')
  75. def get_lib_testresult_folder(ut_folder):
  76. return os.path.join(get_lib_folder(ut_folder), '_testresults_')
  77. def get_lib_jsonlog(ut_folder):
  78. return os.path.join(get_lib_testresult_folder(ut_folder), JSONLOG_FNAME)
  79. def get_ut_jsonlog(ut_folder):
  80. return os.path.join(get_ut_testresult_folder(ut_folder), JSONLOG_FNAME)
  81. def get_ut_src_folder(ut_folder):
  82. return os.path.join(get_ut_subfolder(ut_folder), 'src')
  83. def get_ut_subfolder(ut_folder):
  84. return os.path.join(ut_folder, 'unittest')
  85. def module_uid(path):
  86. return fstools.uid_filelist(path, '*.py', rekursive=True)
  87. def __get_release_state__(ut_folder, lib):
  88. if lib:
  89. fn = get_lib_jsonlog(ut_folder)
  90. else:
  91. fn = get_ut_jsonlog(ut_folder)
  92. try:
  93. with open(fn, 'r') as fh:
  94. ut_data = json.loads(fh.read())
  95. except IOError:
  96. return STATUS_MISSING
  97. else:
  98. ut_status = ut_data.get(MAIN_KEY_TESTOBJECT_INFO, {}).get(TOBI_STATE, 'unknown')
  99. if ut_status == TOBI_STATE_RELEASED:
  100. return STATUS_RELEASED
  101. elif ut_status == TOBI_STATE_IN_DEVELOPMENT:
  102. return STATUS_IN_WORK
  103. else:
  104. print(ut_status)
  105. return STATUS_UNKNOWN
  106. def get_lib_release_state(ut_folder):
  107. return __get_release_state__(ut_folder, True)
  108. def get_ut_release_state(ut_folder):
  109. return __get_release_state__(ut_folder, False)
  110. def __get_testcase_integrity__(ut_folder, lib):
  111. if lib:
  112. fn = get_lib_jsonlog(ut_folder)
  113. else:
  114. fn = get_ut_jsonlog(ut_folder)
  115. try:
  116. with open(fn, 'r') as fh:
  117. ut_data = json.loads(fh.read())
  118. except IOError:
  119. return STATUS_MISSING
  120. else:
  121. tc_version = ut_data.get(MAIN_KEY_UNITTEST_INFO, {}).get(UTEI_VERSION)
  122. current_version = module_uid(get_ut_testcase_folder(ut_folder))
  123. if tc_version == current_version:
  124. return STATUS_CLEAN
  125. else:
  126. return STATUS_IN_WORK
  127. def get_lib_testcase_integrity(ut_folder):
  128. return __get_testcase_integrity__(ut_folder, True)
  129. def get_ut_testcase_integrity(ut_folder):
  130. return __get_testcase_integrity__(ut_folder, False)
  131. def __get_src_integrity__(ut_folder, lib):
  132. if lib:
  133. fn = get_lib_jsonlog(ut_folder)
  134. else:
  135. fn = get_ut_jsonlog(ut_folder)
  136. try:
  137. with open(fn, 'r') as fh:
  138. ut_data = json.loads(fh.read())
  139. except IOError:
  140. return STATUS_MISSING
  141. else:
  142. tested_version = ut_data.get(MAIN_KEY_TESTOBJECT_INFO, {}).get(TOBI_VERSION)
  143. current_version = module_uid(get_lib_folder(ut_folder))
  144. if tested_version == current_version:
  145. return STATUS_CLEAN
  146. else:
  147. return STATUS_CHANGED
  148. def get_lib_src_integrity(ut_folder):
  149. return __get_src_integrity__(ut_folder, True)
  150. def get_ut_src_integrity(ut_folder):
  151. return __get_src_integrity__(ut_folder, False)
  152. def status_lib_unittest(ut_folder):
  153. if get_lib_release_state(ut_folder) == STATUS_RELEASED and get_lib_src_integrity(ut_folder) == STATUS_CLEAN and get_lib_testcase_integrity(ut_folder) == STATUS_CLEAN:
  154. return STATUS_CLEAN
  155. elif get_lib_release_state(ut_folder) == STATUS_MISSING and get_lib_src_integrity(ut_folder) == STATUS_MISSING and get_lib_testcase_integrity(ut_folder) == STATUS_MISSING:
  156. return STATUS_MISSING
  157. elif get_lib_release_state(ut_folder) == STATUS_IN_WORK or get_lib_src_integrity(ut_folder) == STATUS_IN_WORK or get_lib_testcase_integrity(ut_folder) == STATUS_IN_WORK:
  158. return STATUS_IN_WORK
  159. else:
  160. return STATUS_UNKNOWN
  161. def versions_module(ut_folder):
  162. try:
  163. with open(get_ut_jsonlog(ut_folder), 'r') as fh:
  164. ut = json.loads(fh.read())
  165. except IOError:
  166. return STATUS_UNKNOWN
  167. else:
  168. interpreters = ut.get(MAIN_KEY_TESTOBJECT_INFO, {}).get(TOBI_SUPP_INTERP, '')
  169. interpreters = interpreters.split(',')
  170. for i in range(len(interpreters)):
  171. interpreters[i] = interpreters[i].strip()
  172. interpreters[i] = interpreters[i][6:]
  173. return ', '.join(interpreters)
  174. def __get_coverage__(ut_folder, lib):
  175. if lib:
  176. fn = get_lib_jsonlog(ut_folder)
  177. else:
  178. fn = get_ut_jsonlog(ut_folder)
  179. try:
  180. with open(fn, 'r') as fh:
  181. ut = json.loads(fh.read())
  182. except IOError:
  183. return None, None
  184. else:
  185. lcov = ut.get(MAIN_KEY_COVERAGE_INFO, [{}])[0].get(COVI_KEY_LINE_COVERAGE)
  186. bcov = ut.get(MAIN_KEY_COVERAGE_INFO, [{}])[0].get(COVI_KEY_BRANCH_COVERAGE)
  187. return lcov, bcov
  188. def lib_coverage(ut_folder):
  189. return __get_coverage__(ut_folder, True)
  190. def ut_coverage(ut_folder):
  191. return __get_coverage__(ut_folder, False)
  192. def status_git(ut_folder):
  193. p = subprocess.Popen("git -C %s status 2> /dev/null" % ut_folder, stdout=subprocess.PIPE, shell=True)
  194. output = p.communicate()[0]
  195. p_status = p.wait()
  196. if p_status == 0:
  197. if b"nichts zu committen" in output and b"um lokale Commits zu publizieren" not in output:
  198. return STATUS_CLEAN
  199. else:
  200. return STATUS_CHANGED
  201. else:
  202. return STATUS_UNKNOWN
  203. def status_doc(ut_folder):
  204. if os.path.exists(os.path.join(get_lib_folder(ut_folder), '_docs_', 'index.html')):
  205. return STATUS_AVAILABLE
  206. else:
  207. if os.path.exists(os.path.join(ut_folder, 'docs', 'index.rst')):
  208. return STATUS_IN_WORK
  209. else:
  210. return STATUS_MISSING
  211. def status_spec(ut_folder):
  212. if os.path.exists(os.path.join(ut_folder, 'requirements', 'specification.reqif')):
  213. try:
  214. with open(get_lib_jsonlog(ut_folder), 'r') as fh:
  215. ut = json.loads(fh.read())
  216. if len(ut[MAIN_KEY_LOST_SOULS][LOST_ITEMLIST]) > 0 or len(ut[MAIN_KEY_LOST_SOULS][LOST_TESTCASELIST]) > 0:
  217. return STATUS_IN_WORK
  218. else:
  219. return STATUS_CLEAN
  220. except IOError:
  221. return STATUS_EXISTS
  222. else:
  223. return STATUS_MISSING