test_assert_produces_warning.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. """"
  2. Test module for testing ``pandas._testing.assert_produces_warning``.
  3. """
  4. import warnings
  5. import pytest
  6. from pandas.errors import (
  7. DtypeWarning,
  8. PerformanceWarning,
  9. )
  10. import pandas._testing as tm
  11. @pytest.fixture(
  12. params=[
  13. RuntimeWarning,
  14. ResourceWarning,
  15. UserWarning,
  16. FutureWarning,
  17. DeprecationWarning,
  18. PerformanceWarning,
  19. DtypeWarning,
  20. ],
  21. )
  22. def category(request):
  23. """
  24. Return unique warning.
  25. Useful for testing behavior of tm.assert_produces_warning with various categories.
  26. """
  27. return request.param
  28. @pytest.fixture(
  29. params=[
  30. (RuntimeWarning, UserWarning),
  31. (UserWarning, FutureWarning),
  32. (FutureWarning, RuntimeWarning),
  33. (DeprecationWarning, PerformanceWarning),
  34. (PerformanceWarning, FutureWarning),
  35. (DtypeWarning, DeprecationWarning),
  36. (ResourceWarning, DeprecationWarning),
  37. (FutureWarning, DeprecationWarning),
  38. ],
  39. ids=lambda x: type(x).__name__,
  40. )
  41. def pair_different_warnings(request):
  42. """
  43. Return pair or different warnings.
  44. Useful for testing how several different warnings are handled
  45. in tm.assert_produces_warning.
  46. """
  47. return request.param
  48. def f():
  49. warnings.warn("f1", FutureWarning)
  50. warnings.warn("f2", RuntimeWarning)
  51. @pytest.mark.filterwarnings("ignore:f1:FutureWarning")
  52. def test_assert_produces_warning_honors_filter():
  53. # Raise by default.
  54. msg = r"Caused unexpected warning\(s\)"
  55. with pytest.raises(AssertionError, match=msg):
  56. with tm.assert_produces_warning(RuntimeWarning):
  57. f()
  58. with tm.assert_produces_warning(RuntimeWarning, raise_on_extra_warnings=False):
  59. f()
  60. @pytest.mark.parametrize(
  61. "message, match",
  62. [
  63. ("", None),
  64. ("", ""),
  65. ("Warning message", r".*"),
  66. ("Warning message", "War"),
  67. ("Warning message", r"[Ww]arning"),
  68. ("Warning message", "age"),
  69. ("Warning message", r"age$"),
  70. ("Message 12-234 with numbers", r"\d{2}-\d{3}"),
  71. ("Message 12-234 with numbers", r"^Mes.*\d{2}-\d{3}"),
  72. ("Message 12-234 with numbers", r"\d{2}-\d{3}\s\S+"),
  73. ("Message, which we do not match", None),
  74. ],
  75. )
  76. def test_catch_warning_category_and_match(category, message, match):
  77. with tm.assert_produces_warning(category, match=match):
  78. warnings.warn(message, category)
  79. def test_fail_to_match_runtime_warning():
  80. category = RuntimeWarning
  81. match = "Did not see this warning"
  82. unmatched = (
  83. r"Did not see warning 'RuntimeWarning' matching 'Did not see this warning'. "
  84. r"The emitted warning messages are "
  85. r"\[RuntimeWarning\('This is not a match.'\), "
  86. r"RuntimeWarning\('Another unmatched warning.'\)\]"
  87. )
  88. with pytest.raises(AssertionError, match=unmatched):
  89. with tm.assert_produces_warning(category, match=match):
  90. warnings.warn("This is not a match.", category)
  91. warnings.warn("Another unmatched warning.", category)
  92. def test_fail_to_match_future_warning():
  93. category = FutureWarning
  94. match = "Warning"
  95. unmatched = (
  96. r"Did not see warning 'FutureWarning' matching 'Warning'. "
  97. r"The emitted warning messages are "
  98. r"\[FutureWarning\('This is not a match.'\), "
  99. r"FutureWarning\('Another unmatched warning.'\)\]"
  100. )
  101. with pytest.raises(AssertionError, match=unmatched):
  102. with tm.assert_produces_warning(category, match=match):
  103. warnings.warn("This is not a match.", category)
  104. warnings.warn("Another unmatched warning.", category)
  105. def test_fail_to_match_resource_warning():
  106. category = ResourceWarning
  107. match = r"\d+"
  108. unmatched = (
  109. r"Did not see warning 'ResourceWarning' matching '\\d\+'. "
  110. r"The emitted warning messages are "
  111. r"\[ResourceWarning\('This is not a match.'\), "
  112. r"ResourceWarning\('Another unmatched warning.'\)\]"
  113. )
  114. with pytest.raises(AssertionError, match=unmatched):
  115. with tm.assert_produces_warning(category, match=match):
  116. warnings.warn("This is not a match.", category)
  117. warnings.warn("Another unmatched warning.", category)
  118. def test_fail_to_catch_actual_warning(pair_different_warnings):
  119. expected_category, actual_category = pair_different_warnings
  120. match = "Did not see expected warning of class"
  121. with pytest.raises(AssertionError, match=match):
  122. with tm.assert_produces_warning(expected_category):
  123. warnings.warn("warning message", actual_category)
  124. def test_ignore_extra_warning(pair_different_warnings):
  125. expected_category, extra_category = pair_different_warnings
  126. with tm.assert_produces_warning(expected_category, raise_on_extra_warnings=False):
  127. warnings.warn("Expected warning", expected_category)
  128. warnings.warn("Unexpected warning OK", extra_category)
  129. def test_raise_on_extra_warning(pair_different_warnings):
  130. expected_category, extra_category = pair_different_warnings
  131. match = r"Caused unexpected warning\(s\)"
  132. with pytest.raises(AssertionError, match=match):
  133. with tm.assert_produces_warning(expected_category):
  134. warnings.warn("Expected warning", expected_category)
  135. warnings.warn("Unexpected warning NOT OK", extra_category)
  136. def test_same_category_different_messages_first_match():
  137. category = UserWarning
  138. with tm.assert_produces_warning(category, match=r"^Match this"):
  139. warnings.warn("Match this", category)
  140. warnings.warn("Do not match that", category)
  141. warnings.warn("Do not match that either", category)
  142. def test_same_category_different_messages_last_match():
  143. category = DeprecationWarning
  144. with tm.assert_produces_warning(category, match=r"^Match this"):
  145. warnings.warn("Do not match that", category)
  146. warnings.warn("Do not match that either", category)
  147. warnings.warn("Match this", category)
  148. def test_match_multiple_warnings():
  149. # https://github.com/pandas-dev/pandas/issues/47829
  150. category = (FutureWarning, UserWarning)
  151. with tm.assert_produces_warning(category, match=r"^Match this"):
  152. warnings.warn("Match this", FutureWarning)
  153. warnings.warn("Match this too", UserWarning)
  154. def test_right_category_wrong_match_raises(pair_different_warnings):
  155. target_category, other_category = pair_different_warnings
  156. with pytest.raises(AssertionError, match="Did not see warning.*matching"):
  157. with tm.assert_produces_warning(target_category, match=r"^Match this"):
  158. warnings.warn("Do not match it", target_category)
  159. warnings.warn("Match this", other_category)
  160. @pytest.mark.parametrize("false_or_none", [False, None])
  161. class TestFalseOrNoneExpectedWarning:
  162. def test_raise_on_warning(self, false_or_none):
  163. msg = r"Caused unexpected warning\(s\)"
  164. with pytest.raises(AssertionError, match=msg):
  165. with tm.assert_produces_warning(false_or_none):
  166. f()
  167. def test_no_raise_without_warning(self, false_or_none):
  168. with tm.assert_produces_warning(false_or_none):
  169. pass
  170. def test_no_raise_with_false_raise_on_extra(self, false_or_none):
  171. with tm.assert_produces_warning(false_or_none, raise_on_extra_warnings=False):
  172. f()
  173. def test_raises_during_exception():
  174. msg = "Did not see expected warning of class 'UserWarning'"
  175. with pytest.raises(AssertionError, match=msg):
  176. with tm.assert_produces_warning(UserWarning):
  177. raise ValueError
  178. with pytest.raises(AssertionError, match=msg):
  179. with tm.assert_produces_warning(UserWarning):
  180. warnings.warn("FutureWarning", FutureWarning)
  181. raise IndexError
  182. msg = "Caused unexpected warning"
  183. with pytest.raises(AssertionError, match=msg):
  184. with tm.assert_produces_warning(None):
  185. warnings.warn("FutureWarning", FutureWarning)
  186. raise SystemError
  187. def test_passes_during_exception():
  188. with pytest.raises(SyntaxError, match="Error"):
  189. with tm.assert_produces_warning(None):
  190. raise SyntaxError("Error")
  191. with pytest.raises(ValueError, match="Error"):
  192. with tm.assert_produces_warning(FutureWarning, match="FutureWarning"):
  193. warnings.warn("FutureWarning", FutureWarning)
  194. raise ValueError("Error")