TestSuite_Main.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. """
  2. Copyright (c) Contributors to the Open 3D Engine Project.
  3. For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. SPDX-License-Identifier: Apache-2.0 OR MIT
  5. """
  6. """
  7. This suite contains the tests for editor_test utilities.
  8. """
  9. import pytest
  10. import os
  11. import sys
  12. import importlib
  13. import re
  14. from ly_test_tools import LAUNCHERS
  15. sys.path.append(os.path.dirname(os.path.abspath(__file__)))
  16. from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorTestSuite, Result
  17. from ly_test_tools.o3de.asset_processor import AssetProcessor
  18. import ly_test_tools.environment.process_utils as process_utils
  19. import argparse, sys
  20. @pytest.mark.SUITE_main
  21. @pytest.mark.parametrize("launcher_platform", ['windows_editor'])
  22. @pytest.mark.parametrize("project", ["AutomatedTesting"])
  23. class TestEditorTest:
  24. args = None
  25. path = None
  26. @classmethod
  27. def setup_class(cls):
  28. TestEditorTest.args = sys.argv.copy()
  29. build_dir_arg_index = TestEditorTest.args.index("--build-directory")
  30. if build_dir_arg_index < 0:
  31. print("Error: Must pass --build-directory argument in order to run this test")
  32. sys.exit(-2)
  33. TestEditorTest.args[build_dir_arg_index+1] = os.path.abspath(TestEditorTest.args[build_dir_arg_index+1])
  34. TestEditorTest.args.append("-s")
  35. TestEditorTest.path = os.path.dirname(os.path.abspath(__file__))
  36. cls._asset_processor = None
  37. def teardown_class(cls):
  38. if cls._asset_processor:
  39. cls._asset_processor.stop(1)
  40. cls._asset_processor.teardown()
  41. # Test runs #
  42. @classmethod
  43. def _run_single_test(cls, testdir, workspace, module_name):
  44. if cls._asset_processor is None:
  45. if not process_utils.process_exists("AssetProcessor", ignore_extensions=True):
  46. cls._asset_processor = AssetProcessor(workspace)
  47. cls._asset_processor.start()
  48. testdir.makepyfile(
  49. f"""
  50. import pytest
  51. import os
  52. import sys
  53. from ly_test_tools import LAUNCHERS
  54. from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorTestSuite
  55. @pytest.mark.SUITE_main
  56. @pytest.mark.parametrize("launcher_platform", ['windows_editor'])
  57. @pytest.mark.parametrize("project", ["AutomatedTesting"])
  58. class TestAutomation(EditorTestSuite):
  59. class test_single(EditorSingleTest):
  60. import {module_name} as test_module
  61. """)
  62. result = testdir.runpytest(*TestEditorTest.args[2:])
  63. def get_class(module_name):
  64. class test_single(EditorSingleTest):
  65. test_module = importlib.import_module(module_name)
  66. return test_single
  67. output = "".join(result.outlines)
  68. extracted_results = EditorTestSuite._get_results_using_output([get_class(module_name)], output, output)
  69. extracted_result = next(iter(extracted_results.items()))
  70. return (extracted_result[1], result)
  71. def test_single_passing_test(self, request, workspace, launcher_platform, testdir):
  72. (extracted_result, result) = TestEditorTest._run_single_test(testdir, workspace, "EditorTest_That_Passes")
  73. result.assert_outcomes(passed=1)
  74. assert isinstance(extracted_result, Result.Pass)
  75. def test_single_failing_test(self, request, workspace, launcher_platform, testdir):
  76. (extracted_result, result) = TestEditorTest._run_single_test(testdir, workspace, "EditorTest_That_Fails")
  77. result.assert_outcomes(failed=1)
  78. assert isinstance(extracted_result, Result.Fail)
  79. def test_single_crashing_test(self, request, workspace, launcher_platform, testdir):
  80. (extracted_result, result) = TestEditorTest._run_single_test(testdir, workspace, "EditorTest_That_Crashes")
  81. result.assert_outcomes(failed=1)
  82. assert isinstance(extracted_result, Result.Unknown)
  83. @classmethod
  84. def _run_shared_test(cls, testdir, module_class_code, extra_cmd_line=None):
  85. if not extra_cmd_line:
  86. extra_cmd_line = []
  87. if cls._asset_processor is None:
  88. if not process_utils.process_exists("AssetProcessor", ignore_extensions=True):
  89. cls._asset_processor = AssetProcessor(workspace)
  90. cls._asset_processor.start()
  91. testdir.makepyfile(
  92. f"""
  93. import pytest
  94. import os
  95. import sys
  96. from ly_test_tools import LAUNCHERS
  97. from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorTestSuite
  98. @pytest.mark.SUITE_main
  99. @pytest.mark.parametrize("launcher_platform", ['windows_editor'])
  100. @pytest.mark.parametrize("project", ["AutomatedTesting"])
  101. class TestAutomation(EditorTestSuite):
  102. {module_class_code}
  103. """)
  104. result = testdir.runpytest(*TestEditorTest.args[2:] + extra_cmd_line)
  105. return result
  106. def test_batched_two_passing(self, request, workspace, launcher_platform, testdir):
  107. result = self._run_shared_test(testdir,
  108. """
  109. class test_pass(EditorSharedTest):
  110. import EditorTest_That_Passes as test_module
  111. is_parallelizable = False
  112. class test_2(EditorSharedTest):
  113. import EditorTest_That_PassesToo as test_module
  114. is_parallelizable = False
  115. """
  116. )
  117. # 2 Passes +1(batch runner)
  118. result.assert_outcomes(passed=3)
  119. def test_batched_one_pass_one_fail(self, request, workspace, launcher_platform, testdir):
  120. result = self._run_shared_test(testdir,
  121. """
  122. class test_pass(EditorSharedTest):
  123. import EditorTest_That_Passes as test_module
  124. is_parallelizable = False
  125. class test_fail(EditorSharedTest):
  126. import EditorTest_That_Fails as test_module
  127. is_parallelizable = False
  128. """
  129. )
  130. # 1 Fail, 1 Passes +1(batch runner)
  131. result.assert_outcomes(passed=2, failed=1)
  132. def test_batched_one_pass_one_fail_one_crash(self, request, workspace, launcher_platform, testdir):
  133. result = self._run_shared_test(testdir,
  134. """
  135. class test_pass(EditorSharedTest):
  136. import EditorTest_That_Passes as test_module
  137. is_parallelizable = False
  138. class test_fail(EditorSharedTest):
  139. import EditorTest_That_Fails as test_module
  140. is_parallelizable = False
  141. class test_crash(EditorSharedTest):
  142. import EditorTest_That_Crashes as test_module
  143. is_parallelizable = False
  144. """
  145. )
  146. # 2 Fail, 1 Passes + 1(batch runner)
  147. result.assert_outcomes(passed=2, failed=2)
  148. def test_parallel_two_passing(self, request, workspace, launcher_platform, testdir):
  149. result = self._run_shared_test(testdir,
  150. """
  151. class test_pass_1(EditorSharedTest):
  152. import EditorTest_That_Passes as test_module
  153. is_batchable = False
  154. class test_pass_2(EditorSharedTest):
  155. import EditorTest_That_PassesToo as test_module
  156. is_batchable = False
  157. """
  158. )
  159. # 2 Passes +1(parallel runner)
  160. result.assert_outcomes(passed=3)
  161. def test_parallel_one_passing_one_failing_one_crashing(self, request, workspace, launcher_platform, testdir):
  162. result = self._run_shared_test(testdir,
  163. """
  164. class test_pass(EditorSharedTest):
  165. import EditorTest_That_Passes as test_module
  166. is_batchable = False
  167. class test_fail(EditorSharedTest):
  168. import EditorTest_That_Fails as test_module
  169. is_batchable = False
  170. class test_crash(EditorSharedTest):
  171. import EditorTest_That_Crashes as test_module
  172. is_batchable = False
  173. """
  174. )
  175. # 2 Fail, 1 Passes + 1(parallel runner)
  176. result.assert_outcomes(passed=2, failed=2)
  177. def test_parallel_batched_two_passing(self, request, workspace, launcher_platform, testdir):
  178. result = self._run_shared_test(testdir,
  179. """
  180. class test_pass_1(EditorSharedTest):
  181. import EditorTest_That_Passes as test_module
  182. class test_pass_2(EditorSharedTest):
  183. import EditorTest_That_PassesToo as test_module
  184. """
  185. )
  186. # 2 Passes +1(batched+parallel runner)
  187. result.assert_outcomes(passed=3)
  188. def test_parallel_batched_one_passing_one_failing_one_crashing(self, request, workspace, launcher_platform, testdir):
  189. result = self._run_shared_test(testdir,
  190. """
  191. class test_pass(EditorSharedTest):
  192. import EditorTest_That_Passes as test_module
  193. class test_fail(EditorSharedTest):
  194. import EditorTest_That_Fails as test_module
  195. class test_crash(EditorSharedTest):
  196. import EditorTest_That_Crashes as test_module
  197. """
  198. )
  199. # 2 Fail, 1 Passes + 1(batched+parallel runner)
  200. result.assert_outcomes(passed=2, failed=2)
  201. def test_selection_2_deselected_1_selected(self, request, workspace, launcher_platform, testdir):
  202. result = self._run_shared_test(testdir,
  203. """
  204. class test_pass(EditorSharedTest):
  205. import EditorTest_That_Passes as test_module
  206. class test_fail(EditorSharedTest):
  207. import EditorTest_That_Fails as test_module
  208. class test_crash(EditorSharedTest):
  209. import EditorTest_That_Crashes as test_module
  210. """, extra_cmd_line=["-k", "fail"]
  211. )
  212. # 1 Fail + 1 Success(parallel runner)
  213. result.assert_outcomes(failed=1, passed=1)
  214. outcomes = result.parseoutcomes()
  215. deselected = outcomes.get("deselected")
  216. assert deselected == 2