Python tests: Split re-usable test related functionality to a module
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 1 Mar 2018 16:39:57 +0000 (17:39 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 1 Mar 2018 16:44:35 +0000 (17:44 +0100)
The idea is to avoid re-implementing this for an upcoming FFmpeg tests.

tests/python/alembic_tests.py
tests/python/modules/test_utils.py [new file with mode: 0755]

index 96a68de..b9dc78a 100755 (executable)
@@ -28,37 +28,17 @@ import sys
 import tempfile
 import unittest
 
+from modules.test_utils import (with_tempdir,
+                                AbstractBlenderRunnerTest,
+                                )
 
-def with_tempdir(wrapped):
-    """Creates a temporary directory for the function, cleaning up after it returns normally.
-
-    When the wrapped function raises an exception, the contents of the temporary directory
-    remain available for manual inspection.
-
-    The wrapped function is called with an extra positional argument containing
-    the pathlib.Path() of the temporary directory.
-    """
-
-    @functools.wraps(wrapped)
-    def decorator(*args, **kwargs):
-        dirname = tempfile.mkdtemp(prefix='blender-alembic-test')
-        try:
-            retval = wrapped(*args, pathlib.Path(dirname), **kwargs)
-        except:
-            print('Exception in %s, not cleaning up temporary directory %s' % (wrapped, dirname))
-            raise
-        else:
-            shutil.rmtree(dirname)
-        return retval
-
-    return decorator
 
 
 class AbcPropError(Exception):
     """Raised when AbstractAlembicTest.abcprop() finds an error."""
 
 
-class AbstractAlembicTest(unittest.TestCase):
+class AbstractAlembicTest(AbstractBlenderRunnerTest):
     @classmethod
     def setUpClass(cls):
         import re
@@ -74,37 +54,6 @@ class AbstractAlembicTest(unittest.TestCase):
         # 'abcls' array notation, like "name[16]"
         cls.abcls_array = re.compile(r'^(?P<name>[^\[]+)(\[(?P<arraysize>\d+)\])?$')
 
-    def run_blender(self, filepath: str, python_script: str, timeout: int=300) -> str:
-        """Runs Blender by opening a blendfile and executing a script.
-
-        Returns Blender's stdout + stderr combined into one string.
-
-        :param filepath: taken relative to self.testdir.
-        :param timeout: in seconds
-        """
-
-        blendfile = self.testdir / filepath
-
-        command = (
-            self.blender,
-            '--background',
-            '-noaudio',
-            '--factory-startup',
-            '--enable-autoexec',
-            str(blendfile),
-            '-E', 'CYCLES',
-            '--python-exit-code', '47',
-            '--python-expr', python_script,
-        )
-
-        proc = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
-                              timeout=timeout)
-        output = proc.stdout.decode('utf8')
-        if proc.returncode:
-            self.fail('Error %d running Blender:\n%s' % (proc.returncode, output))
-
-        return output
-
     def abcprop(self, filepath: pathlib.Path, proppath: str) -> dict:
         """Uses abcls to obtain compound property values from an Alembic object.
 
diff --git a/tests/python/modules/test_utils.py b/tests/python/modules/test_utils.py
new file mode 100755 (executable)
index 0000000..489f36c
--- /dev/null
@@ -0,0 +1,97 @@
+#!/usr/bin/env python3
+# ##### 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>
+
+import argparse
+import functools
+import shutil
+import pathlib
+import re
+import subprocess
+import sys
+import tempfile
+import unittest
+
+
+def with_tempdir(wrapped):
+    """Creates a temporary directory for the function, cleaning up after it returns normally.
+
+    When the wrapped function raises an exception, the contents of the temporary directory
+    remain available for manual inspection.
+
+    The wrapped function is called with an extra positional argument containing
+    the pathlib.Path() of the temporary directory.
+    """
+
+    @functools.wraps(wrapped)
+    def decorator(*args, **kwargs):
+        dirname = tempfile.mkdtemp(prefix='blender-alembic-test')
+        try:
+            retval = wrapped(*args, pathlib.Path(dirname), **kwargs)
+        except:
+            print('Exception in %s, not cleaning up temporary directory %s' % (wrapped, dirname))
+            raise
+        else:
+            shutil.rmtree(dirname)
+        return retval
+
+    return decorator
+
+
+class AbstractBlenderRunnerTest(unittest.TestCase):
+    """Base class for all test suites which needs to run Blender"""
+
+    @classmethod
+    def setUpClass(cls):
+        global args
+        cls.blender = args.blender
+        cls.testdir = pathlib.Path(args.testdir)
+
+    def run_blender(self, filepath: str, python_script: str, timeout: int=300) -> str:
+        """Runs Blender by opening a blendfile and executing a script.
+
+        Returns Blender's stdout + stderr combined into one string.
+
+        :param filepath: taken relative to self.testdir.
+        :param timeout: in seconds
+        """
+
+        blendfile = self.testdir / filepath
+
+        command = (
+            self.blender,
+            '--background',
+            '-noaudio',
+            '--factory-startup',
+            '--enable-autoexec',
+            str(blendfile),
+            '-E', 'CYCLES',
+            '--python-exit-code', '47',
+            '--python-expr', python_script,
+        )
+
+        proc = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+                              timeout=timeout)
+        output = proc.stdout.decode('utf8')
+        if proc.returncode:
+            self.fail('Error %d running Blender:\n%s' % (proc.returncode, output))
+
+        return output
+