| OLD | NEW |
| 1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 __version__ = '1.0' |
| 6 |
| 7 import collections |
| 5 import inspect | 8 import inspect |
| 6 import unittest | 9 import unittest |
| 7 | 10 |
| 8 | 11 |
| 9 class OrderedDict(object): | |
| 10 """Incomplete and inefficient implementation of collections.OrderedDict.""" | |
| 11 def __init__(self): | |
| 12 self._keys = [] | |
| 13 | |
| 14 def setdefault(self, key, value): | |
| 15 try: | |
| 16 self._getindex(key) | |
| 17 except KeyError: | |
| 18 self._keys.append((key, value)) | |
| 19 return self[key] | |
| 20 | |
| 21 def _getindex(self, key): | |
| 22 for i, v in enumerate(self._keys): | |
| 23 if v[0] == key: | |
| 24 return i | |
| 25 raise KeyError(key) | |
| 26 | |
| 27 def __getitem__(self, key): | |
| 28 return self._keys[self._getindex(key)][1] | |
| 29 | |
| 30 def iteritems(self): | |
| 31 for i in self._keys: | |
| 32 yield i | |
| 33 | |
| 34 | |
| 35 class AutoStubMixIn(object): | 12 class AutoStubMixIn(object): |
| 36 """Automatically restores stubbed functions on unit test teardDown. | 13 """Automatically restores stubbed functions on unit test teardDown. |
| 37 | 14 |
| 38 It's an extremely lightweight mocking class that doesn't require bookeeping. | 15 It's an extremely lightweight mocking class that doesn't require bookeeping. |
| 39 """ | 16 """ |
| 40 _saved = None | 17 _saved = None |
| 41 | 18 |
| 42 def mock(self, obj, member, mock): | 19 def mock(self, obj, member, mock): |
| 43 self._saved = self._saved or OrderedDict() | 20 self._saved = self._saved or collections.OrderedDict() |
| 44 old_value = self._saved.setdefault( | 21 old_value = self._saved.setdefault( |
| 45 obj, OrderedDict()).setdefault(member, getattr(obj, member)) | 22 obj, collections.OrderedDict()).setdefault(member, getattr(obj, member)) |
| 46 setattr(obj, member, mock) | 23 setattr(obj, member, mock) |
| 47 return old_value | 24 return old_value |
| 48 | 25 |
| 49 def tearDown(self): | 26 def tearDown(self): |
| 50 """Restore all the mocked members.""" | 27 """Restore all the mocked members.""" |
| 51 if self._saved: | 28 if self._saved: |
| 52 for obj, items in self._saved.iteritems(): | 29 for obj, items in self._saved.iteritems(): |
| 53 for member, previous_value in items.iteritems(): | 30 for member, previous_value in items.iteritems(): |
| 54 setattr(obj, member, previous_value) | 31 setattr(obj, member, previous_value) |
| 55 | 32 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 79 def _register_call(self, *args, **kwargs): | 56 def _register_call(self, *args, **kwargs): |
| 80 """Registers the name of the caller function.""" | 57 """Registers the name of the caller function.""" |
| 81 caller_name = kwargs.pop('caller_name', None) or inspect.stack()[1][3] | 58 caller_name = kwargs.pop('caller_name', None) or inspect.stack()[1][3] |
| 82 str_args = ', '.join(repr(arg) for arg in args) | 59 str_args = ', '.join(repr(arg) for arg in args) |
| 83 str_kwargs = ', '.join('%s=%r' % (k, v) for k, v in kwargs.iteritems()) | 60 str_kwargs = ', '.join('%s=%r' % (k, v) for k, v in kwargs.iteritems()) |
| 84 self.calls.append('%s(%s)' % ( | 61 self.calls.append('%s(%s)' % ( |
| 85 caller_name, ', '.join(filter(None, [str_args, str_kwargs])))) | 62 caller_name, ', '.join(filter(None, [str_args, str_kwargs])))) |
| 86 | 63 |
| 87 | 64 |
| 88 class TestCase(unittest.TestCase, AutoStubMixIn): | 65 class TestCase(unittest.TestCase, AutoStubMixIn): |
| 89 """Adds python 2.7 functionality.""" | 66 """Adds self.mock() and self.has_failed() to a TestCase.""" |
| 90 | |
| 91 def tearDown(self): | 67 def tearDown(self): |
| 92 AutoStubMixIn.tearDown(self) | 68 AutoStubMixIn.tearDown(self) |
| 93 unittest.TestCase.tearDown(self) | 69 unittest.TestCase.tearDown(self) |
| 94 | 70 |
| 95 def has_failed(self): | 71 def has_failed(self): |
| 96 """Returns True if the test has failed.""" | 72 """Returns True if the test has failed.""" |
| 97 if hasattr(self, '_exc_info'): | |
| 98 # Only present in python <= 2.6 | |
| 99 # pylint: disable=E1101 | |
| 100 return bool(self._exc_info()[0]) | |
| 101 | |
| 102 # Only present in python >= 2.7 | |
| 103 # pylint: disable=E1101 | |
| 104 return not self._resultForDoCleanups.wasSuccessful() | 73 return not self._resultForDoCleanups.wasSuccessful() |
| 105 | |
| 106 def assertIs(self, expr1, expr2, msg=None): | |
| 107 if hasattr(super(TestCase, self), 'assertIs'): | |
| 108 return super(TestCase, self).assertIs(expr1, expr2, msg) | |
| 109 if expr1 is not expr2: | |
| 110 self.fail(msg or '%r is not %r' % (expr1, expr2)) | |
| 111 | |
| 112 def assertIsNot(self, expr1, expr2, msg=None): | |
| 113 if hasattr(super(TestCase, self), 'assertIsNot'): | |
| 114 return super(TestCase, self).assertIsNot(expr1, expr2, msg) | |
| 115 if expr1 is expr2: | |
| 116 self.fail(msg or 'unexpectedly identical: %r' % expr1) | |
| 117 | |
| 118 def assertIn(self, expr1, expr2, msg=None): | |
| 119 if hasattr(super(TestCase, self), 'assertIn'): | |
| 120 return super(TestCase, self).assertIn(expr1, expr2, msg) | |
| 121 if expr1 not in expr2: | |
| 122 self.fail(msg or '%r not in %r' % (expr1, expr2)) | |
| 123 | |
| 124 def assertLess(self, a, b, msg=None): | |
| 125 if hasattr(super(TestCase, self), 'assertLess'): | |
| 126 return super(TestCase, self).assertLess(a, b, msg) | |
| 127 if not a < b: | |
| 128 self.fail(msg or '%r not less than %r' % (a, b)) | |
| OLD | NEW |