unitTests.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. '''
  2. Licensed to the Apache Software Foundation (ASF) under one
  3. or more contributor license agreements. See the NOTICE file
  4. distributed with this work for additional information
  5. regarding copyright ownership. The ASF licenses this file
  6. to you under the Apache License, Version 2.0 (the
  7. "License"); you may not use this file except in compliance
  8. with the License. You may obtain a copy of the License at
  9. http://www.apache.org/licenses/LICENSE-2.0
  10. Unless required by applicable law or agreed to in writing, software
  11. distributed under the License is distributed on an "AS IS" BASIS,
  12. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. See the License for the specific language governing permissions and
  14. limitations under the License.
  15. '''
  16. import unittest
  17. import multiprocessing
  18. import os
  19. import sys
  20. from random import shuffle
  21. import fnmatch
  22. #excluded directories with non-test staff from stack and service scanning,
  23. #also we can add service or stack to skip here
  24. STACK_EXCLUDE = ["utils"]
  25. SERVICE_EXCLUDE = ["configs"]
  26. TEST_MASK = '[Tt]est*.py'
  27. CUSTOM_TEST_MASK = '_[Tt]est*.py'
  28. def get_parent_path(base, directory_name):
  29. """
  30. Returns absolute path for directory_name, if directory_name present in base.
  31. For example, base=/home/user/test2, directory_name=user - will return /home/user
  32. """
  33. done = False
  34. while not done:
  35. base = os.path.dirname(base)
  36. if base == "/":
  37. return None
  38. done = True if os.path.split(base)[-1] == directory_name else False
  39. return base
  40. def get_test_files(path, mask = None, recursive=True):
  41. """
  42. Returns test files for path recursively
  43. """
  44. current = []
  45. directory_items = os.listdir(path)
  46. for item in directory_items:
  47. add_to_pythonpath = False
  48. if os.path.isfile(path + "/" + item):
  49. if fnmatch.fnmatch(item, mask):
  50. add_to_pythonpath = True
  51. current.append(item)
  52. elif os.path.isdir(path + "/" + item):
  53. if recursive:
  54. current.extend(get_test_files(path + "/" + item, mask = mask))
  55. if add_to_pythonpath:
  56. sys.path.append(path)
  57. return current
  58. def stack_test_executor(base_folder, stack, service, custom_tests, executor_result):
  59. """
  60. Stack tests executor. Must be executed in separate process to prevent module
  61. name conflicts in different stacks.
  62. """
  63. #extract stack scripts folders
  64. if custom_tests:
  65. test_mask = CUSTOM_TEST_MASK
  66. else:
  67. test_mask = TEST_MASK
  68. server_src_dir = get_parent_path(base_folder,'src')
  69. base_stack_folder = os.path.join(server_src_dir,
  70. 'main/resources/stacks/HDP/{0}'.format(stack))
  71. script_folders = set()
  72. for root, subFolders, files in os.walk(base_stack_folder):
  73. if os.path.split(root)[-1] == "scripts" and service in root:
  74. script_folders.add(root)
  75. sys.path.extend(script_folders)
  76. tests = get_test_files(base_folder, mask = test_mask)
  77. shuffle(tests)
  78. modules = [os.path.basename(s)[:-3] for s in tests]
  79. suites = [unittest.defaultTestLoader.loadTestsFromName(name) for name in
  80. modules]
  81. testSuite = unittest.TestSuite(suites)
  82. textRunner = unittest.TextTestRunner(verbosity=2).run(testSuite)
  83. #for pretty output
  84. sys.stdout.flush()
  85. sys.stderr.flush()
  86. exit_code = 0 if textRunner.wasSuccessful() else 1
  87. executor_result.put({'exit_code':exit_code,
  88. 'tests_run':textRunner.testsRun,
  89. 'errors':[(str(item[0]),str(item[1]),"ERROR") for item in textRunner.errors],
  90. 'failures':[(str(item[0]),str(item[1]),"FAIL") for item in textRunner.failures]})
  91. executor_result.put(0) if textRunner.wasSuccessful() else executor_result.put(1)
  92. def main():
  93. custom_tests = False
  94. if len(sys.argv) > 1:
  95. if sys.argv[1] == "true":
  96. custom_tests = True
  97. pwd = os.path.abspath(os.path.dirname(__file__))
  98. ambari_server_folder = get_parent_path(pwd,'ambari-server')
  99. ambari_agent_folder = os.path.join(ambari_server_folder,os.path.normpath("../ambari-agent"))
  100. ambari_common_folder = os.path.join(ambari_server_folder,os.path.normpath("../ambari-common"))
  101. # append pythonpath (for running from IDE)
  102. sys.path.append(ambari_common_folder + os.path.normpath("/src/test/python"))
  103. sys.path.append(ambari_common_folder + os.path.normpath("/src/main/python/jinja2"))
  104. sys.path.append(ambari_agent_folder + os.path.normpath("/src/main/python"))
  105. stacks_folder = pwd+'/stacks'
  106. #generate test variants(path, service, stack)
  107. test_variants = []
  108. for stack in os.listdir(stacks_folder):
  109. current_stack_dir = stacks_folder+"/"+stack
  110. if os.path.isdir(current_stack_dir) and stack not in STACK_EXCLUDE:
  111. for service in os.listdir(current_stack_dir):
  112. current_service_dir = current_stack_dir+"/"+service
  113. if os.path.isdir(current_service_dir) and service not in SERVICE_EXCLUDE:
  114. test_variants.append({'directory':current_service_dir,
  115. 'service':service,
  116. 'stack':stack})
  117. #run tests for every service in every stack in separate process
  118. has_failures = False
  119. test_runs = 0
  120. test_failures = []
  121. test_errors = []
  122. for variant in test_variants:
  123. executor_result = multiprocessing.Queue()
  124. sys.stderr.write( "Running tests for stack:{0} service:{1}\n"
  125. .format(variant['stack'],variant['service']))
  126. process = multiprocessing.Process(target=stack_test_executor,
  127. args=(variant['directory'],
  128. variant['service'],
  129. variant['stack'],
  130. custom_tests,
  131. executor_result)
  132. )
  133. process.start()
  134. process.join()
  135. #for pretty output
  136. sys.stdout.flush()
  137. sys.stderr.flush()
  138. variant_result = executor_result.get()
  139. test_runs += variant_result['tests_run']
  140. test_errors.extend(variant_result['errors'])
  141. test_failures.extend(variant_result['failures'])
  142. if variant_result['exit_code'] != 0:
  143. has_failures = True
  144. #run base ambari-server tests
  145. sys.stderr.write("Running tests for ambari-server\n")
  146. if custom_tests:
  147. test_mask = CUSTOM_TEST_MASK
  148. else:
  149. test_mask = TEST_MASK
  150. tests = get_test_files(pwd, mask=test_mask, recursive=False)
  151. shuffle(tests)
  152. modules = [os.path.basename(s)[:-3] for s in tests]
  153. suites = [unittest.defaultTestLoader.loadTestsFromName(name) for name in
  154. modules]
  155. testSuite = unittest.TestSuite(suites)
  156. textRunner = unittest.TextTestRunner(verbosity=2).run(testSuite)
  157. test_runs += textRunner.testsRun
  158. test_errors.extend([(str(item[0]),str(item[1]),"ERROR") for item in textRunner.errors])
  159. test_failures.extend([(str(item[0]),str(item[1]),"FAIL") for item in textRunner.failures])
  160. tests_status = textRunner.wasSuccessful() and not has_failures
  161. if not tests_status:
  162. sys.stderr.write("----------------------------------------------------------------------\n")
  163. sys.stderr.write("Failed tests:\n")
  164. for failed_tests in [test_errors,test_failures]:
  165. for err in failed_tests:
  166. sys.stderr.write("{0}: {1}\n".format(err[2],err[0]))
  167. sys.stderr.write("----------------------------------------------------------------------\n")
  168. sys.stderr.write("{0}\n".format(err[1]))
  169. sys.stderr.write("----------------------------------------------------------------------\n")
  170. sys.stderr.write("Total run:{0}\n".format(test_runs))
  171. sys.stderr.write("Total errors:{0}\n".format(len(test_errors)))
  172. sys.stderr.write("Total failures:{0}\n".format(len(test_failures)))
  173. if tests_status:
  174. sys.stderr.write("OK\n")
  175. exit_code = 0
  176. else:
  177. sys.stderr.write("ERROR\n")
  178. exit_code = 1
  179. return exit_code
  180. if __name__ == "__main__":
  181. sys.exit(main())