[Bf-blender-cvs] [2edc2136a1d] soc-2021-geometry-nodes-regression-test: WIP: Saving work, Mesh Test Abstract class implementattion complete, updating to Win 11

Himanshi Kalra noreply at git.blender.org
Sat Jul 3 10:48:07 CEST 2021


Commit: 2edc2136a1d89e4fdeafa7df127a1e4df18fb9db
Author: Himanshi Kalra
Date:   Sat Jul 3 14:17:38 2021 +0530
Branches: soc-2021-geometry-nodes-regression-test
https://developer.blender.org/rB2edc2136a1d89e4fdeafa7df127a1e4df18fb9db

WIP: Saving work, Mesh Test Abstract class implementattion complete, updating to Win 11

===================================================================

M	tests/python/modules/base_mesh_test.py
A	tests/python/modules/spec_classes.py
A	tests/python/test_classes.py

===================================================================

diff --git a/tests/python/modules/base_mesh_test.py b/tests/python/modules/base_mesh_test.py
index d07f5485041..1e8f48b74fc 100644
--- a/tests/python/modules/base_mesh_test.py
+++ b/tests/python/modules/base_mesh_test.py
@@ -3,6 +3,8 @@ import bpy
 import os
 import sys
 
+from modules.spec_classes import ModifierSpec, DeformModifierSpec, OperatorSpecEditMode, OperatorSpecObjectMode
+
 
 class MeshTest(ABC):
     def __init__(self, test_object_name, exp_object_name, threshold=None):
@@ -10,37 +12,123 @@ class MeshTest(ABC):
         self.exp_object_name = exp_object_name
         self.threshold = threshold
         self.update = os.getenv("BLENDER_TEST_UPDATE") is not None
-        self.eval_object_name = "evaluated_object"
+        # self.eval_object_name = "evaluated_object"
+
+        # Private flag to indicate whether the blend file was updated after the test.
+        self._test_updated = False
+        objects = bpy.data.objects
+        self.test_object = objects[self.test_object_name]
+
+        # TODO - create exp object, in case doesn't exist.
+        self.expected_object = objects[self.exp_object_name]
 
     def create_evaluated_object(self):
+        bpy.context.view_layer.objects.active = self.test_object
+
+        # Duplicate test object.
+        bpy.ops.object.mode_set(mode="OBJECT")
+        bpy.ops.object.select_all(action="DESELECT")
+        bpy.context.view_layer.objects.active = self.test_object
+
+        self.test_object.select_set(True)
+        bpy.ops.object.duplicate()
+        evaluated_test_object = bpy.context.active_object
+        evaluated_test_object.name = "evaluated_object"
         # Real implementation.
-        pass
+        return evaluated_test_object
+
+    @staticmethod
+    def _print_result(result):
+        comparison_result, selection_result, validation_result = result
+        print("Mesh Compariosn: {}".format(comparison_result))
+        print("Selection Result: {}".format(selection_result))
+        print("Mesh Validation: {}".format(validation_result))
 
     def run_test(self):
+        evaluated_test_object = self.create_evaluated_object()
+        self.apply_operations(evaluated_test_object)
+        result = self.compare_meshes(evaluated_test_object)
+
+        comparison_result, selection_result, validation_result = result
+
+        if comparison_result == "Same" and selection_result == "Same" and validation_result == "Valid":
+            self.passed_test(result)
+
+        elif self.update:
+            self.failed_test(result)
+            self.update_failed_test(evaluated_test_object)
+
+        else:
+            self.failed_test(result)
+
         # Real implementation.
         pass
 
-    def failed_test(self):
+    def failed_test(self, result):
+        print("The test failed with the following: ")
+        self._print_result(result)
         # Real implementation.
         pass
 
-    def passed_test(self):
+    def passed_test(self, result):
+        print("The tests passed successfully.")
+        self._print_result(result)
         # Real implementation
         pass
 
