Changeset View
Standalone View
tests/python/transform_operators.py
- This file was added.
| # ##### BEGIN GPL LICENSE BLOCK ##### | |||||
| # | |||||
| # This program is free software; you can redistribute it and/or | |||||
| # modify it under the terms of the GNU General Public License | |||||
| # as published by the Free Software Foundation; either version 2 | |||||
| # of the License, or (at your option) any later version. | |||||
| # | |||||
| # This program is distributed in the hope that it will be useful, | |||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| # GNU General Public License for more details. | |||||
| # | |||||
| # You should have received a copy of the GNU General Public License | |||||
| # along with this program; if not, write to the Free Software Foundation, | |||||
| # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||||
| # | |||||
| # ##### END GPL LICENSE BLOCK ##### | |||||
| # <pep8 compliant> | |||||
| # To run all tests, use | |||||
| # BLENDER_VERBOSE=1 blender path/to/transform_regression.blend --python path/to/transform_operators.py -- --run-all-tests | |||||
| # To run one test, use | |||||
| # BLENDER_VERBOSE=1 blender path/to/transform_regression.blend --python path/to/transform_operators.py -- --run-test <index> | |||||
| # where <index> is the index of the test specified in the list tests. | |||||
| import bpy | |||||
| import os | |||||
| import sys | |||||
sybren: I've never seen this before, and I feel it's also a bit clunky. Most test frameworks use the… | |||||
Done Inline ActionsThis index is for internal use. The test name is "transform". This is the same as seen in modifier.py which has an API similar. mano-wii: This index is for internal use. The test name is `"transform"`.
This is the same as seen in… | |||||
Done Inline ActionsIf there is the need to manually add comments to a list to indicate the index of each item, that's an indication of a bad design. There is also a comment that explains how to use that index to run a single test, so it's not for internal use either. modifiers.py identifies tests by name, and not by index, so I don't really see your point. sybren: If there is the need to manually add comments to a list to indicate the index of each item… | |||||
Done Inline ActionsI may be seeing things, but I'm sure it used to be index. mano-wii: I may be seeing things, but I'm sure it used to be index.
I don't even know what the names of… | |||||
| sys.path.append(os.path.dirname(os.path.realpath(__file__))) | |||||
| from modules.transform_test import TestContext | |||||
| def test_translate_global_objectmode(test_ctx): | |||||
| obj_test = bpy.data.objects['MyObject'] | |||||
| obj_expected = bpy.data.objects['MyObject_trans_global_object_expected'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| bpy.context.scene.transform_orientation_slots[0].type = 'GLOBAL' | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| bpy.ops.transform.translate( | |||||
| test_ctx.override_context, | |||||
| value=(0,0,1), | |||||
| constraint_axis=(True,True,True), | |||||
| ) | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, True, False) | |||||
| def test_translate_global_editmode_a(test_ctx): | |||||
Done Inline ActionsWhat are "edit mode a" and "b"? What is being tested here? The way the test code is written, it's hard to see the difference between the "a" and "b" functions. sybren: What are "edit mode a" and "b"? What is being tested here? The way the test code is written… | |||||
| obj_test = bpy.data.objects['MyObject'] | |||||
| obj_expected = bpy.data.objects['MyObject_trans_global_edit_expected'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| bpy.context.scene.transform_orientation_slots[0].type = 'GLOBAL' | |||||
| bpy.ops.object.mode_set(mode="EDIT") | |||||
| bpy.ops.mesh.select_all(action="SELECT") | |||||
| bpy.ops.transform.translate( | |||||
| test_ctx.override_context, | |||||
| value=(0,0,1), | |||||
| constraint_axis=(True,True,True), | |||||
| ) | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, False, True) | |||||
| def test_translate_global_editmode_b(test_ctx): | |||||
| obj_test = bpy.data.objects['MyObject'] | |||||
| obj_expected = bpy.data.objects['MyObject_trans_global_edit_expected'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| bpy.context.scene.transform_orientation_slots[0].type = 'GLOBAL' | |||||
| bpy.ops.object.mode_set(mode="EDIT") | |||||
| bpy.ops.mesh.select_all(action="SELECT") | |||||
| bpy.ops.transform.translate( | |||||
| test_ctx.override_context, | |||||
| value=(0,0,1), | |||||
| constraint_axis=(True,True,True), | |||||
| orient_type='GLOBAL', | |||||
| ) | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, False, True) | |||||
| def test_translate_local_objectmode(test_ctx): | |||||
Done Inline ActionsI am sure you can make this more readable about what is the input, what is the expected expression. sergey: I am sure you can make this more readable about what is the input, what is the expected… | |||||
| obj_test = bpy.data.objects['MyObject_transformed'] | |||||
| obj_expected = bpy.data.objects['MyObject_trans_local_object_expected'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| bpy.context.scene.transform_orientation_slots[0].type = 'LOCAL' | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| bpy.ops.transform.translate( | |||||
| test_ctx.override_context, | |||||
| value=(0,0,1), | |||||
| constraint_axis=(True,True,True), | |||||
| ) | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, True, False) | |||||
| def test_translate_local_editmode_a(test_ctx): | |||||
| obj_test = bpy.data.objects['MyObject_transformed'] | |||||
| obj_expected = bpy.data.objects['MyObject_trans_local_edit_expected'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| bpy.context.scene.transform_orientation_slots[0].type = 'LOCAL' | |||||
| bpy.ops.object.mode_set(mode="EDIT") | |||||
| bpy.ops.mesh.select_all(action="SELECT") | |||||
| bpy.ops.transform.translate( | |||||
| test_ctx.override_context, | |||||
| value=(0,0,1), | |||||
| constraint_axis=(True,True,True), | |||||
| ) | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, False, True) | |||||
| def test_translate_local_editmode_b(test_ctx): | |||||
| obj_test = bpy.data.objects['MyObject_transformed'] | |||||
| obj_expected = bpy.data.objects['MyObject_trans_local_edit_expected'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| bpy.context.scene.transform_orientation_slots[0].type = 'LOCAL' | |||||
| bpy.ops.object.mode_set(mode="EDIT") | |||||
| bpy.ops.mesh.select_all(action="SELECT") | |||||
| bpy.ops.transform.translate( | |||||
| test_ctx.override_context, | |||||
| value=(0,0,1), | |||||
| constraint_axis=(True,True,True), | |||||
| orient_type='LOCAL', | |||||
| ) | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, False, True) | |||||
| def test_rotate_local_objectmode_a(test_ctx): | |||||
| obj_test = bpy.data.objects['MyObject_transformed'] | |||||
| obj_expected = bpy.data.objects['MyObject_rot_local_object_expected'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| bpy.context.scene.transform_orientation_slots[0].type = 'LOCAL' | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| bpy.ops.transform.rotate( | |||||
| test_ctx.override_context, | |||||
| value=1.5708, | |||||
| constraint_axis=(False,False,True), | |||||
| ) | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, False, True) | |||||
| def test_rotate_local_objectmode_b(test_ctx): | |||||
| obj_test = bpy.data.objects['MyObject_transformed'] | |||||
| obj_expected = bpy.data.objects['MyObject_rot_local_object_expected'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| bpy.context.scene.transform_orientation_slots[0].type = 'LOCAL' | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| bpy.ops.transform.rotate( | |||||
| test_ctx.override_context, | |||||
| value=1.5708, | |||||
| constraint_axis=(False,False,True), | |||||
| orient_type='LOCAL', | |||||
| ) | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, False, True) | |||||
| def test_rotate_view_objectmode_a(test_ctx): | |||||
| obj_test = bpy.data.objects['MyObject_transformed'] | |||||
| obj_expected = bpy.data.objects['MyObject_rot_view_object_expected_0'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| bpy.context.scene.transform_orientation_slots[0].type = 'VIEW' | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| bpy.ops.transform.rotate( | |||||
| test_ctx.override_context, | |||||
| value=1.5708, | |||||
| ) | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, False, True) | |||||
| def test_rotate_view_objectmode_b(test_ctx): | |||||
| obj_test = bpy.data.objects['MyObject_transformed'] | |||||
| obj_expected = bpy.data.objects['MyObject_rot_view_object_expected_1'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| bpy.context.scene.transform_orientation_slots[0].type = 'VIEW' | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| bpy.ops.transform.rotate( | |||||
| test_ctx.override_context, | |||||
| value=1.5708, | |||||
| constraint_axis=(False,False,True), | |||||
| orient_type='VIEW', | |||||
| orient_matrix_type='VIEW', | |||||
| orient_matrix=((0.9079387784004211,-0.17976072430610657,0.3785933554172516), | |||||
| (0.4191024899482727,0.3894294500350952,-0.8201814889907837), | |||||
| (-9.983776863009552e-07,-0.9033441543579102,-0.428916335105896)), | |||||
| ) | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, False, True) | |||||
| def test_rotate_normal_editmode_individual_orig_a(test_ctx): | |||||
| scene = bpy.context.scene | |||||
| obj_test = bpy.data.objects['MyObject_transformed'] | |||||
| obj_expected = bpy.data.objects['MyObject_rot_normal_edit_individual_orig_expected'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| scene.transform_orientation_slots[0].type = 'NORMAL' | |||||
| scene.tool_settings.transform_pivot_point = 'INDIVIDUAL_ORIGINS' | |||||
| bpy.ops.object.mode_set(mode="EDIT") | |||||
| bpy.ops.mesh.select_all(action="SELECT") | |||||
| bpy.ops.transform.rotate( | |||||
| test_ctx.override_context, | |||||
| value=0.785398, | |||||
| constraint_axis=(False,False,True), | |||||
| ) | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, False, True) | |||||
| def test_rotate_normal_editmode_individual_orig_b(test_ctx): | |||||
| scene = bpy.context.scene | |||||
| obj_test = bpy.data.objects['MyObject_transformed'] | |||||
| obj_expected = bpy.data.objects['MyObject_rot_normal_edit_individual_orig_expected'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| scene.transform_orientation_slots[0].type = 'NORMAL' | |||||
| scene.tool_settings.transform_pivot_point = 'INDIVIDUAL_ORIGINS' | |||||
| bpy.ops.object.mode_set(mode="EDIT") | |||||
| bpy.ops.mesh.select_all(action="SELECT") | |||||
| bpy.ops.transform.rotate( | |||||
| test_ctx.override_context, | |||||
| value=0.785398, | |||||
| constraint_axis=(False,False,True), | |||||
| orient_type='NORMAL', | |||||
| ) | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, False, True) | |||||
| def test_rotate_normal_editmode_individual_orig_c(test_ctx): | |||||
| scene = bpy.context.scene | |||||
| obj_test = bpy.data.objects['MyObject_transformed'] | |||||
| obj_expected = bpy.data.objects['MyObject_rot_normal_edit_individual_orig_expected'] | |||||
| obj_dupl = test_ctx.duplicate_object(obj_test) | |||||
| test_ctx.activate_object(obj_dupl) | |||||
| scene.transform_orientation_slots[0].type = 'NORMAL' | |||||
| scene.tool_settings.transform_pivot_point = 'INDIVIDUAL_ORIGINS' | |||||
| bpy.ops.object.mode_set(mode="EDIT") | |||||
| bpy.ops.mesh.select_all(action="SELECT") | |||||
| bpy.ops.transform.rotate( | |||||
| test_ctx.override_context, | |||||
| value=0.785398, | |||||
| constraint_axis=(False,False,True), | |||||
| orient_type='NORMAL', | |||||
| orient_matrix_type='NORMAL', | |||||
| orient_matrix=((1,0,0), | |||||
| (0,1,0), | |||||
| (0,0,1)), | |||||
| ) | |||||
| bpy.ops.object.mode_set(mode="OBJECT") | |||||
| return test_ctx.compare_objects(obj_dupl, obj_expected, False, True) | |||||
| def main(): | |||||
| index = None | |||||
| command = list(sys.argv) | |||||
| for i, cmd in enumerate(command): | |||||
| if cmd == "--run-all-tests": | |||||
| break | |||||
| elif cmd == "--run-test": | |||||
| index = int(command[i + 1]) | |||||
| break | |||||
| os.environ["BLENDER_VERBOSE"] = "1" | |||||
| funcs = [ | |||||
| test_translate_global_objectmode, | |||||
| test_translate_global_editmode_a, | |||||
| test_translate_global_editmode_b, | |||||
| test_translate_local_objectmode, | |||||
Done Inline ActionsWhy isn't this using argparse instead? sybren: Why isn't this using `argparse` instead? | |||||
| test_translate_local_editmode_a, | |||||
| test_translate_local_editmode_b, | |||||
Done Inline ActionsWhat does this do? sybren: What does this do? | |||||
Done Inline ActionsRemoved because it was not meant to be set here. mano-wii: Removed because it was not meant to be set here.
This environment variable is used in some… | |||||
| test_rotate_local_objectmode_a, | |||||
| test_rotate_local_objectmode_b, | |||||
| test_rotate_view_objectmode_a, | |||||
| test_rotate_view_objectmode_b, | |||||
| #test_rotate_normal_editmode_individual_orig_a, | |||||
| #test_rotate_normal_editmode_individual_orig_b, | |||||
| #test_rotate_normal_editmode_individual_orig_c, | |||||
| ] | |||||
| test_ctx = TestContext(funcs) | |||||
| if index: | |||||
| test_ctx.cleanup = False | |||||
| test_ctx.run_test(index) | |||||
| else: | |||||
| test_ctx.run_all_tests() | |||||
| test_ctx.end() | |||||
| if __name__ == "__main__": | |||||
| try: | |||||
| main() | |||||
| except: | |||||
| import traceback | |||||
| traceback.print_exc() | |||||
| sys.exit(1) | |||||
I've never seen this before, and I feel it's also a bit clunky. Most test frameworks use the name of the test, and not its index.