Skip to content

STY: use pytest.raises context manager (generic) #25603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 44 additions & 24 deletions pandas/tests/generic/test_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import numpy as np
import pytest

from pandas.compat import PY3, range, zip
from pandas.compat import PY2, PY3, range, zip

from pandas.core.dtypes.common import is_scalar

Expand All @@ -16,8 +16,6 @@
import pandas.util.testing as tm
from pandas.util.testing import assert_frame_equal, assert_series_equal

import pandas.io.formats.printing as printing

# ----------------------------------------------------------------------
# Generic types test cases

Expand Down Expand Up @@ -135,37 +133,51 @@ def test_nonzero(self):
# GH 4633
# look at the boolean/nonzero behavior for objects
obj = self._construct(shape=4)
pytest.raises(ValueError, lambda: bool(obj == 0))
pytest.raises(ValueError, lambda: bool(obj == 1))
pytest.raises(ValueError, lambda: bool(obj))
msg = "The truth value of a {} is ambiguous".format(
self._typ.__name__)
with pytest.raises(ValueError, match=msg):
bool(obj == 0)
with pytest.raises(ValueError, match=msg):
bool(obj == 1)
with pytest.raises(ValueError, match=msg):
bool(obj)

obj = self._construct(shape=4, value=1)
pytest.raises(ValueError, lambda: bool(obj == 0))
pytest.raises(ValueError, lambda: bool(obj == 1))
pytest.raises(ValueError, lambda: bool(obj))
with pytest.raises(ValueError, match=msg):
bool(obj == 0)
with pytest.raises(ValueError, match=msg):
bool(obj == 1)
with pytest.raises(ValueError, match=msg):
bool(obj)

obj = self._construct(shape=4, value=np.nan)
pytest.raises(ValueError, lambda: bool(obj == 0))
pytest.raises(ValueError, lambda: bool(obj == 1))
pytest.raises(ValueError, lambda: bool(obj))
with pytest.raises(ValueError, match=msg):
bool(obj == 0)
with pytest.raises(ValueError, match=msg):
bool(obj == 1)
with pytest.raises(ValueError, match=msg):
bool(obj)

# empty
obj = self._construct(shape=0)
pytest.raises(ValueError, lambda: bool(obj))
with pytest.raises(ValueError, match=msg):
bool(obj)

# invalid behaviors

obj1 = self._construct(shape=4, value=1)
obj2 = self._construct(shape=4, value=1)

def f():
with pytest.raises(ValueError, match=msg):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fine to remove as this exact behaviour is tested on line 151 right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alimcmaster1 : I'm not sure that this should be removed. I think it was added for a reason. If it could be removed then the remaining part of the test would probably be redundant as well.

probably related to the fact that bool(obj == 0) raises whereas obj == 0 does not.

if obj1:
printing.pprint_thing("this works and shouldn't")
pass

pytest.raises(ValueError, f)
pytest.raises(ValueError, lambda: obj1 and obj2)
pytest.raises(ValueError, lambda: obj1 or obj2)
pytest.raises(ValueError, lambda: not obj1)
with pytest.raises(ValueError, match=msg):
obj1 and obj2
with pytest.raises(ValueError, match=msg):
obj1 or obj2
with pytest.raises(ValueError, match=msg):
not obj1

def test_downcast(self):
# test close downcasting
Expand Down Expand Up @@ -200,9 +212,10 @@ def test_constructor_compound_dtypes(self):
def f(dtype):
return self._construct(shape=3, value=1, dtype=dtype)

pytest.raises(NotImplementedError, f, [("A", "datetime64[h]"),
("B", "str"),
("C", "int32")])
msg = ("compound dtypes are not implemented in the {} constructor"
.format(self._typ.__name__))
with pytest.raises(NotImplementedError, match=msg):
f([("A", "datetime64[h]"), ("B", "str"), ("C", "int32")])

# these work (though results may be unexpected)
f('int64')
Expand Down Expand Up @@ -725,6 +738,7 @@ def test_sample(sel):
with pytest.raises(ValueError):
df.sample(1, weights=s4)

@pytest.mark.skipif(PY2, reason="pytest.raises match regex fails")
def test_squeeze(self):
# noop
for s in [tm.makeFloatSeries(), tm.makeStringSeries(),
Expand Down Expand Up @@ -755,8 +769,14 @@ def test_squeeze(self):
tm.assert_series_equal(df.squeeze(axis=1), df.iloc[:, 0])
tm.assert_series_equal(df.squeeze(axis='columns'), df.iloc[:, 0])
assert df.squeeze() == df.iloc[0, 0]
pytest.raises(ValueError, df.squeeze, axis=2)
pytest.raises(ValueError, df.squeeze, axis='x')
msg = ("No axis named 2 for object type <class"
" 'pandas.core.frame.DataFrame'>")
with pytest.raises(ValueError, match=msg):
df.squeeze(axis=2)
msg = ("No axis named x for object type <class"
" 'pandas.core.frame.DataFrame'>")
with pytest.raises(ValueError, match=msg):
df.squeeze(axis='x')

df = tm.makeTimeDataFrame(3)
tm.assert_frame_equal(df.squeeze(axis=0), df)
Expand Down
23 changes: 17 additions & 6 deletions pandas/tests/generic/test_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,23 +102,34 @@ def test_nonzero_single_element(self):
s = Series([False])
assert not s.bool()

msg = "The truth value of a Series is ambiguous"
# single item nan to raise
for s in [Series([np.nan]), Series([pd.NaT]), Series([True]),
Series([False])]:
pytest.raises(ValueError, lambda: bool(s))
with pytest.raises(ValueError, match=msg):
bool(s)

msg = "bool cannot act on a non-boolean single element Series"
for s in [Series([np.nan]), Series([pd.NaT])]:
pytest.raises(ValueError, lambda: s.bool())
with pytest.raises(ValueError, match=msg):
s.bool()

# multiple bool are still an error
msg = "The truth value of a Series is ambiguous"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Do we need to define this string 3 times in this file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fine for now...

this is surely an indication of tests that could be refactored to use more pytest idiom... but that'll be for a follow-up.

also the messages serve as additional documentation for the tests

for s in [Series([True, True]), Series([False, False])]:
pytest.raises(ValueError, lambda: bool(s))
pytest.raises(ValueError, lambda: s.bool())
with pytest.raises(ValueError, match=msg):
bool(s)
with pytest.raises(ValueError, match=msg):
s.bool()

# single non-bool are an error
for s in [Series([1]), Series([0]), Series(['a']), Series([0.0])]:
pytest.raises(ValueError, lambda: bool(s))
pytest.raises(ValueError, lambda: s.bool())
msg = "The truth value of a Series is ambiguous"
with pytest.raises(ValueError, match=msg):
bool(s)
msg = "bool cannot act on a non-boolean single element Series"
with pytest.raises(ValueError, match=msg):
s.bool()

def test_metadata_propagation_indiv(self):
# check that the metadata matches up on the resulting ops
Expand Down