You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

decorators.py 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import warnings
  2. from functools import wraps
  3. import mock
  4. def dataProvider(fn_data_provider):
  5. """
  6. Data provider decorator, allows another callable to provide the data for
  7. the test. This is a nice feature from PHPUnit which is very useful. Am
  8. sticking with the JUnit style naming as unittest does this already.
  9. Implementation based on:
  10. http://melp.nl/2011/02/phpunit-style-dataprovider-in-python-unit-test/#more-525 # noqa
  11. """
  12. def test_decorator(test_method):
  13. def execute_test_method_with_each_data_set(self):
  14. for data in fn_data_provider():
  15. if (len(data) == 2 and isinstance(data[0], tuple) and
  16. isinstance(data[1], dict)):
  17. # Both args and kwargs being provided
  18. args, kwargs = data[:]
  19. else:
  20. args, kwargs = data, {}
  21. try:
  22. test_method(self, *args, **kwargs)
  23. except AssertionError as e:
  24. self.fail("%s (Provided data: %s, %s)" % (e, args, kwargs))
  25. return execute_test_method_with_each_data_set
  26. return test_decorator
  27. # This will be in Oscar 0.6 - it should be functools though!
  28. def compose(*functions):
  29. """
  30. Compose functions
  31. This is useful for combining decorators.
  32. """
  33. def _composed(*args):
  34. for fn in functions:
  35. try:
  36. args = fn(*args)
  37. except TypeError:
  38. # args must be scalar so we don't try to expand it
  39. args = fn(args)
  40. return args
  41. return _composed
  42. no_database = mock.patch(
  43. 'django.db.backends.util.CursorWrapper', mock.Mock(
  44. side_effect=RuntimeError("Using the database is not permitted!")))
  45. no_filesystem = mock.patch('__builtin__.open', mock.Mock(
  46. side_effect=RuntimeError("Using the filesystem is not permitted!")))
  47. no_sockets = mock.patch('socket.getaddrinfo', mock.Mock(
  48. side_effect=RuntimeError("Using sockets is not permitted!")))
  49. no_externals = no_diggity = compose(
  50. no_database, no_filesystem, no_sockets) # = no doubt
  51. def ignore_deprecation_warnings(target):
  52. """
  53. Ignore deprecation warnings for the wrapped TestCase or test method
  54. This is useful as the test runner can be set to raise an exception on a
  55. deprecation warning. Using this decorator allows tests to exercise
  56. deprecated code without an exception.
  57. """
  58. if target.__class__.__name__ not in ('instancemethod', 'function'):
  59. # Decorate every test method in class
  60. for attr in dir(target):
  61. if not attr.startswith('test'):
  62. continue
  63. attr_value = getattr(target, attr)
  64. if not hasattr(attr_value, '__call__'):
  65. continue
  66. setattr(target, attr, ignore_deprecation_warnings(attr_value))
  67. return target
  68. else:
  69. # Decorate single test method
  70. @wraps(target)
  71. def _wrapped(*args, **kwargs):
  72. with warnings.catch_warnings():
  73. warnings.filterwarnings("ignore", category=DeprecationWarning)
  74. return target(*args, **kwargs)
  75. return _wrapped