Skip to content

Commit 4a4103e

Browse files
committed
Replace use of pretend library with unitest.mock in tests
The pretend library was used by very few tests. In all cases, it is simple enough to switch to stdlib unitest.mock. Using stdlib means there is one fewer library to install before running tests. It can also simplify mypy usage via typeshed.
1 parent 28e794e commit 4a4103e

File tree

9 files changed

+47
-67
lines changed

9 files changed

+47
-67
lines changed

docs/html/development/getting-started.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ You can then invoke your local source tree pip normally.
5959
Running Tests
6060
=============
6161

62-
pip's tests are written using the :pypi:`pytest` test framework, :pypi:`mock`
63-
and :pypi:`pretend`. :pypi:`tox` is used to automate the setup and execution of
64-
pip's tests.
62+
pip's tests are written using the :pypi:`pytest` test framework and
63+
:mod:`unittest.mock`. :pypi:`tox` is used to automate the setup and execution
64+
of pip's tests.
6565

6666
It is preferable to run the tests in parallel for better experience during development,
6767
since the tests can take a long time to finish when run sequentially.

news/7ecf31fa-f1eb-4735-8c89-2a64f1bb2741.trivial.rst

Whitespace-only changes.

tests/functional/test_search.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import logging
2+
from unittest import mock
23

3-
import pretend
44
import pytest
55

66
from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS
@@ -156,18 +156,18 @@ def test_latest_prerelease_install_message(caplog, monkeypatch):
156156
}
157157
]
158158

159-
installed_package = pretend.stub(project_name="ni")
159+
installed_package = mock.Mock(project_name="ni")
160160
monkeypatch.setattr("pip._vendor.pkg_resources.working_set", [installed_package])
161161

162-
dist = pretend.stub(version="1.0.0")
163-
get_dist = pretend.call_recorder(lambda x: dist)
162+
get_dist = mock.Mock()
163+
get_dist.return_value = mock.Mock(version="1.0.0")
164164
monkeypatch.setattr("pip._internal.commands.search.get_distribution", get_dist)
165165
with caplog.at_level(logging.INFO):
166166
print_results(hits)
167167

168168
message = caplog.records[-1].getMessage()
169169
assert 'pre-release; install with "pip install --pre"' in message
170-
assert get_dist.calls == [pretend.call("ni")]
170+
assert get_dist.call_args_list == [mock.call("ni")]
171171

172172

173173
@pytest.mark.search

tests/functional/test_uninstall.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import textwrap
55
from os.path import join, normpath
66
from tempfile import mkdtemp
7+
from unittest.mock import Mock
78

8-
import pretend
99
import pytest
1010

1111
from pip._internal.req.constructors import install_req_from_line
@@ -467,14 +467,13 @@ def test_uninstall_non_local_distutils(caplog, monkeypatch, tmpdir):
467467
with open(einfo, "wb"):
468468
pass
469469

