| OLD | NEW |
| (Empty) |
| 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 | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 """Manages stubs in an simple and efficient way. | |
| 6 | |
| 7 Original source: | |
| 8 https://chromium.googlesource.com/chromium/tools/depot_tools.git/ \ | |
| 9 +/master/testing_support/auto_stub.py | |
| 10 """ | |
| 11 | |
| 12 import inspect | |
| 13 import unittest | |
| 14 | |
| 15 | |
| 16 class OrderedDict(object): | |
| 17 """Incomplete and inefficient implementation of collections.OrderedDict.""" | |
| 18 def __init__(self): | |
| 19 self._keys = [] | |
| 20 | |
| 21 def setdefault(self, key, value): | |
| 22 try: | |
| 23 self._getindex(key) | |
| 24 except KeyError: | |
| 25 self._keys.append((key, value)) | |
| 26 return self[key] | |
| 27 | |
| 28 def _getindex(self, key): | |
| 29 for i, v in enumerate(self._keys): | |
| 30 if v[0] == key: | |
| 31 return i | |
| 32 raise KeyError(key) | |
| 33 | |
| 34 def __getitem__(self, key): | |
| 35 return self._keys[self._getindex(key)][1] | |
| 36 | |
| 37 def iteritems(self): | |
| 38 for i in self._keys: | |
| 39 yield i | |
| 40 | |
| 41 | |
| 42 class AutoStubMixIn(object): | |
| 43 """Automatically restores stubbed functions on unit test teardDown. | |
| 44 | |
| 45 It's an extremely lightweight mocking class that doesn't require bookeeping. | |
| 46 """ | |
| 47 _saved = None | |
| 48 | |
| 49 def mock(self, obj, member, mock): | |
| 50 self._saved = self._saved or OrderedDict() | |
| 51 old_value = self._saved.setdefault( | |
| 52 obj, OrderedDict()).setdefault(member, getattr(obj, member)) | |
| 53 setattr(obj, member, mock) | |
| 54 return old_value | |
| 55 | |
| 56 def tearDown(self): | |
| 57 """Restore all the mocked members.""" | |
| 58 if self._saved: | |
| 59 for obj, items in self._saved.iteritems(): | |
| 60 for member, previous_value in items.iteritems(): | |
| 61 setattr(obj, member, previous_value) | |
| 62 | |
| 63 | |
| 64 class SimpleMock(object): | |
| 65 """Really simple manual class mock.""" | |
| 66 def __init__(self, unit_test): | |
| 67 """Do not call __init__ if you want to use the global call list to detect | |
| 68 ordering across different instances. | |
| 69 """ | |
| 70 self.calls = [] | |
| 71 self.unit_test = unit_test | |
| 72 self.assertEqual = unit_test.assertEqual | |
| 73 | |
| 74 def pop_calls(self): | |
| 75 """Returns the list of calls up to date. | |
| 76 | |
| 77 Good to do self.assertEqual(expected, mock.pop_calls()). | |
| 78 """ | |
| 79 calls = self.calls | |
| 80 self.calls = [] | |
| 81 return calls | |
| 82 | |
| 83 def check_calls(self, expected): | |
| 84 self.assertEqual(expected, self.pop_calls()) | |
| 85 | |
| 86 def _register_call(self, *args, **kwargs): | |
| 87 """Registers the name of the caller function.""" | |
| 88 caller_name = kwargs.pop('caller_name', None) or inspect.stack()[1][3] | |
| 89 str_args = ', '.join(repr(arg) for arg in args) | |
| 90 str_kwargs = ', '.join('%s=%r' % (k, v) for k, v in kwargs.iteritems()) | |
| 91 self.calls.append('%s(%s)' % ( | |
| 92 caller_name, ', '.join(filter(None, [str_args, str_kwargs])))) | |
| 93 | |
| 94 | |
| 95 class TestCase(unittest.TestCase, AutoStubMixIn): | |
| 96 """Adds python 2.7 functionality.""" | |
| 97 | |
| 98 def tearDown(self): | |
| 99 AutoStubMixIn.tearDown(self) | |
| 100 unittest.TestCase.tearDown(self) | |
| 101 | |
| 102 def has_failed(self): | |
| 103 """Returns True if the test has failed.""" | |
| 104 if hasattr(self, '_exc_info'): | |
| 105 # Only present in python <= 2.6 | |
| 106 # pylint: disable=E1101 | |
| 107 return bool(self._exc_info()[0]) | |
| 108 | |
| 109 # Only present in python >= 2.7 | |
| 110 # pylint: disable=E1101 | |
| 111 return not self._resultForDoCleanups.wasSuccessful() | |
| 112 | |
| 113 def assertIs(self, expr1, expr2, msg=None): | |
| 114 if hasattr(super(TestCase, self), 'assertIs'): | |
| 115 return super(TestCase, self).assertIs(expr1, expr2, msg) | |
| 116 if expr1 is not expr2: | |
| 117 self.fail(msg or '%r is not %r' % (expr1, expr2)) | |
| 118 | |
| 119 def assertIsNot(self, expr1, expr2, msg=None): | |
| 120 if hasattr(super(TestCase, self), 'assertIsNot'): | |
| 121 return super(TestCase, self).assertIsNot(expr1, expr2, msg) | |
| 122 if expr1 is expr2: | |
| 123 self.fail(msg or 'unexpectedly identical: %r' % expr1) | |
| 124 | |
| 125 def assertIn(self, expr1, expr2, msg=None): | |
| 126 if hasattr(super(TestCase, self), 'assertIn'): | |
| 127 return super(TestCase, self).assertIn(expr1, expr2, msg) | |
| 128 if expr1 not in expr2: | |
| 129 self.fail(msg or '%r not in %r' % (expr1, expr2)) | |
| 130 | |
| 131 def assertLess(self, a, b, msg=None): | |
| 132 if hasattr(super(TestCase, self), 'assertLess'): | |
| 133 return super(TestCase, self).assertLess(a, b, msg) | |
| 134 if not a < b: | |
| 135 self.fail(msg or '%r not less than %r' % (a, b)) | |
| OLD | NEW |