From 7c2b58caae69c0e37df1301bca1963afd04b4521 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 21 Nov 2014 12:44:55 +0100 Subject: [PATCH] re-work blend file testing - dependencies are returned as a list - improve failing to check if the blend creation worked - add commments explaining strange workarounds --- tests/blendfile_templates.py | 27 ++++-- tests/test_cli.py | 175 ++++++++++++++++++++++++++--------- 2 files changed, 151 insertions(+), 51 deletions(-) diff --git a/tests/blendfile_templates.py b/tests/blendfile_templates.py index fdd5936..07813b8 100644 --- a/tests/blendfile_templates.py +++ b/tests/blendfile_templates.py @@ -23,22 +23,26 @@ def _clear_blend(): bpy_data_iter.remove(id_data) -def create_blank(): - pass +def create_blank(deps): + assert(isinstance(deps, list)) -def create_image_single(): +def create_image_single(deps): import bpy + + path = "//my_image.png" image = bpy.data.images.new(name="MyImage", width=512, height=512) - image.filepath_raw = "//my_image.png" + image.filepath_raw = path + deps.append(bpy.path.abspath(path)) image.file_format = 'PNG' image.use_fake_user = True image.save() + if __name__ == "__main__": import sys - blendfile, create_id, returncode = sys.argv[-3:] + blendfile, blendfile_deps_json, create_id, returncode = sys.argv[-4:] returncode = int(returncode) create_fn = globals()[create_id] @@ -53,7 +57,18 @@ if __name__ == "__main__": # ---- _clear_blend() - create_fn() + deps = [] + create_fn(deps) + if deps: + with open(blendfile_deps_json, 'w') as f: + import json + json.dump( + deps, f, ensure_ascii=False, + check_circular=False, + # optional (pretty) + sort_keys=True, indent=4, separators=(',', ': '), + ) + del json import bpy bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=blendfile) diff --git a/tests/test_cli.py b/tests/test_cli.py index 8223555..9768143 100755 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -39,6 +39,13 @@ del os, sys, path # ----------------------------------------- # Ensure we get stdout & stderr on sys.exit +# +# We have this because we override the standard output, +# _AND_ during this state a command may call `sys.exit` +# In this case, we the output is hidden which is very annoying. +# +# So override `sys.exit` with one that prints to the original +# stdout/stderr on exit. if 1: import sys @@ -72,6 +79,13 @@ if 1: # -------------------------------------------- # Don't Exit when argparse fails to parse args +# +# Argparse can call `sys.exit` if the wrong args are given. +# This messes with testing, which we want to keep the process running. +# +# This monkey-patches in an exist function which simply raises an exception. +# We could do something a bit nicer here, +# but for now just use a basic exception. import argparse def argparse_fake_exit(self, status, message): sys.__stdout__.write(message) @@ -276,6 +290,44 @@ def file_quick_touch(path, filepart=None, times=None): os.utime(path, times) +def blendfile_template_create(blendfile, create_id, deps): + returncode_test = 123 + blendfile_deps_json = os.path.join(TEMP, "blend_template_deps.json") + os.makedirs(os.path.dirname(blendfile), exist_ok=True) + stdout, stderr, returncode = run( + ("blender", + "--background", + "--factory-startup", + "-noaudio", + "--python", + os.path.join(CURRENT_DIR, "blendfile_templates.py"), + "--", + blendfile, + blendfile_deps_json, + create_id, + str(returncode_test), + )) + + if os.path.exists(blendfile_deps_json): + import json + with open(blendfile_deps_json, 'r') as f: + deps[:] = json.load(f) + os.remove(blendfile_deps_json) + else: + deps.clear() + + if returncode != returncode_test: + # verbose will have already printed + if not VERBOSE: + print(">>> ", args_as_string(cmd)) + sys.stdout.write(" stdout: %s\n" % stdout.strip()) + sys.stdout.write(" stderr: %s\n" % stderr.strip()) + sys.stdout.write(" return: %d\n" % returncode) + return False + else: + return True + + def wait_for_input(): """for debugging, so we can inspect the state of the system before the test finished. @@ -347,7 +399,8 @@ def server(mode='testing', debug=False): return p -def global_setup(): +def global_setup(use_server=True): + data = [] if VERBOSE: # for server @@ -357,14 +410,20 @@ def global_setup(): shutil.rmtree(TEMP_SERVER, ignore_errors=True) shutil.rmtree(TEMP, ignore_errors=True) - p = server() - data = p + + if use_server: + p = server() + data.append(p) + return data -def global_teardown(data): - p = data - p.terminate() +def global_teardown(data, use_server=True): + + if use_server: + p = data.pop(0) + p.terminate() + shutil.rmtree(TEMP_SERVER, ignore_errors=True) shutil.rmtree(TEMP, ignore_errors=True) @@ -375,6 +434,27 @@ def global_teardown(data): import unittest +class BamSimpleTestCase(unittest.TestCase): + """ Basic testcase, only make temp dirs. + """ + def setUp(self): + + # for running single tests + if __name__ != "__main__": + self._data = global_setup(use_server=False) + + if not os.path.isdir(TEMP): + os.makedirs(TEMP) + + def tearDown(self): + # input('Wait:') + shutil.rmtree(TEMP) + + # for running single tests + if __name__ != "__main__": + global_teardown(self._data, use_server=False) + + class BamSessionTestCase(unittest.TestCase): def setUp(self): @@ -536,60 +616,63 @@ class BamCommitTest(BamSessionTestCase): stdout, stderr = bam_run(["checkout", "testfile.txt"], proj_path) self.assertEqual("", stderr) # wait_for_input() - self.assertEqual(True, os.path.exists(os.path.join(proj_path, "testfile/testfile.txt"))) + self.assertTrue(os.path.exists(os.path.join(proj_path, "testfile/testfile.txt"))) file_data_test = file_quick_read(os.path.join(proj_path, "testfile/testfile.txt")) self.assertEqual(file_data, file_data_test) -class BamBlendTest(BamSessionTestCase): - - def __init__(self, *args): - self.init_defaults() - super().__init__(*args) - - @staticmethod - def create_blend_id(blendfile, create_id, returncode_test): - os.makedirs(os.path.dirname(blendfile), exist_ok=True) - stdout, stderr, returncode = run( - ("blender", - "--background", - "--factory-startup", - "-noaudio", - "--python", - os.path.join(CURRENT_DIR, "blendfile_templates.py"), - "--", - blendfile, - create_id, - str(returncode_test), - )) - return stdout, stderr, returncode +class BamBlendTest(BamSimpleTestCase): def test_create_all(self): """ This simply tests all the create functions run without error. """ import blendfile_templates - returncode_test = 42 + TEMP_SESSION = os.path.join(TEMP, "blend_file_template") + + def iter_files_session(): + for dirpath, dirnames, filenames in os.walk(TEMP_SESSION): + for filename in filenames: + filepath = os.path.join(dirpath, filename) + yield filepath + for create_id, create_fn in blendfile_templates.__dict__.items(): - if create_id.startswith("create_"): - if create_fn.__class__.__name__ == "function": - blendfile = os.path.join(TEMP, create_id + ".blend") + if (create_id.startswith("create_") and + create_fn.__class__.__name__ == "function"): - stdout, stderr, returncode = self.create_blend_id(blendfile, create_id, returncode_test) + os.makedirs(TEMP_SESSION) - self.assertEqual(b'', stderr) - self.assertEqual(True, os.path.exists(blendfile)) - self.assertEqual(returncode, returncode_test) - with open(blendfile, 'rb') as blendfile_handle: - self.assertEqual(b'BLENDER', blendfile_handle.read(7)) - os.remove(blendfile) + blendfile = os.path.join(TEMP, create_id + ".blend") + deps = [] + + if not blendfile_template_create(blendfile, create_id, deps): + # self.fail("blend file couldn't be create") + # ... we want to keep running + self.assertTrue(False, True) # GRR, a better way? + shutil.rmtree(TEMP_SESSION) + continue + + self.assertTrue(os.path.exists(blendfile)) + with open(blendfile, 'rb') as blendfile_handle: + self.assertEqual(b'BLENDER', blendfile_handle.read(7)) + os.remove(blendfile) + + # check all deps are accounted for + for f in deps: + self.assertTrue(os.path.exists(f)) + for f in iter_files_session(): + self.assertIn(f, deps) + + shutil.rmtree(TEMP_SESSION) def test_empty(self): blendfile = os.path.join(TEMP, "test.blend") - returncode_test = 13 - stdout, stderr, returncode = self.create_blend_id(blendfile, "create_blank", returncode_test) - self.assertEqual(True, os.path.exists(blendfile)) - self.assertEqual(returncode_test, returncode) + if not blendfile_template_create(blendfile, "create_blank", []): + self.fail("blend file couldn't be created") + return + + self.assertTrue(os.path.exists(blendfile)) + class BamDeleteTest(BamSessionTestCase): @@ -614,7 +697,9 @@ class BamDeleteTest(BamSessionTestCase): # now do a real commit returncode_test = 42 blendfile = os.path.join(session_path, "testfile.blend") - stdout, stderr, returncode = BamBlendTest.create_blend_id(blendfile, "create_blank", returncode_test) + if not blendfile_template_create(blendfile, "create_blank", []): + self.fail("blend file couldn't be created") + return stdout, stderr = bam_run(["commit", "-m", "tests message"], session_path) self.assertEqual("", stderr)