-    def update_failed_test(self):
-        if self.failed_test() and self.update:
-            self.create_evaluated_object()
-        # Real implementation
-        pass
+    def do_selection(self, mesh: bpy.types.Mesh, select_mode: str, selection: set):
+        """
+        Do selection on a mesh
+        :param mesh: bpy.types.Mesh - input mesh
+        :param: select_mode: str - selection mode. Must be 'VERT', 'EDGE' or 'FACE'
+        :param: selection: set - indices of selection.
+
+        Example: select_mode='VERT' and selection={1,2,3} selects veritces 1, 2 and 3 of input mesh
+        """
+        # deselect all
+        bpy.ops.object.mode_set(mode='EDIT')
+        bpy.ops.mesh.select_all(action='DESELECT')
+        bpy.ops.object.mode_set(mode='OBJECT')
+
+        bpy.context.tool_settings.mesh_select_mode = (select_mode == 'VERT',
+                                                      select_mode == 'EDGE',
+                                                      select_mode == 'FACE')
+
+        items = (mesh.vertices if select_mode == 'VERT'
+                 else mesh.edges if select_mode == 'EDGE'
+                 else mesh.polygons if select_mode == 'FACE'
+                 else None)
+        if items is None:
+            raise ValueError("Invalid selection mode")
+        for index in selection:
+            items[index].select = True
+
+    def update_failed_test(self, evaluated_test_object):
+        # Update expected object.
+        evaluated_test_object.location = self.expected_object.location
+        expected_object_name = self.expected_object.name
+        evaluated_selection = {
+            v.index for v in evaluated_test_object.data.vertices if v.select}
+
+        bpy.data.objects.remove(self.expected_object, do_unlink=True)
+        evaluated_test_object.name = expected_object_name
+        self.do_selection(evaluated_test_object.data,
+                          "VERT", evaluated_selection)
+
+        # Save file.
+        bpy.ops.wm.save_as_mainfile(filepath=bpy.data.filepath)
+        self._test_updated = True
+        self.expected_object = evaluated_test_object
+
+        # Real implementation.
 
-    def compare_meshes(self, evaluated_object, with_selection=True):
+    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
         result_codes = []
 
-        # Mesh Comparison
+        # Mesh Comparison.
         if self.threshold:
             result_mesh = expected_mesh.unit_test_compare(
                 mesh=evaluated_test_mesh, threshold=self.threshold)
@@ -50,37 +138,40 @@ class MeshTest(ABC):
         result_codes.append(result_mesh)
 
         # Selection comparison.
-        if with_selection:
-            selected_evaluatated_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:
-                result_selection = "Same"
-            else:
-                result_selection = "Selection doesn't match."
-        else:
-            result_selection = "NA"
 
+        selected_evaluatated_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:
+            result_selection = "Same"
+        else:
+            result_selection = "Selection doesn't match."
         result_codes.append(result_selection)
 
         # Validation check.
-        # TODO
+        result_validation = evaluated_test_mesh.validate(verbose=True)
+        if result_validation:
+            result_validation = "Invalid Mesh"
+        else:
+            result_validation = "Valid"
+        result_codes.append(result_validation)
 
         return result_codes
 
     @abstractmethod
-    def apply_operations(self):
+    def apply_operations(self, evaluated_test_object):
         pass
 
     def __repr__(self):
         return "MeshTest({}, {} )".format(self.test_object_name, self.exp_object_name)
 
 
-class SpecTest(MeshTest):
-    def __init__(self, test_object_name, exp_object_name, threshold=None, operation_stack=None):
-        super.__init__(test_object_name, exp_object_name, threshold=None)
+class SpecMeshTest(MeshTest):
+    def __init__(self, test_name, test_object_name, exp_object_name, operation_stack=None, threshold=None):
+        self.test_name = test_name
+        super().__init__(test_object_name, exp_object_name, threshold)
         pass
 
     def apply_operations(self):
@@ -88,12 +179,21 @@ class SpecTest(MeshTest):
 
 
 class BlendFileTest(MeshTest):
-    def apply_operations(self):
-        pass
+    def apply_operations(self, evaluated_test_object):
+        """
+        Apply all modifiers (Geometry Nodes for now) added to the current object [Discuss]
+        """
+        # select_only_object(evaluated_test_object)
+
+        modifiers_list = evaluated_test_object.modifiers
+
+        for modifier in modifiers_list:
+            bpy.ops.object.modifier_apply(modifier=modifier.name)
 
 
 geometry_nodes_test = BlendFileTest("test_object", "expected_object")
 geometry_nodes_test.run_test()
 
-modifier_test = SpecTest("test_array", "exp_array", operation_stack=[])
+modifier_test = SpecMeshTest("test_name", "test_array",
+                             "exp_array", operation_stack=[])
 modifier_test.run_test()
diff --git a/tests/python/modules/spec_classes.py b/tests/python/modules/spec_classes.py
new file mode 100644
index 00000000000..8416bc60aa0
--- /dev/null
+++ b/tests/python/modules/spec_classes.py
@@ -0,0 +1,168 @@
+# ##### 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>
+
+# A framework to run regression tests on mesh modifiers and operators based on howardt's mesh_ops_test.py
+#
+# General idea:
+# A test is:
+#    Object mode
+#    Select <test_object>
+#    Duplicate the object
+#    Select the object
+#    Apply operation for each operation in <operations_stack> with given parameters
+#    (an operation is either a modifier or an operator)
+#    tes

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list