470-
dist = pretend.stub(
470+
get_dist = Mock()
471+
get_dist.return_value = Mock(
471472
key="thing",
472473
project_name="thing",
473474
egg_info=einfo,
474475
location=einfo,
475-
_provider=pretend.stub(),
476476
)
477-
get_dist = pretend.call_recorder(lambda x: dist)
478477
monkeypatch.setattr("pip._vendor.pkg_resources.get_distribution", get_dist)
479478

480479
req = install_req_from_line("thing")

tests/requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
cryptography
22
freezegun
3-
pretend
43
pytest
54
pytest-cov
65
pytest-rerunfailures

tests/unit/test_appdirs.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@
22
import os
33
import posixpath
44
import sys
5+
from unittest import mock
56

6-
import pretend
77
from pip._vendor import appdirs as _appdirs
88

99
from pip._internal.utils import appdirs
1010

1111

1212
class TestUserCacheDir:
1313
def test_user_cache_dir_win(self, monkeypatch):
14-
@pretend.call_recorder
15-
def _get_win_folder(base):
16-
return "C:\\Users\\test\\AppData\\Local"
14+
_get_win_folder = mock.Mock(return_value="C:\\Users\\test\\AppData\\Local")
1715

1816
monkeypatch.setattr(
1917
_appdirs,
@@ -28,7 +26,7 @@ def _get_win_folder(base):
2826
appdirs.user_cache_dir("pip")
2927
== "C:\\Users\\test\\AppData\\Local\\pip\\Cache"
3028
)
31-
assert _get_win_folder.calls == [pretend.call("CSIDL_LOCAL_APPDATA")]
29+
assert _get_win_folder.call_args_list == [mock.call("CSIDL_LOCAL_APPDATA")]
3230

3331
def test_user_cache_dir_osx(self, monkeypatch):
3432
monkeypatch.setattr(_appdirs, "system", "darwin")
@@ -89,9 +87,7 @@ def my_get_win_folder(csidl_name):
8987

9088
class TestSiteConfigDirs:
9189
def test_site_config_dirs_win(self, monkeypatch):
92-
@pretend.call_recorder
93-
def _get_win_folder(base):
94-
return "C:\\ProgramData"
90+
_get_win_folder = mock.Mock(return_value="C:\\ProgramData")
9591

9692
monkeypatch.setattr(
9793
_appdirs,
@@ -103,7 +99,7 @@ def _get_win_folder(base):
10399
monkeypatch.setattr(os, "path", ntpath)
104100

105101
assert appdirs.site_config_dirs("pip") == ["C:\\ProgramData\\pip"]
106-
assert _get_win_folder.calls == [pretend.call("CSIDL_COMMON_APPDATA")]
102+
assert _get_win_folder.call_args_list == [mock.call("CSIDL_COMMON_APPDATA")]
107103

108104
def test_site_config_dirs_osx(self, monkeypatch):
109105
monkeypatch.setattr(_appdirs, "system", "darwin")
@@ -146,9 +142,7 @@ def test_site_config_dirs_linux_empty(self, monkeypatch):
146142

147143
class TestUserConfigDir:
148144
def test_user_config_dir_win_no_roaming(self, monkeypatch):
149-
@pretend.call_recorder
150-
def _get_win_folder(base):
151-
return "C:\\Users\\test\\AppData\\Local"
145+
_get_win_folder = mock.Mock(return_value="C:\\Users\\test\\AppData\\Local")
152146

153147
monkeypatch.setattr(
154148
_appdirs,
@@ -163,12 +157,10 @@ def _get_win_folder(base):
163157
appdirs.user_config_dir("pip", roaming=False)
164158
== "C:\\Users\\test\\AppData\\Local\\pip"
165159
)
166-
assert _get_win_folder.calls == [pretend.call("CSIDL_LOCAL_APPDATA")]
160+
assert _get_win_folder.call_args_list == [mock.call("CSIDL_LOCAL_APPDATA")]
167161

168162
def test_user_config_dir_win_yes_roaming(self, monkeypatch):
169-
@pretend.call_recorder
170-
def _get_win_folder(base):
171-
return "C:\\Users\\test\\AppData\\Roaming"
163+
_get_win_folder = mock.Mock(return_value="C:\\Users\\test\\AppData\\Roaming")
172164

173165
monkeypatch.setattr(
174166
_appdirs,
@@ -182,7 +174,7 @@ def _get_win_folder(base):
182174
assert (
183175
appdirs.user_config_dir("pip") == "C:\\Users\\test\\AppData\\Roaming\\pip"
184176
)
185-
assert _get_win_folder.calls == [pretend.call("CSIDL_APPDATA")]
177+
assert _get_win_folder.call_args_list == [mock.call("CSIDL_APPDATA")]
186178

187179
def test_user_config_dir_osx(self, monkeypatch):
188180
monkeypatch.setattr(_appdirs, "system", "darwin")

tests/unit/test_collector.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from unittest import mock
99
from unittest.mock import Mock, patch
1010

11-
import pretend
1211
import pytest
1312
from pip._vendor import html5lib, requests
1413

@@ -518,7 +517,7 @@ def test_request_retries(caplog):
518517

519518
def test_make_html_page():
520519
headers = {"Content-Type": "text/html; charset=UTF-8"}
521-
response = pretend.stub(
520+
response = Mock(
522521
content=b"<content>",
523522
url="https://example.com/index.html",
524523
headers=headers,
@@ -604,7 +603,7 @@ def make_fake_html_response(url):
604603
"""
605604
)
606605
content = html.encode("utf-8")
607-
return pretend.stub(content=content, url=url, headers={})
606+
return Mock(content=content, url=url, headers={})
608607

609608

610609
def test_get_html_page_directory_append_index(tmpdir):
@@ -636,8 +635,8 @@ def test_collect_sources__file_expand_dir(data):
636635
Test that a file:// dir from --find-links becomes _FlatDirectorySource
637636
"""
638637
collector = LinkCollector.create(
639-
session=pretend.stub(is_secure_origin=None), # Shouldn't be used.
640-
options=pretend.stub(
638+
session=Mock(is_secure_origin=None), # Shouldn't be used.
639+
options=Mock(
641640
index_url="ignored-by-no-index",
642641
extra_index_urls=[],
643642
no_index=True,
@@ -664,8 +663,8 @@ def test_collect_sources__file_not_find_link(data):
664663
run
665664
"""
666665
collector = LinkCollector.create(
667-
session=pretend.stub(is_secure_origin=None), # Shouldn't be used.
668-
options=pretend.stub(
666+
session=Mock(is_secure_origin=None), # Shouldn't be used.
667+
options=Mock(
669668
index_url=data.index_url("empty_with_pkg"),
670669
extra_index_urls=[],
671670
no_index=False,
@@ -688,8 +687,8 @@ def test_collect_sources__non_existing_path():
688687
Test that a non-existing path is ignored.
689688
"""
690689
collector = LinkCollector.create(
691-
session=pretend.stub(is_secure_origin=None), # Shouldn't be used.
692-
options=pretend.stub(
690+
session=Mock(is_secure_origin=None), # Shouldn't be used.
691+
options=Mock(
693692
index_url="ignored-by-no-index",
694693
extra_index_urls=[],
695694
no_index=True,
@@ -810,7 +809,7 @@ def test_link_collector_create(
810809
"""
811810
expected_find_links, expected_index_urls = expected
812811
session = PipSession()
813-
options = pretend.stub(
812+
options = Mock(
814813
find_links=find_links,
815814
index_url="default_url",
816815
extra_index_urls=["url1", "url2"],
@@ -846,7 +845,7 @@ def expand_path(path):
846845
mock_expanduser.side_effect = expand_path
847846

848847
session = PipSession()
849-
options = pretend.stub(
848+
options = Mock(
850849
find_links=["~/temp1", "~/temp2"],
851850
index_url="default_url",
852851
extra_index_urls=[],

tests/unit/test_req_file.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
import os
44
import subprocess
55
import textwrap
6-
from unittest.mock import patch
6+
from unittest import mock
77

88
import pytest
9-
from pretend import stub
109

1110
import pip._internal.req.req_file # this will be monkeypatched
1211
from pip._internal.exceptions import InstallationError, RequirementsFileParseError
@@ -39,7 +38,7 @@ def finder(session):
3938

4039
@pytest.fixture
4140
def options(session):
42-
return stub(
41+
return mock.Mock(
4342
isolated_mode=False,
4443
index_url="default_url",
4544
format_control=FormatControl(set(), set()),
@@ -614,7 +613,7 @@ def make_var(name):
614613
# Construct the session outside the monkey-patch, since it access the
615614
# env
616615
session = PipSession()
617-
with patch("pip._internal.req.req_file.os.getenv") as getenv:
616+
with mock.patch("pip._internal.req.req_file.os.getenv") as getenv:
618617
getenv.side_effect = lambda n: env_vars[n]
619618

620619
reqs = list(
@@ -640,7 +639,7 @@ def test_expand_missing_env_variables(self, tmpdir, finder):
640639
# Construct the session outside the monkey-patch, since it access the
641640
# env
642641
session = PipSession()
643-
with patch("pip._internal.req.req_file.os.getenv") as getenv:
642+
with mock.patch("pip._internal.req.req_file.os.getenv") as getenv:
644643
getenv.return_value = ""
645644

646645
reqs = list(
@@ -761,7 +760,7 @@ def test_install_requirements_with_options(self, tmpdir, finder, session, option
761760
)
762761

763762
req.source_dir = os.curdir
764-
with patch.object(subprocess, "Popen") as popen:
763+
with mock.patch.object(subprocess, "Popen") as popen:
765764
popen.return_value.stdout.readline.return_value = b""
766765
try:
767766
req.install([])

tests/unit/test_self_check_outdated.py

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import json
44
import os
55
import sys
6+
from unittest import mock
67

78
import freezegun # type: ignore
8-
import pretend
99
import pytest
1010
from pip._vendor.packaging.version import parse as parse_version
1111

@@ -75,7 +75,7 @@ def get_distribution(self, name):
7575
def _options():
7676
"""Some default options that we pass to
7777
self_outdated_check.pip_self_version_check"""
78-
return pretend.stub(
78+
return mock.Mock(
7979
find_links=[],
8080
index_url="default_url",
8181
extra_index_urls=[],
@@ -124,20 +124,12 @@ def test_pip_self_version_check(
124124
"PackageFinder",
125125
MockPackageFinder,
126126
)
127-
monkeypatch.setattr(
128-
logger,
129-
"warning",
130-
pretend.call_recorder(lambda *a, **kw: None),
131-
)
132-
monkeypatch.setattr(
133-
logger,
134-
"debug",
135-
pretend.call_recorder(lambda s, exc_info=None: None),
136-
)
127+
monkeypatch.setattr(logger, "warning", mock.Mock())
128+
monkeypatch.setattr(logger, "debug", mock.Mock())
137129

138-
fake_state = pretend.stub(
130+
fake_state = mock.Mock(
139131
state={"last_check": stored_time, "pypi_version": installed_ver},
140-
save=pretend.call_recorder(lambda v, t: None),
132+
save=mock.Mock(),
141133
)
142134
monkeypatch.setattr(self_outdated_check, "SelfCheckState", lambda **kw: fake_state)
143135

@@ -156,20 +148,20 @@ def test_pip_self_version_check(
156148
assert not latest_pypi_version
157149
# See that we saved the correct version
158150
elif check_if_upgrade_required:
159-
assert fake_state.save.calls == [
160-
pretend.call(new_ver, datetime.datetime(1970, 1, 9, 10, 00, 00)),
151+
assert fake_state.save.call_args_list == [
152+
mock.call(new_ver, datetime.datetime(1970, 1, 9, 10, 00, 00)),
161153
]
162154
else:
163155
# Make sure no Exceptions
164-
assert not logger.debug.calls
156+
assert not logger.debug.call_args_list
165157
# See that save was not called
166-
assert fake_state.save.calls == []
158+
assert fake_state.save.call_args_list == []
167159

168160
# Ensure we warn the user or not
169161
if check_warn_logs:
170-
assert len(logger.warning.calls) == 1
162+
assert logger.warning.call_count == 1
171163
else:
172-
assert len(logger.warning.calls) == 0
164+
assert logger.warning.call_count == 0
173165

174166

175167
statefile_name_case_1 = "fcd2d5175dd33d5df759ee7b045264230205ef837bf9f582f7c3ada7"

0 commit comments

Comments
 (0)