auto_stub.py 3.9 KB

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