blob: 9ff710f4a1673dbc020083d5c02775188a542de4 [file] [log] [blame]
Copyright 2014 Google Inc.
Use of this source code is governed by a BSD-style license that can be
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
a more common place within the Skia repo?
import errno
import filecmp
import os
import shutil
import tempfile
import unittest
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('.')[-3:])
self._temp_dir = tempfile.mkdtemp()
if self._testdata_dir:
def tearDown(self):
"""Called after each test."""
if self._testdata_dir and os.path.exists(self.output_dir_expected):
different_files = _find_different_files(self.output_dir_actual,
# 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]))
def temp_dir(self):
return self._temp_dir
def input_dir(self):
assert self._testdata_dir, 'self._testdata_dir must be set'
return os.path.join(self._testdata_dir, 'inputs')
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)
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
def create_empty_dir(self, path):
"""Creates an empty directory at path and returns path.
path: path on local disk
# Delete the old one, if any.
if os.path.isdir(path):
shutil.rmtree(path=path, ignore_errors=True)
elif os.path.lexists(path):
# Create the new one.
except OSError as exc:
# Guard against race condition (somebody else is creating the same dir)
if exc.errno != errno.EEXIST:
return path
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.
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
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)
for common_dir in dircmp.common_dirs:
os.path.join(dir1, common_dir), os.path.join(dir2, common_dir)))
return differing_files
def main(test_case_class):
"""Run the unit tests within the given class.
Raises an Exception if any of those tests fail (in case we are running in the
context of, which depends on that Exception to signal failures).
suite = unittest.TestLoader().loadTestsFromTestCase(test_case_class)
results = unittest.TextTestRunner(verbosity=2).run(suite)
if not results.wasSuccessful():
raise Exception('failed unittest %s' % test_case_class)