tornavis/tests/python/curves_extrude.py

193 lines
6.8 KiB
Python

# 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()