test_utils.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # Based on https://github.com/PaddlePaddle/PaddleNLP/blob/develop/tests/common_test.py
  15. import unittest
  16. import warnings
  17. import numpy as np
  18. import paddle
  19. __all__ = ['CommonTest', 'CpuCommonTest']
  20. # Assume all elements has same data type
  21. def get_container_type(container):
  22. container_t = type(container)
  23. if container_t in [list, tuple]:
  24. if len(container) == 0:
  25. return container_t
  26. return get_container_type(container[0])
  27. return container_t
  28. class _CommonTestNamespace:
  29. # Wrap the subclasses of unittest.TestCase that are expected to be inherited from.
  30. class CommonTest(unittest.TestCase):
  31. CATCH_WARNINGS = False
  32. def __init__(self, methodName='runTest'):
  33. super(CommonTest, self).__init__(methodName=methodName)
  34. self.config = {}
  35. self.places = ['cpu']
  36. if paddle.is_compiled_with_cuda():
  37. self.places.append('gpu')
  38. @classmethod
  39. def setUpClass(cls):
  40. '''
  41. Set the decorators for all test function
  42. '''
  43. for key, value in cls.__dict__.items():
  44. if key.startswith('test'):
  45. decorator_func_list = ["_test_places"]
  46. if cls.CATCH_WARNINGS:
  47. decorator_func_list.append("_catch_warnings")
  48. for decorator_func in decorator_func_list:
  49. decorator_func = getattr(CommonTest, decorator_func)
  50. value = decorator_func(value)
  51. setattr(cls, key, value)
  52. def _catch_warnings(func):
  53. '''
  54. Catch the warnings and treat them as errors for each test.
  55. '''
  56. def wrapper(self, *args, **kwargs):
  57. with warnings.catch_warnings(record=True) as w:
  58. warnings.resetwarnings()
  59. # ignore specified warnings
  60. warning_white_list = [UserWarning]
  61. for warning in warning_white_list:
  62. warnings.simplefilter("ignore", warning)
  63. func(self, *args, **kwargs)
  64. msg = None if len(w) == 0 else w[0].message
  65. self.assertFalse(len(w) > 0, msg)
  66. return wrapper
  67. def _test_places(func):
  68. '''
  69. Setting the running place for each test.
  70. '''
  71. def wrapper(self, *args, **kwargs):
  72. places = self.places
  73. for place in places:
  74. paddle.set_device(place)
  75. func(self, *args, **kwargs)
  76. return wrapper
  77. def _check_output_impl(self,
  78. result,
  79. expected_result,
  80. rtol,
  81. atol,
  82. equal=True):
  83. assertForNormalType = self.assertNotEqual
  84. assertForFloat = self.assertFalse
  85. if equal:
  86. assertForNormalType = self.assertEqual
  87. assertForFloat = self.assertTrue
  88. result_t = type(result)
  89. error_msg = 'Output has diff at place:{}. \nExpect: {} \nBut Got: {} in class {}'
  90. if result_t in [list, tuple]:
  91. result_t = get_container_type(result)
  92. if result_t in [
  93. str, int, bool, set, np.bool, np.int32, np.int64, np.str
  94. ]:
  95. assertForNormalType(
  96. result,
  97. expected_result,
  98. msg=error_msg.format(paddle.get_device(), expected_result,
  99. result, self.__class__.__name__))
  100. elif result_t in [float, np.ndarray, np.float32, np.float64]:
  101. assertForFloat(
  102. np.allclose(
  103. result, expected_result, rtol=rtol, atol=atol),
  104. msg=error_msg.format(paddle.get_device(), expected_result,
  105. result, self.__class__.__name__))
  106. if result_t == np.ndarray:
  107. assertForNormalType(
  108. result.shape,
  109. expected_result.shape,
  110. msg=error_msg.format(
  111. paddle.get_device(), expected_result.shape,
  112. result.shape, self.__class__.__name__))
  113. else:
  114. raise ValueError(
  115. 'result type must be str, int, bool, set, np.bool, np.int32, '
  116. 'np.int64, np.str, float, np.ndarray, np.float32, np.float64'
  117. )
  118. def check_output_equal(self,
  119. result,
  120. expected_result,
  121. rtol=1.e-5,
  122. atol=1.e-8):
  123. '''
  124. Check whether result and expected result are equal, including shape.
  125. Args:
  126. result: str, int, bool, set, np.ndarray.
  127. The result needs to be checked.
  128. expected_result: str, int, bool, set, np.ndarray. The type has to be same as result's.
  129. Use the expected result to check result.
  130. rtol: float
  131. relative tolerance, default 1.e-5.
  132. atol: float
  133. absolute tolerance, default 1.e-8
  134. '''
  135. self._check_output_impl(result, expected_result, rtol, atol)
  136. def check_output_not_equal(self,
  137. result,
  138. expected_result,
  139. rtol=1.e-5,
  140. atol=1.e-8):
  141. '''
  142. Check whether result and expected result are not equal, including shape.
  143. Args:
  144. result: str, int, bool, set, np.ndarray.
  145. The result needs to be checked.
  146. expected_result: str, int, bool, set, np.ndarray. The type has to be same as result's.
  147. Use the expected result to check result.
  148. rtol: float
  149. relative tolerance, default 1.e-5.
  150. atol: float
  151. absolute tolerance, default 1.e-8
  152. '''
  153. self._check_output_impl(
  154. result, expected_result, rtol, atol, equal=False)
  155. class CpuCommonTest(CommonTest):
  156. def __init__(self, methodName='runTest'):
  157. super(CpuCommonTest, self).__init__(methodName=methodName)
  158. self.places = ['cpu']
  159. CommonTest = _CommonTestNamespace.CommonTest
  160. CpuCommonTest = _CommonTestNamespace.CpuCommonTest