Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(244)

Unified Diff: tools/tests/base_unittest.py

Issue 397103003: combine base_unittest.py modules from gm and tools (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: pylint Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gm/rebaseline_server/imagepair_test.py ('k') | tools/tests/fix_pythonpath.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/tests/base_unittest.py
diff --git a/tools/tests/base_unittest.py b/tools/tests/base_unittest.py
index f7ee570a246cc5a0f6e74ffba8868746927585e3..9ff710f4a1673dbc020083d5c02775188a542de4 100755
--- a/tools/tests/base_unittest.py
+++ b/tools/tests/base_unittest.py
@@ -8,22 +8,77 @@ found in the LICENSE file.
A wrapper around the standard Python unittest library, adding features we need
for various unittests within this directory.
+
+TODO(epoger): Move this into the common repo for broader use? Or at least in
epoger 2014/07/16 20:05:45 As noted here, I would like to move the real base_
+a more common place within the Skia repo?
"""
import errno
+import filecmp
import os
import shutil
-import sys
+import tempfile
import unittest
-# Set the PYTHONPATH to include the tools directory.
-sys.path.append(
- os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
-import find_run_binary
+TRUNK_DIR = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), os.pardir, os.pardir))
class TestCase(unittest.TestCase):
+ def __init__(self, *args, **kwargs):
+ super(TestCase, self).__init__(*args, **kwargs)
+ # Subclasses should override this default value if they want their output
+ # to be automatically compared against expectations (see setUp and tearDown)
+ self._testdata_dir = None
+
+ def setUp(self):
+ """Called before each test."""
+ # Get the name of this test, in such a way that it will be consistent
+ # regardless of the directory it is run from (throw away package names,
+ # if any).
+ self._test_name = '.'.join(self.id().split('.')[-3:])
+
+ self._temp_dir = tempfile.mkdtemp()
+ if self._testdata_dir:
+ self.create_empty_dir(self.output_dir_actual)
+
+ def tearDown(self):
+ """Called after each test."""
+ shutil.rmtree(self._temp_dir)
+ if self._testdata_dir and os.path.exists(self.output_dir_expected):
+ different_files = _find_different_files(self.output_dir_actual,
+ self.output_dir_expected)
+ # Don't add any cleanup code below this assert!
+ # Then if tests fail, the artifacts will not be cleaned up.
+ assert (not different_files), \
+ ('found differing files:\n' +
+ '\n'.join(['tkdiff %s %s &' % (
+ os.path.join(self.output_dir_actual, basename),
+ os.path.join(self.output_dir_expected, basename))
+ for basename in different_files]))
+
+ @property
+ def temp_dir(self):
+ return self._temp_dir
+
+ @property
+ def input_dir(self):
+ assert self._testdata_dir, 'self._testdata_dir must be set'
+ return os.path.join(self._testdata_dir, 'inputs')
+
+ @property
+ def output_dir_actual(self):
+ assert self._testdata_dir, 'self._testdata_dir must be set'
+ return os.path.join(
+ self._testdata_dir, 'outputs', 'actual', self._test_name)
+
+ @property
+ def output_dir_expected(self):
+ assert self._testdata_dir, 'self._testdata_dir must be set'
+ return os.path.join(
+ self._testdata_dir, 'outputs', 'expected', self._test_name)
+
def shortDescription(self):
"""Tell unittest framework to not print docstrings for test cases."""
return None
@@ -34,42 +89,48 @@ class TestCase(unittest.TestCase):
Args:
path: path on local disk
"""
- shutil.rmtree(path=path, ignore_errors=True)
+ # Delete the old one, if any.
+ if os.path.isdir(path):
+ shutil.rmtree(path=path, ignore_errors=True)
+ elif os.path.lexists(path):
+ os.remove(path)
+
+ # Create the new one.
try:
os.makedirs(path)
except OSError as exc:
+ # Guard against race condition (somebody else is creating the same dir)
if exc.errno != errno.EEXIST:
raise
return path
- def run_command(self, args):
- """Runs a program from the command line and returns stdout.
- Args:
- args: Command line to run, as a list of string parameters. args[0] is the
- binary to run.
-
- Returns:
- stdout from the program, as a single string.
-
- Raises:
- Exception: the program exited with a nonzero return code.
- """
- return find_run_binary.run_command(args)
+def _find_different_files(dir1, dir2, ignore_subtree_names=None):
+ """Returns a list of any files that differ between the directory trees rooted
+ at dir1 and dir2.
- def find_path_to_program(self, program):
- """Returns path to an existing program binary.
+ Args:
+ dir1: root of a directory tree; if nonexistent, will raise OSError
+ dir2: root of another directory tree; if nonexistent, will raise OSError
+ ignore_subtree_names: list of subtree directory names to ignore;
+ defaults to ['.svn'], so all SVN files are ignores
- Args:
- program: Basename of the program to find (e.g., 'render_pictures').
-
- Returns:
- Absolute path to the program binary, as a string.
-
- Raises:
- Exception: unable to find the program binary.
- """
- return find_run_binary.find_path_to_program(program)
+ TODO(epoger): include the dirname within each filename (not just the
+ basename), to make it easier to locate any differences
+ """
+ differing_files = []
+ if ignore_subtree_names is None:
+ ignore_subtree_names = ['.svn']
+ dircmp = filecmp.dircmp(dir1, dir2, ignore=ignore_subtree_names)
+ differing_files.extend(dircmp.left_only)
+ differing_files.extend(dircmp.right_only)
+ differing_files.extend(dircmp.common_funny)
+ differing_files.extend(dircmp.diff_files)
+ differing_files.extend(dircmp.funny_files)
+ for common_dir in dircmp.common_dirs:
+ differing_files.extend(_find_different_files(
+ os.path.join(dir1, common_dir), os.path.join(dir2, common_dir)))
+ return differing_files
def main(test_case_class):
@@ -77,10 +138,6 @@ def main(test_case_class):
Raises an Exception if any of those tests fail (in case we are running in the
context of run_all.py, which depends on that Exception to signal failures).
-
- TODO(epoger): Make all of our unit tests use the Python unittest framework,
- so we can leverage its ability to run *all* the tests and report failures at
- the end.
"""
suite = unittest.TestLoader().loadTestsFromTestCase(test_case_class)
results = unittest.TextTestRunner(verbosity=2).run(suite)
« no previous file with comments | « gm/rebaseline_server/imagepair_test.py ('k') | tools/tests/fix_pythonpath.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698