The undo/redo feature test is used to test the undo/redo system in an automated way, reducing the regressions introduced by new changes.
The way this is done is by reproducing critical test cases with a set of python scripts. The scripts writer can specify a list of objects of objects and assets that need testing. This means that before and after a single test, the serialized state of an object/asset must be the same.
Each <> represents a node; <Object> is a node tag, the rest of the key-data pairs inside a node are the Node Attributes.
Nodes in more indented levels are children of the nodes in less indented levels.
The serialization of objects is carried out automatically and their state is saved in an .xml file structured like the following:
This is a group with one brush object as a child.
The main asset comparison is done via a Cyclic Redundancy Check (CRC) algorithm; moreover, to help with error logging, all asset metadata files (e.g .cryasset files) are serialized as .xml archives in memory.
The undo system supports many different kinds of undos such as undo group detach/attach, prefab extract all, etc, with different setup conditions. For this reason, the actions that are required to set up and execute a single test and its components are exposed via python scripts. This way it is possible to expose editor actions via a flexible and simple scripting language and test Sandbox python APIs at the same time.
All testing scripts reside in <Engine installation directory>/Editor/Scripts/Test/UndoRedo, and a scripts is composed of:
- a setup() function to prepares the test, instantiate all necessary objects/assets and to add them to the objects_to_test/assets_to_test lists,
- an executeTest() function to execute all the test actions,
- a cleanup() function to delete all objects created for this test,
- an objects_to_test list (implicitly defined in the C++ APIs for each script) that has to be filled by the script writer with the names of objects to be tested,
- an assets_to_test list (implicitly defined in the C++ APIs for each script) that has to be filled by the script writer with the guids of assets to be tested,
Also a test_common module with some utility functions to create and operate on prefab hierarchies is available to the test scripts to make test creation faster.
The testing system executes all .py scripts found in the Test/UndoRedo folder the following way:
- The objects_to_test and assets_to_test lists are created in the C++ side of the testing framework and made available to each test;
- It calls setup() function;
All the objects added to the objects_to_test list are serialized in .xml archives, each with a root tag called <object name>-PreTest;The serialization takes place on the C++ side of the framework and an .xml archive is created in memory for each object to be tested.
- All the assets added to the assets_to_test list have all their file CRCs computed and their content stored as .xml archives when possible;
- It calls executeTest() function;
- All the objects added to the objects_to_test list are serialized in XML archives, each with a root tag called <object name>-PostTest;
- All the assets added to the assets_to_test list have all their file CRCs computed and their content stored as XML archives when possible;
- The list of archives serialized before executeTest are compared by the order they are added to the objects_to_test list with the archives serialized after executeTest;
- The list of asset files serialized before executeTest are compared by their CRCs by the order they are added to the assets_to_test list with the assets serialized after executeTest. In case CRC comparison fails, the asset files XML archives are also compared and the results are relayed to the user;
Calls cleanup() function.
All Phyton scripts can be placed in the folder <Engine installation directory>/Editor/Scripts/Test.
A test named Editor/PythonTestUndoRedo on the Test Runner can be used to execute all the tests in this folder. Note that if there is no level open, a new one named PythonUndoTestsLevel will be automatically created to run the tests in (currently no deletion is possible because of sandbox limitations).
For more information about Test Runner, please refer to the Test Runner page.
Custom Test Example
Following is a commented test script example that attaches an object to a group, undoes this and checks if both actions have been performed successfully.
This example can be used as a reference when a custom test is being created: