[Bf-blender-cvs] [eb8afc39f85] master: Tests: remove noisy output from bl_pyapi_idprop_datablock

Campbell Barton noreply at git.blender.org
Tue Oct 12 08:59:21 CEST 2021


Commit: eb8afc39f858ca397e53fc8cd36b3ebc0024476e
Author: Campbell Barton
Date:   Tue Oct 12 17:57:41 2021 +1100
Branches: master
https://developer.blender.org/rBeb8afc39f858ca397e53fc8cd36b3ebc0024476e

Tests: remove noisy output from bl_pyapi_idprop_datablock

As part of expected behavior this printed an exception,
making it seem as if there was an error in the test.

Now the exception is suppressed from the output, ensuring it matches
an the expected output.

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

M	tests/python/bl_pyapi_idprop_datablock.py

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

diff --git a/tests/python/bl_pyapi_idprop_datablock.py b/tests/python/bl_pyapi_idprop_datablock.py
index 6cc99154cfe..d4253dc4665 100644
--- a/tests/python/bl_pyapi_idprop_datablock.py
+++ b/tests/python/bl_pyapi_idprop_datablock.py
@@ -18,13 +18,17 @@
 
 # ./blender.bin --background -noaudio --python tests/python/bl_pyapi_idprop_datablock.py -- --verbose
 
-import bpy
-import sys
+import contextlib
+import inspect
+import io
 import os
+import re
+import sys
 import tempfile
-import inspect
-from bpy.types import UIList
 
+import bpy
+
+from bpy.types import UIList
 arr_len = 100
 ob_cp_count = 100
 
@@ -49,13 +53,40 @@ def print_fail_msg_and_exit(msg):
     os._exit(1)
 
 
-def abort_if_false(expr, msg=None):
+def expect_false_or_abort(expr, msg=None):
     if not expr:
         if not msg:
             msg = "test failed"
         print_fail_msg_and_exit(msg)
 
 
+def expect_exception_or_abort(*, fn, ex):
+    try:
+        fn()
+        exception = False
+    except ex:
+        exception = True
+    if exception:
+        return  # OK
+    print_fail_msg_and_exit("test failed")
+
+
+def expect_ouput_or_abort(*, fn, match_stderr=None, match_stdout=None):
+
+    stdout, stderr = io.StringIO(), io.StringIO()
+
+    with (contextlib.redirect_stderr(stderr), contextlib.redirect_stdout(stdout)):
+        fn()
+
+    for (handle, match) in ((stdout, match_stdout), (stderr, match_stderr)):
+        if not match:
+            continue
+        handle.seek(0)
+        output = handle.read()
+        if not re.match(match, output):
+            print_fail_msg_and_exit("%r not found in %r" % (match, output))
+
+
 class TestClass(bpy.types.PropertyGroup):
     test_prop: bpy.props.PointerProperty(type=bpy.types.Object)
     name: bpy.props.StringProperty()
@@ -71,14 +102,6 @@ def get_scene(lib_name, sce_name):
                 return s
 
 
