1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
# SPDX-FileCopyrightText: 2020-2023 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
from abc import ABC, abstractmethod
import bpy
import os
import sys
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
from modules.mesh_test import RunTest
class CurvesTest(ABC):
def __init__(self, test_object_name, exp_object_name, test_name=None):
self.test_object_name = test_object_name
self.exp_object_name = exp_object_name
self.test_object = bpy.data.objects[self.test_object_name]
self.expected_object = bpy.data.objects[self.exp_object_name]
self.verbose = os.getenv("BLENDER_VERBOSE") is not None
if test_name:
self.test_name = test_name
else:
filepath = bpy.data.filepath
self.test_name = bpy.path.display_name_from_filepath(filepath)
self._failed_tests_list = []
def create_evaluated_object(self):
"""
Creates an evaluated object.
"""
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()
self.evaluated_object = bpy.context.active_object
self.evaluated_object.name = "evaluated_object"
@staticmethod
def _print_result(result):
"""
Prints the comparison, selection and validation result.
"""
print("Results:")
for key in result:
print("{} : {}".format(key, result[key][1]))
print()
def run_test(self):
"""
Runs a single test, runs it again if test file is updated.
"""
print("\nSTART {} test.".format(self.test_name))
self.create_evaluated_object()
self.apply_operations()
result = self.compare_objects(self.evaluated_object, self.expected_object)
# Initializing with True to get correct resultant of result_code booleans.
success = True
inside_loop_flag = False
for key in result:
inside_loop_flag = True
success = success and result[key][0]
# Check "success" is actually evaluated and is not the default True value.
if not inside_loop_flag:
success = False
if success:
self.print_passed_test_result(result)
# Clean up.
if self.verbose:
print("Cleaning up...")
# Delete evaluated_test_object.
bpy.ops.object.delete()
return True
else:
self.print_failed_test_result(result)
return False
@abstractmethod
def apply_operations(self, evaluated_test_object_name):
pass
@staticmethod
def compare_curves(evaluated_curves, expected_curves):
if len(evaluated_curves.attributes.items()) != len(expected_curves.attributes.items()):
print("Attribute count doesn't match")
for a_idx, attribute in evaluated_curves.attributes.items():
expected_attribute = expected_curves.attributes[a_idx]
if len(attribute.data.items()) != len(expected_attribute.data.items()):
print("Attribute data length doesn't match")
value_attr_name = (
'vector' if attribute.data_type == 'FLOAT_VECTOR' or
attribute.data_type == 'FLOAT2' else
'color' if attribute.data_type == 'FLOAT_COLOR' else 'value'
)
for v_idx, attribute_value in attribute.data.items():
if getattr(
attribute_value,
value_attr_name) != getattr(
expected_attribute.data[v_idx],
value_attr_name):
print("Attribute '{}' values do not match".format(attribute.name))
return False
return True
def compare_objects(self, evaluated_object, expected_object):
result_codes = {}
equal = self.compare_curves(evaluated_object.data, expected_object.data)
result_codes['Curves Comparison'] = (equal, evaluated_object.data)
return result_codes
def print_failed_test_result(self, result):
"""
Print results for failed test.
"""
print("FAILED {} test with the following: ".format(self.test_name))
def print_passed_test_result(self, result):
"""
Print results for passing test.
"""
print("PASSED {} test successfully.".format(self.test_name))
class CurvesOpTest(CurvesTest):
def __init__(self, test_name, test_object_name, exp_object_name, operators_stack):
super().__init__(test_object_name, exp_object_name, test_name)
self.operators_stack = operators_stack
def apply_operations(self):
for operator_name in self.operators_stack:
bpy.ops.object.mode_set(mode='EDIT')
curves_operator = getattr(bpy.ops.curves, operator_name)
try:
retval = curves_operator()
except AttributeError:
raise AttributeError("bpy.ops.curves has no attribute {}".format(operator_name))
except TypeError as ex:
raise TypeError("Incorrect operator parameters {!r} raised {!r}".format([], ex))
if retval != {'FINISHED'}:
raise RuntimeError("Unexpected operator return value: {}".format(operator_name))
bpy.ops.object.mode_set(mode='OBJECT')
def main():
tests = [
CurvesOpTest("Extrude 1 Point Curve", "a_test1PointCurve", "a_test1PointCurveExpected", ['extrude']),
CurvesOpTest("Extrude Middle Points", "b_testMiddlePoints", "b_testMiddlePointsExpected", ['extrude']),
CurvesOpTest("Extrude End Points", "c_testEndPoints", "c_testEndPointsExpected", ['extrude']),
CurvesOpTest("Extrude Neighbors In Separate Curves", "d_testNeighborsInCurves", "d_testNeighborsInCurvesExpected", ['extrude']),
CurvesOpTest("Extrude Edge Curves", "e_testEdgeCurves", "e_testEdgeCurvesExpected", ['extrude']),
CurvesOpTest("Extrude Middle Curve", "f_testMiddleCurve", "f_testMiddleCurveExpected", ['extrude']),
CurvesOpTest("Extrude All Points", "g_testAllPoints", "g_testAllPointsExpected", ['extrude'])
]
curves_extrude_test = RunTest(tests)
command = list(sys.argv)
for i, cmd in enumerate(command):
if cmd == "--run-all-tests":
curves_extrude_test.do_compare = True
curves_extrude_test.run_all_tests()
break
elif cmd == "--run-test":
curves_extrude_test.do_compare = False
name = command[i + 1]
curves_extrude_test.run_test(name)
break
if __name__ == "__main__":
main()
|