From 7daef6ab03cc3c66274d417a6a26ecd414992aab Mon Sep 17 00:00:00 2001 From: jckand-amzn Date: Fri, 20 Aug 2021 15:58:43 -0500 Subject: [PATCH] Converting Editor Main tests to use TestAutomationBase, and preparing for optimization Signed-off-by: jckand-amzn --- .../Gem/PythonTests/editor/CMakeLists.txt | 11 +- ...ditorWorkflows_LevelEntityComponentCRUD.py | 120 ++++++++++-------- .../PythonTests/editor/test_Editor_Main.py | 43 +++++++ .../editor/test_Editor_Main_Optimized.py | 38 ++++++ 4 files changed, 154 insertions(+), 58 deletions(-) create mode 100644 AutomatedTesting/Gem/PythonTests/editor/test_Editor_Main.py create mode 100644 AutomatedTesting/Gem/PythonTests/editor/test_Editor_Main_Optimized.py diff --git a/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt index fa35bb25c6..770a46c178 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt @@ -11,8 +11,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ NAME AutomatedTesting::EditorTests_Main TEST_SUITE main TEST_SERIAL - PATH ${CMAKE_CURRENT_LIST_DIR} - PYTEST_MARKS "SUITE_main and not REQUIRES_gpu" + PATH ${CMAKE_CURRENT_LIST_DIR}/test_Editor_Main.py + PYTEST_MARKS "not REQUIRES_gpu" RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor @@ -25,8 +25,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ NAME AutomatedTesting::EditorTests_Periodic TEST_SUITE periodic TEST_SERIAL - PATH ${CMAKE_CURRENT_LIST_DIR} - PYTEST_MARKS "SUITE_periodic and not REQUIRES_gpu" + PATH ${CMAKE_CURRENT_LIST_DIR}/test_Editor_Periodic.py RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor @@ -40,8 +39,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE main TEST_SERIAL TEST_REQUIRES gpu - PATH ${CMAKE_CURRENT_LIST_DIR} - PYTEST_MARKS "SUITE_main and REQUIRES_gpu" + PATH ${CMAKE_CURRENT_LIST_DIR}/test_Editor_Main.py + PYTEST_MARKS "REQUIRES_gpu" RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py index 994fc661ed..906e28bf8d 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py @@ -5,36 +5,44 @@ For complete copyright and license terms please see the LICENSE at the root of t SPDX-License-Identifier: Apache-2.0 OR MIT """ -""" -C6351273: Create a new level -C6384955: Basic Workflow: Entity Manipulation in the Outliner -C16929880: Add Delete Components -C15167490: Save a level -C15167491: Export a level -""" -import os -import sys -from PySide2 import QtWidgets - -import azlmbr.bus as bus -import azlmbr.editor as editor -import azlmbr.entity as entity -import azlmbr.math as math -import azlmbr.paths - -sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -from editor_python_test_tools.editor_test_helper import EditorTestHelper -import editor_python_test_tools.pyside_utils as pyside_utils -import editor_python_test_tools.hydra_editor_utils as hydra +class Tests: + level_created = ( + "New level created successfully", + "Failed to create new level" + ) + new_entity_created = ( + "New entity created successfully", + "Failed to create a new entity" + ) + child_entity_created = ( + "New child entity created successfully", + "Failed to create new child entity" + ) + component_added = ( + "Component added to entity successfully", + "Failed to add component to entity" + ) + component_updated = ( + "Component property updated successfully", + "Failed to update component property" + ) + component_removed = ( + "Component removed from entity successfully", + "Failed to remove component from entity" + ) + level_saved_and_exported = ( + "Level saved and exported successfully", + "Failed to save/export level" + ) -class TestBasicEditorWorkflows(EditorTestHelper): - def __init__(self): - EditorTestHelper.__init__(self, log_prefix="BasicEditorWorkflows_LevelEntityComponent", args=["level"]) +def RunTest(): + + import editor_python_test_tools.pyside_utils as pyside_utils @pyside_utils.wrap_async - async def run_test(self): + async def BasicEditorWorkflows_LevelEntityComponentCRUD(): """ Summary: Open O3DE editor and check if basic Editor workflows are completable. @@ -55,6 +63,18 @@ class TestBasicEditorWorkflows(EditorTestHelper): :return: None """ + import os + from PySide2 import QtWidgets + + import azlmbr.bus as bus + import azlmbr.editor as editor + import azlmbr.entity as entity + import azlmbr.math as math + import azlmbr.paths + + import editor_python_test_tools.hydra_editor_utils as hydra + from editor_python_test_tools.utils import Report + def find_entity_by_name(entity_name): search_filter = entity.SearchFilter() search_filter.names = [entity_name] @@ -64,6 +84,7 @@ class TestBasicEditorWorkflows(EditorTestHelper): return None # 1) Create a new level + level = "tmp_level" editor_window = pyside_utils.get_editor_main_window() new_level_action = pyside_utils.get_action_for_menu_path(editor_window, "File", "New Level") pyside_utils.trigger_action_async(new_level_action) @@ -71,21 +92,17 @@ class TestBasicEditorWorkflows(EditorTestHelper): new_level_dlg = active_modal_widget.findChild(QtWidgets.QWidget, "CNewLevelDialog") if new_level_dlg: if new_level_dlg.windowTitle() == "New Level": - self.log("New Level dialog opened") + Report.info("New Level dialog opened") grp_box = new_level_dlg.findChild(QtWidgets.QGroupBox, "STATIC_GROUP1") level_name = grp_box.findChild(QtWidgets.QLineEdit, "LEVEL") - level_name.setText(self.args["level"]) + level_name.setText(level) button_box = new_level_dlg.findChild(QtWidgets.QDialogButtonBox, "buttonBox") button_box.button(QtWidgets.QDialogButtonBox.Ok).click() # Verify new level was created successfully level_create_success = await pyside_utils.wait_for_condition(lambda: editor.EditorToolsApplicationRequestBus( - bus.Broadcast, "GetCurrentLevelName") == self.args["level"], 5.0) - self.test_success = level_create_success - self.log(f"Create and load new level: {level_create_success}") - - # Execute EditorTestHelper setup since level was created outside of EditorTestHelper's methods - self.test_success = self.test_success and self.after_level_load() + bus.Broadcast, "GetCurrentLevelName") == level, 5.0) + Report.critical_result(Tests.level_created, level_create_success) # 2) Delete existing entities, and create and manipulate new entities via Entity Inspector search_filter = azlmbr.entity.SearchFilter() @@ -99,8 +116,7 @@ class TestBasicEditorWorkflows(EditorTestHelper): # Find the new entity parent_entity_id = find_entity_by_name("Entity1") parent_entity_success = await pyside_utils.wait_for_condition(lambda: parent_entity_id is not None, 5.0) - self.test_success = self.test_success and parent_entity_success - self.log(f"New entity creation: {parent_entity_success}") + Report.critical_result(Tests.new_entity_created, parent_entity_success) # TODO: Replace Hydra call to creates child entity and add components with context menu triggering - LYN-3951 # Create a new child entity @@ -111,29 +127,26 @@ class TestBasicEditorWorkflows(EditorTestHelper): # Verify entity hierarchy child_entity.get_parent_info() - self.test_success = self.test_success and child_entity.parent_id == parent_entity_id - self.log(f"Create entity hierarchy: {child_entity.parent_id == parent_entity_id}") + Report.result(Tests.child_entity_created, child_entity.parent_id == parent_entity_id) # 3) Add/configure a component on an entity # Add component and verify success child_entity.add_component("Box Shape") - component_add_success = self.wait_for_condition(lambda: hydra.has_components(child_entity.id, ["Box Shape"]), 5.0) - self.test_success = self.test_success and component_add_success - self.log(f"Add component: {component_add_success}") + component_add_success = await pyside_utils.wait_for_condition(lambda: hydra.has_components(child_entity.id, + ["Box Shape"]), 5.0) + Report.result(Tests.component_added, component_add_success) # Update the component dimensions_to_set = math.Vector3(16.0, 16.0, 16.0) child_entity.get_set_test(0, "Box Shape|Box Configuration|Dimensions", dimensions_to_set) box_shape_dimensions = hydra.get_component_property_value(child_entity.components[0], "Box Shape|Box Configuration|Dimensions") - self.test_success = self.test_success and box_shape_dimensions == dimensions_to_set - self.log(f"Component update: {box_shape_dimensions == dimensions_to_set}") + Report.result(Tests.component_updated, box_shape_dimensions == dimensions_to_set) # Remove the component child_entity.remove_component("Box Shape") - component_rem_success = self.wait_for_condition(lambda: not hydra.has_components(child_entity.id, ["Box Shape"]), - 5.0) - self.test_success = self.test_success and component_rem_success - self.log(f"Remove component: {component_rem_success}") + component_rem_success = await pyside_utils.wait_for_condition(lambda: not hydra.has_components(child_entity.id, + ["Box Shape"]), 5.0) + Report.result(Tests.component_removed, component_rem_success) # 4) Save the level save_level_action = pyside_utils.get_action_for_menu_path(editor_window, "File", "Save") @@ -143,12 +156,15 @@ class TestBasicEditorWorkflows(EditorTestHelper): export_action = pyside_utils.get_action_for_menu_path(editor_window, "Game", "Export to Engine") pyside_utils.trigger_action_async(export_action) level_pak_file = os.path.join( - "AutomatedTesting", "Levels", self.args["level"], "level.pak" + "AutomatedTesting", "Levels", level, "level.pak" ) - export_success = self.wait_for_condition(lambda: os.path.exists(level_pak_file), 5.0) - self.test_success = self.test_success and export_success - self.log(f"Save and Export: {export_success}") + export_success = await pyside_utils.wait_for_condition(lambda: os.path.exists(level_pak_file), 5.0) + Report.result(Tests.level_saved_and_exported, export_success) + + BasicEditorWorkflows_LevelEntityComponentCRUD() -test = TestBasicEditorWorkflows() -test.run() +if __name__ == "__main__": + + from editor_python_test_tools.utils import Report + Report.start_test(RunTest) diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_Editor_Main.py b/AutomatedTesting/Gem/PythonTests/editor/test_Editor_Main.py new file mode 100644 index 0000000000..26b254ae71 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/editor/test_Editor_Main.py @@ -0,0 +1,43 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +import os +import pytest +import sys + +import ly_test_tools.environment.file_system as file_system + +sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared') +from base import TestAutomationBase + + +@pytest.fixture +def remove_test_level(request, workspace, project): + file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", "tmp_level")], True, True) + + def teardown(): + file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", "tmp_level")], True, True) + + request.addfinalizer(teardown) + + +@pytest.mark.SUITE_main +@pytest.mark.parametrize("launcher_platform", ['windows_editor']) +@pytest.mark.parametrize("project", ["AutomatedTesting"]) +class TestAutomation(TestAutomationBase): + + def test_BasicEditorWorkflows_LevelEntityComponentCRUD(self, request, workspace, editor, launcher_platform, + remove_test_level): + from .EditorScripts import BasicEditorWorkflows_LevelEntityComponentCRUD as test_module + self._run_test(request, workspace, editor, test_module, batch_mode=False, autotest_mode=False) + + @pytest.mark.REQUIRES_gpu + def test_BasicEditorWorkflows_GPU_LevelEntityComponentCRUD(self, request, workspace, editor, launcher_platform, + remove_test_level): + from .EditorScripts import BasicEditorWorkflows_LevelEntityComponentCRUD as test_module + self._run_test(request, workspace, editor, test_module, batch_mode=False, autotest_mode=False, + use_null_renderer=False) diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_Editor_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/editor/test_Editor_Main_Optimized.py new file mode 100644 index 0000000000..ac9c46e4e7 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/editor/test_Editor_Main_Optimized.py @@ -0,0 +1,38 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +import os +import pytest + +import ly_test_tools.environment.file_system as file_system +from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorParallelTest, EditorTestSuite + + +@pytest.mark.SUITE_main +@pytest.mark.parametrize("launcher_platform", ['windows_editor']) +@pytest.mark.parametrize("project", ["AutomatedTesting"]) +class TestAutomation(EditorTestSuite): + + class test_BasicEditorWorkflows_LevelEntityComponentCRUD(EditorSingleTest): + # Disable -BatchMode and -autotest_mode + EditorTestSuite.global_extra_cmdline_args = [] + # Custom teardown to remove slice asset created during test + def teardown(self, request, workspace, editor, editor_test_results, launcher_platform): + file_system.delete([os.path.join(workspace.paths.engine_root(), "AutomatedTesting", "Levels", "tmp_level")], + True, True) + from .EditorScripts import BasicEditorWorkflows_LevelEntityComponentCRUD as test_module + + @pytest.mark.REQUIRES_gpu + class test_BasicEditorWorkflows_GPU_LevelEntityComponentCRUD(EditorSingleTest): + # Disable -BatchMode, -autotest_mode, and null renderer + EditorTestSuite.global_extra_cmdline_args = [] + use_null_renderer = False + # Custom teardown to remove slice asset created during test + def teardown(self, request, workspace, editor, editor_test_results, launcher_platform): + file_system.delete([os.path.join(workspace.paths.engine_root(), "AutomatedTesting", "Levels", "tmp_level")], + True, True) + from .EditorScripts import BasicEditorWorkflows_LevelEntityComponentCRUD as test_module \ No newline at end of file