-
Notifications
You must be signed in to change notification settings - Fork 235
Simplify the _get_default_display_method tests using unittest.mock #3537
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
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/patchas a decorator
@patch("IPython.get_ipython", return_value=Mock(config={"IPKernelApp": True}))
def test_xxxx():
...
- Use
mock/patchas 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.mockprovides more features thanpytest.monkeypatchwhich 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-mockwhich is as powerful asunittest.mockand can be used as a fixture, whileunittest.mockmust be used as a context manager or a decorator.I think we have many options:
pytest.monkeypatchonly, which means in some cases, we have to write more codes for testsunittest.mockonly orpytest-mockonlypytest.monkeypatch+unittest.mockpytest.monkeypatch+pytest-mock