-
Notifications
You must be signed in to change notification settings - Fork 224
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
Simplify the _get_default_display_method tests using unittest.mock #3537
Conversation
22358cc
to
541df3d
Compare
pygmt/tests/test_figure.py
Outdated
# Mock IPython.get_ipython() to return an object with a config attribute, so PyGMT | ||
# can detect that an IPython kernel is running. | ||
@patch("IPython.get_ipython", return_value=Mock(config={"IPKernelApp": True})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't played around with unittest.mock
much yet, but does this unittest.mock.path
call need to be here on top as a decorator, rather than in the test function below? I find this looks a little unintuitive (even though it is less code) compared to setting up the MockIPython class inside the unit test which makes it clear what is happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are different ways to mock IPython:
- Define a custom class, as in the current main branch and use
pytest.monkeypatch
class MockIPython:
def __init__(self):
self.config = {"IPKernelApp": True}
# Mock IPython.get_ipython() to return a MockIPython instance.
mock_ipython = MockIPython()
monkeypatch.setattr(IPython, "get_ipython", lambda: mock_ipython)
- Use
mock
/patch
as a decorator
@patch("IPython.get_ipython", return_value=Mock(config={"IPKernelApp": True}))
def test_xxxx():
...
- Use
mock
/patch
as a context manager
def test_xxxx():
with patch("IPython.get_ipython", return_value=Mock(config={"IPKernelApp": True})):
....
Maybe we should use option 3 although it means more indentations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, option 3 sounds good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I've changed it to context manager in d08001c.
Refer to pytest-dev/pytest#4576 (comment) for comparisons of pytest.monkeypatch, unittest.mock and pytest-mock.
unittest.mock
provides more features thanpytest.monkeypatch
which can simplify our tests. For example, withmock.call_count
, we can directly count how many times a function/method is called, rather than implementing our own counter (like what're doing inpygmt/pygmt/tests/test_clib_loading.py
Line 224 in d1ab97c
Personally, I prefer
pytest-mock
which is as powerful asunittest.mock
and can be used as a fixture, whileunittest.mock
must be used as a context manager or a decorator.I think we have many options:
pytest.monkeypatch
only, which means in some cases, we have to write more codes for testsunittest.mock
only orpytest-mock
onlypytest.monkeypatch
+unittest.mock
pytest.monkeypatch
+pytest-mock