-def check_crash(fnc, args=None):
-    try:
-        fnc(args) if args else fnc()
-    except:
-        return
-    print_fail_msg_and_exit("test failed")
-
-
 def init():
     bpy.utils.register_class(TestClass)
     bpy.types.Object.prop_array = bpy.props.CollectionProperty(
@@ -122,12 +145,13 @@ def make_lib():
 
 def check_lib():
     # check pointer
-    abort_if_false(bpy.data.objects["Cube"].prop == bpy.data.objects['Camera'])
+    expect_false_or_abort(bpy.data.objects["Cube"].prop == bpy.data.objects['Camera'])
 
     # check array of pointers in duplicated object
     for i in range(0, arr_len):
-        abort_if_false(bpy.data.objects["Cube.001"].prop_array[i].test_prop ==
-                       bpy.data.objects['Light'])
+        expect_false_or_abort(
+            bpy.data.objects["Cube.001"].prop_array[i].test_prop ==
+            bpy.data.objects['Light'])
 
 
 def check_lib_linking():
@@ -140,9 +164,9 @@ def check_lib_linking():
 
     o = bpy.data.scenes["Scene_lib"].objects['Unique_Cube']
 
-    abort_if_false(o.prop_array[0].test_prop == bpy.data.scenes["Scene_lib"].objects['Light'])
-    abort_if_false(o.prop == bpy.data.scenes["Scene_lib"].objects['Camera'])
-    abort_if_false(o.prop.library == o.library)
+    expect_false_or_abort(o.prop_array[0].test_prop == bpy.data.scenes["Scene_lib"].objects['Light'])
+    expect_false_or_abort(o.prop == bpy.data.scenes["Scene_lib"].objects['Camera'])
+    expect_false_or_abort(o.prop.library == o.library)
 
     bpy.ops.wm.save_as_mainfile(filepath=test_path)
 
@@ -162,9 +186,10 @@ def check_linked_scene_copying():
 
     # check node's props
     # must point to own scene camera
-    abort_if_false(intern_sce.node_tree.nodes['Render Layers']["prop"] and
-                   not (intern_sce.node_tree.nodes['Render Layers']["prop"] ==
-                        extern_sce.node_tree.nodes['Render Layers']["prop"]))
+    expect_false_or_abort(
+        intern_sce.node_tree.nodes['Render Layers']["prop"] and
+        not (intern_sce.node_tree.nodes['Render Layers']["prop"] ==
+             extern_sce.node_tree.nodes['Render Layers']["prop"]))
 
 
 def check_scene_copying():
@@ -183,8 +208,9 @@ def check_scene_copying():
 
     # check node's props
     # must point to own scene camera
-    abort_if_false(not (first_sce.node_tree.nodes['Render Layers']["prop"] ==
-                        second_sce.node_tree.nodes['Render Layers']["prop"]))
+    expect_false_or_abort(
+        not (first_sce.node_tree.nodes['Render Layers']["prop"] ==
+             second_sce.node_tree.nodes['Render Layers']["prop"]))
 
 
 # count users
@@ -194,11 +220,11 @@ def test_users_counting():
     n = 1000
     for i in range(0, n):
         bpy.data.objects["Cube"]["a%s" % i] = bpy.data.objects["Light"].data
-    abort_if_false(bpy.data.objects["Light"].data.users == Light_us + n)
+    expect_false_or_abort(bpy.data.objects["Light"].data.users == Light_us + n)
 
     for i in range(0, int(n / 2)):
         bpy.data.objects["Cube"]["a%s" % i] = 1
-    abort_if_false(bpy.data.objects["Light"].data.users == Light_us + int(n / 2))
+    expect_false_or_abort(bpy.data.objects["Light"].data.users == Light_us + int(n / 2))
 
 
 # linking
@@ -240,16 +266,22 @@ def test_restrictions1():
             self.layout.template_ID(context.scene, "prop1")
             self.layout.prop_search(context.scene, "prop2", bpy.data, "node_groups")
 
-            op = self.layout.operator("scene.test_op")
+            op = self.layout.operator(TEST_Op.bl_idname)
             op.str_prop = "test string"
 
-            def test_fnc(op):
+            def test_fn(op):
                 op["ob"] = bpy.data.objects['Unique_Cube']
-            check_crash(test_fnc, op)
-            abort_if_false(not hasattr(op, "id_prop"))
+            expect_exception_or_abort(
+                fn=lambda: test_fn(op),
+                ex=ImportError,
+            )
+            expect_false_or_abort(not hasattr(op, "id_prop"))
 
     bpy.utils.register_class(TEST_PT_DatablockProp)
-    bpy.utils.register_class(TEST_Op)
+    expect_ouput_or_abort(
+        fn=lambda: bpy.utils.register_class(TEST_Op),
+        match_stderr="^ValueError: bpy_struct \"SCENE_OT_test_op\" registration error:",
+    )
 
     def poll(self, value):
         return value.name in bpy.data.scenes["Scene_lib"].objects
@@ -270,12 +302,18 @@ def test_restrictions1():
         # NodeTree id_prop
         bpy.context.scene.prop2 = bpy.data.objects["Light.001"]
 
-    check_crash(sub_test)
+    expect_exception_or_abort(
+        fn=sub_test,
+        ex=TypeError,
+    )
 
     bpy.context.scene.prop2 = bpy.data.node_groups.new("Shader", "ShaderNodeTree")
 
-    print("Please, test GUI performance manually on the Render tab, '%s' panel" %
-          TEST_PT_DatablockProp.bl_label, file=sys.stderr)
+    # NOTE: keep since the author thought this useful information.
+    # print(
+    #     "Please, test GUI performance manually on the Render tab, '%s' panel" %
+    #     TEST_PT_DatablockProp.bl_label, file=sys.stderr,
+    # )
     sys.stderr.flush()
 
 
@@ -318,8 +356,14 @@ def test_restrictions2():
         def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
             layout.prop(item, "name", text="", emboss=False, icon_value=icon)
 
-    check_crash(bpy.utils.register_class, TestPrefs)
-    check_crash(bpy.utils.register_class, TEST_UL_list)
+    expect_exception_or_abort(
+        fn=lambda: bpy.utils.register_class(TestPrefs),
+        ex=ValueError,
+    )
+    expect_exception_or_abort(
+        fn=lambda: bpy.utils.register_class(TEST_UL_list),
+        ex=ValueError,
+    )
 
     bpy.utils.unregister_class(TestClassCollection)
 
@@ -335,7 +379,10 @@ def main():
         test_users_counting()
         test_linking()
         test_restrictions1()
-        check_crash(test_regressions)
+        expect_exception_or_abort(
+            fn=test_regressions,
+            ex=AttributeError,
+        )
         test_restrictions2()



More information about the Bf-blender-cvs mailing list