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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 2
3 """ 3 """
4 Copyright 2014 Google Inc. 4 Copyright 2014 Google Inc.
5 5
6 Use of this source code is governed by a BSD-style license that can be 6 Use of this source code is governed by a BSD-style license that can be
7 found in the LICENSE file. 7 found in the LICENSE file.
8 8
9 A wrapper around the standard Python unittest library, adding features we need 9 A wrapper around the standard Python unittest library, adding features we need
10 for various unittests within this directory. 10 for various unittests within this directory.
11
12 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_
13 a more common place within the Skia repo?
11 """ 14 """
12 15
13 import errno 16 import errno
17 import filecmp
14 import os 18 import os
15 import shutil 19 import shutil
16 import sys 20 import tempfile
17 import unittest 21 import unittest
18 22
19 # Set the PYTHONPATH to include the tools directory. 23 TRUNK_DIR = os.path.abspath(os.path.join(
20 sys.path.append( 24 os.path.dirname(__file__), os.pardir, os.pardir))
21 os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
22 import find_run_binary
23 25
24 26
25 class TestCase(unittest.TestCase): 27 class TestCase(unittest.TestCase):
26 28
29 def __init__(self, *args, **kwargs):
30 super(TestCase, self).__init__(*args, **kwargs)
31 # Subclasses should override this default value if they want their output
32 # to be automatically compared against expectations (see setUp and tearDown)
33 self._testdata_dir = None
34
35 def setUp(self):
36 """Called before each test."""
37 # Get the name of this test, in such a way that it will be consistent
38 # regardless of the directory it is run from (throw away package names,
39 # if any).
40 self._test_name = '.'.join(self.id().split('.')[-3:])
41
42 self._temp_dir = tempfile.mkdtemp()
43 if self._testdata_dir:
44 self.create_empty_dir(self.output_dir_actual)
45
46 def tearDown(self):
47 """Called after each test."""
48 shutil.rmtree(self._temp_dir)
49 if self._testdata_dir and os.path.exists(self.output_dir_expected):
50 different_files = _find_different_files(self.output_dir_actual,
51 self.output_dir_expected)
52 # Don't add any cleanup code below this assert!
53 # Then if tests fail, the artifacts will not be cleaned up.
54 assert (not different_files), \
55 ('found differing files:\n' +
56 '\n'.join(['tkdiff %s %s &' % (
57 os.path.join(self.output_dir_actual, basename),
58 os.path.join(self.output_dir_expected, basename))
59 for basename in different_files]))
60
61 @property
62 def temp_dir(self):
63 return self._temp_dir
64
65 @property
66 def input_dir(self):
67 assert self._testdata_dir, 'self._testdata_dir must be set'
68 return os.path.join(self._testdata_dir, 'inputs')
69
70 @property
71 def output_dir_actual(self):
72 assert self._testdata_dir, 'self._testdata_dir must be set'
73 return os.path.join(
74 self._testdata_dir, 'outputs', 'actual', self._test_name)
75
76 @property
77 def output_dir_expected(self):
78 assert self._testdata_dir, 'self._testdata_dir must be set'
79 return os.path.join(
80 self._testdata_dir, 'outputs', 'expected', self._test_name)
81
27 def shortDescription(self): 82 def shortDescription(self):
28 """Tell unittest framework to not print docstrings for test cases.""" 83 """Tell unittest framework to not print docstrings for test cases."""
29 return None 84 return None
30 85
31 def create_empty_dir(self, path): 86 def create_empty_dir(self, path):
32 """Creates an empty directory at path and returns path. 87 """Creates an empty directory at path and returns path.
33 88
34 Args: 89 Args:
35 path: path on local disk 90 path: path on local disk
36 """ 91 """
37 shutil.rmtree(path=path, ignore_errors=True) 92 # Delete the old one, if any.
93 if os.path.isdir(path):
94 shutil.rmtree(path=path, ignore_errors=True)
95 elif os.path.lexists(path):
96 os.remove(path)
97
98 # Create the new one.
38 try: 99 try:
39 os.makedirs(path) 100 os.makedirs(path)
40 except OSError as exc: 101 except OSError as exc:
102 # Guard against race condition (somebody else is creating the same dir)
41 if exc.errno != errno.EEXIST: 103 if exc.errno != errno.EEXIST:
42 raise 104 raise
43 return path 105 return path
44 106
45 def run_command(self, args):
46 """Runs a program from the command line and returns stdout.
47 107
48 Args: 108 def _find_different_files(dir1, dir2, ignore_subtree_names=None):
49 args: Command line to run, as a list of string parameters. args[0] is the 109 """Returns a list of any files that differ between the directory trees rooted
50 binary to run. 110 at dir1 and dir2.
51 111
52 Returns: 112 Args:
53 stdout from the program, as a single string. 113 dir1: root of a directory tree; if nonexistent, will raise OSError
114 dir2: root of another directory tree; if nonexistent, will raise OSError
115 ignore_subtree_names: list of subtree directory names to ignore;
116 defaults to ['.svn'], so all SVN files are ignores
54 117
55 Raises: 118 TODO(epoger): include the dirname within each filename (not just the
56 Exception: the program exited with a nonzero return code. 119 basename), to make it easier to locate any differences
57 """ 120 """
58 return find_run_binary.run_command(args) 121 differing_files = []
59 122 if ignore_subtree_names is None:
60 def find_path_to_program(self, program): 123 ignore_subtree_names = ['.svn']
61 """Returns path to an existing program binary. 124 dircmp = filecmp.dircmp(dir1, dir2, ignore=ignore_subtree_names)
62 125 differing_files.extend(dircmp.left_only)
63 Args: 126 differing_files.extend(dircmp.right_only)
64 program: Basename of the program to find (e.g., 'render_pictures'). 127 differing_files.extend(dircmp.common_funny)
65 128 differing_files.extend(dircmp.diff_files)
66 Returns: 129 differing_files.extend(dircmp.funny_files)
67 Absolute path to the program binary, as a string. 130 for common_dir in dircmp.common_dirs:
68 131 differing_files.extend(_find_different_files(
69 Raises: 132 os.path.join(dir1, common_dir), os.path.join(dir2, common_dir)))
70 Exception: unable to find the program binary. 133 return differing_files
71 """
72 return find_run_binary.find_path_to_program(program)
73 134
74 135
75 def main(test_case_class): 136 def main(test_case_class):
76 """Run the unit tests within the given class. 137 """Run the unit tests within the given class.
77 138
78 Raises an Exception if any of those tests fail (in case we are running in the 139 Raises an Exception if any of those tests fail (in case we are running in the
79 context of run_all.py, which depends on that Exception to signal failures). 140 context of run_all.py, which depends on that Exception to signal failures).
80
81 TODO(epoger): Make all of our unit tests use the Python unittest framework,
82 so we can leverage its ability to run *all* the tests and report failures at
83 the end.
84 """ 141 """
85 suite = unittest.TestLoader().loadTestsFromTestCase(test_case_class) 142 suite = unittest.TestLoader().loadTestsFromTestCase(test_case_class)
86 results = unittest.TextTestRunner(verbosity=2).run(suite) 143 results = unittest.TextTestRunner(verbosity=2).run(suite)
87 if not results.wasSuccessful(): 144 if not results.wasSuccessful():
88 raise Exception('failed unittest %s' % test_case_class) 145 raise Exception('failed unittest %s' % test_case_class)
OLDNEW
« 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