[Bf-blender-cvs] [7e45a760b4f] soc-2021-geometry-nodes-regression-test: Added backward support for existing tests.
Himanshi Kalra
noreply at git.blender.org
Wed Jul 7 15:40:31 CEST 2021
Commit: 7e45a760b4fc786af4674a0e44398d65cf709af2
Author: Himanshi Kalra
Date: Wed Jul 7 18:46:09 2021 +0530
Branches: soc-2021-geometry-nodes-regression-test
https://developer.blender.org/rB7e45a760b4fc786af4674a0e44398d65cf709af2
Added backward support for existing tests.
- Added create_expected_object if it doesn't exist.
- Added a counter condition for recusrion.
- Added optional test_name in basemesh test.
- Added code of previous MeshTest to SpecMeshTest.
- Changed default value of apply_modifier(s) flag and do_compare flag.
===================================================================
M tests/python/modules/base_mesh_test.py
===================================================================
diff --git a/tests/python/modules/base_mesh_test.py b/tests/python/modules/base_mesh_test.py
index 1e8f48b74fc..d855af74c6d 100644
--- a/tests/python/modules/base_mesh_test.py
+++ b/tests/python/modules/base_mesh_test.py
@@ -3,24 +3,42 @@ import bpy
import os
import sys
-from modules.spec_classes import ModifierSpec, DeformModifierSpec, OperatorSpecEditMode, OperatorSpecObjectMode
+from modules.spec_classes import ModifierSpec, DeformModifierSpec, OperatorSpecEditMode, OperatorSpecObjectMode, ParticleSystemSpec
class MeshTest(ABC):
- def __init__(self, test_object_name, exp_object_name, threshold=None):
+ def __init__(self, test_object_name, exp_object_name, test_name=None, threshold=None):
self.test_object_name = test_object_name
self.exp_object_name = exp_object_name
+ self.test_name = test_name
self.threshold = threshold
self.update = os.getenv("BLENDER_TEST_UPDATE") is not None
+ self.verbose = os.getenv("BLENDER_VERBOSE") is not None
# self.eval_object_name = "evaluated_object"
- # Private flag to indicate whether the blend file was updated after the test.
- self._test_updated = False
+
+ self.test_updated_counter = 0
objects = bpy.data.objects
self.test_object = objects[self.test_object_name]
+ # self.expected_object = objects[self.exp_object_name]
- # TODO - create exp object, in case doesn't exist.
- self.expected_object = objects[self.exp_object_name]
+ if self.update:
+ if objects.find(exp_object_name) > -1:
+ self.expected_object = objects[self.exp_object_name]
+ else:
+ self.create_expected_object()
+ else:
+ self.expected_object = objects[self.exp_object_name]
+
+
+ def create_expected_object(self):
+ print("Creating expected object...")
+ evaluated_object = self.create_evaluated_object()
+ self.expected_object = evaluated_object
+ self.expected_object.name = self.exp_object_name
+ x, y, z = self.test_object.location
+ self.expected_object.location = (x, y+10, z)
+ bpy.ops.wm.save_as_mainfile(filepath=bpy.data.filepath)
def create_evaluated_object(self):
bpy.context.view_layer.objects.active = self.test_object
@@ -40,11 +58,13 @@ class MeshTest(ABC):
@staticmethod
def _print_result(result):
comparison_result, selection_result, validation_result = result
- print("Mesh Compariosn: {}".format(comparison_result))
+ print("Mesh Comparison: {}".format(comparison_result))
print("Selection Result: {}".format(selection_result))
print("Mesh Validation: {}".format(validation_result))
+ print()
def run_test(self):
+ # self.test_updated_counter = 0
evaluated_test_object = self.create_evaluated_object()
self.apply_operations(evaluated_test_object)
result = self.compare_meshes(evaluated_test_object)
@@ -53,25 +73,35 @@ class MeshTest(ABC):
if comparison_result == "Same" and selection_result == "Same" and validation_result == "Valid":
self.passed_test(result)
+ # Clean up.
+ if self.verbose:
+ print("Cleaning up...")
+ # Delete evaluated_test_object.
+ bpy.ops.object.delete()
+ # bpy.ops.wm.save_as_mainfile(filepath=bpy.data.filepath)
+
+ return True
elif self.update:
self.failed_test(result)
self.update_failed_test(evaluated_test_object)
+ if self.test_updated_counter == 1:
+ self.run_test()
+ else:
+ print("The test fails consistently. Exiting...")
else:
self.failed_test(result)
- # Real implementation.
- pass
def failed_test(self, result):
- print("The test failed with the following: ")
+ print("\nFAILED {} test with the following: ".format(self.test_name))
self._print_result(result)
# Real implementation.
pass
def passed_test(self, result):
- print("The tests passed successfully.")
+ print("\nPASSED {} test successfully.".format(self.test_name))
self._print_result(result)
# Real implementation
pass
@@ -117,7 +147,7 @@ class MeshTest(ABC):
# Save file.
bpy.ops.wm.save_as_mainfile(filepath=bpy.data.filepath)
- self._test_updated = True
+ self.test_updated_counter += 1
self.expected_object = evaluated_test_object
# Real implementation.
@@ -125,7 +155,7 @@ class MeshTest(ABC):
def compare_meshes(self, evaluated_object):
objects = bpy.data.objects
evaluated_test_mesh = objects[evaluated_object.name].data
- expected_mesh = objects[self.exp_object_name].data
+ expected_mesh = self.expected_object.data
result_codes = []
# Mesh Comparison.
@@ -139,12 +169,12 @@ class MeshTest(ABC):
# Selection comparison.
- selected_evaluatated_verts = [
+ selected_evaluated_verts = [
v.index for v in evaluated_test_mesh.vertices if v.select]
selected_expected_verts = [
v.index for v in expected_mesh.vertices if v.select]
- if selected_evaluatated_verts == selected_expected_verts:
+ if selected_evaluated_verts == selected_expected_verts:
result_selection = "Same"
else:
result_selection = "Selection doesn't match."
@@ -169,13 +199,312 @@ class MeshTest(ABC):
class SpecMeshTest(MeshTest):
- def __init__(self, test_name, test_object_name, exp_object_name, operation_stack=None, threshold=None):
+ def __init__(self, test_name, test_object_name, exp_object_name, operations_stack=None, apply_modifier=True,
+ do_compare=True, threshold=None):
+
+ super().__init__(test_object_name, exp_object_name, test_name, threshold)
self.test_name = test_name
- super().__init__(test_object_name, exp_object_name, threshold)
- pass
+ if operations_stack is None:
+ self.operations_stack = []
+ else:
+ self.operations_stack = operations_stack
+ self.apply_modifier = apply_modifier
+ self.do_compare = do_compare
- def apply_operations(self):
- pass
+ def apply_operations(self, evaluated_test_object):
+ # Add modifiers and operators.
+ print("Applying operations...")
+ for operation in self.operations_stack:
+ if isinstance(operation, ModifierSpec):
+ self._add_modifier(evaluated_test_object, operation)
+ if self.apply_modifier:
+ self._apply_modifier(
+ evaluated_test_object, operation.modifier_name)
+
+ elif isinstance(operation, OperatorSpecEditMode):
+ self._apply_operator_edit_mode(
+ evaluated_test_object, operation)
+
+ elif isinstance(operation, OperatorSpecObjectMode):
+ self._apply_operator_object_mode(operation)
+
+ elif isinstance(operation, DeformModifierSpec):
+ self._apply_deform_modifier(evaluated_test_object, operation)
+
+ elif isinstance(operation, ParticleSystemSpec):
+ self._apply_particle_system(evaluated_test_object, operation)
+
+ else:
+ raise ValueError("Expected operation of type {} or {} or {} or {}. Got {}".
+ format(type(ModifierSpec), type(OperatorSpecEditMode),
+ type(OperatorSpecObjectMode), type(ParticleSystemSpec), type(operation)))
+
+ def _set_parameters_impl(self, modifier, modifier_parameters, nested_settings_path, modifier_name):
+ """
+ Doing a depth first traversal of the modifier parameters and setting their values.
+ :param: modifier: Of type modifier, its altered to become a setting in recursion.
+ :param: modifier_parameters : dict or sequence, a simple/nested dictionary of modifier parameters.
+ :param: nested_settings_path : list(stack): helps in tracing path to each node.
+ """
+ if not isinstance(modifier_parameters, dict):
+ param_setting = None
+ for i, setting in enumerate(nested_settings_path):
+
+ # We want to set the attribute only when we have reached the last setting.
+ # Applying of intermediate settings is meaningless.
+ if i == len(nested_settings_path) - 1:
+ setattr(modifier, setting, modifier_parameters)
+
+ elif hasattr(modifier, setting):
+ param_setting = getattr(modifier, setting)
+ # getattr doesn't accept canvas_surfaces["Surface"], but we need to pass it to setattr.
+ if setting == "canvas_surfaces":
+ modifier = param_setting.active
+ else:
+ modifier = param_setting
+ else:
+ # Clean up first
+ bpy.ops.object.delete()
+ raise Exception("Modifier '{}' has no parameter named '{}'".
+ format(modifier_name, setting))
+
+ # It pops the current node before moving on to its sibling.
+ nested_settings_path.pop()
+ return
+
+ for key in modifier_parameters:
+ nested_settings_path.append(key)
+ self._set_parameters_impl(
+ modifier, modifier_parameters[key], nested_settings_path, modifier_name)
+
+ if nested_settings_path:
+ nested_settings_path.pop()
+
+ def set_parameters(self, modifier, modifier_parameters):
+ """
+ Wrapper for _set_parameters_util
+ """
+ settings = []
+ modifier_name = modifier.name
+ self._set_parameters_impl(
+ modifier, modifier_parameters, settings, modifier_name)
+
+ def _add_modifier(self, test_object, modifier
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list