Skip to content

Commit

Permalink
tests: refactor and fix repository fixtures
Browse files Browse the repository at this point in the history
This change introduces httpretty based mocking for tests using
mocked legacy or pypi repositories. This also fixes various issues with
tests incorrectly relying on remote versions for metadata and
distributions instead of expected mocked versions.

Additionally, we also auto enables PyPI repository mocking to ensure no
external requests are made without explicit handling.

Further, a new `generate.py` script has now been added to help
regenerate existing repository json and distribution fixtures; or
add/remove release versions to the fixtures.
  • Loading branch information
abn committed Mar 17, 2024
1 parent ce4a212 commit b146dc9
Show file tree
Hide file tree
Showing 194 changed files with 3,166 additions and 1,817 deletions.
9 changes: 7 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from typing import Iterator

import httpretty
import keyring
Expand Down Expand Up @@ -62,6 +63,11 @@
from tests.types import SetProjectContext


pytest_plugins = [
"tests.repositories.fixtures",
]


def pytest_addoption(parser: Parser) -> None:
parser.addoption(
"--integration",
Expand Down Expand Up @@ -279,7 +285,6 @@ def download_mock(mocker: MockerFixture) -> None:
# Patch download to not download anything but to just copy from fixtures
mocker.patch("poetry.utils.helpers.download_file", new=mock_download)
mocker.patch("poetry.packages.direct_origin.download_file", new=mock_download)
mocker.patch("poetry.repositories.http_repository.download_file", new=mock_download)


@pytest.fixture(autouse=True)
Expand Down Expand Up @@ -323,7 +328,7 @@ def git_mock(mocker: MockerFixture) -> None:
@pytest.fixture
def http() -> Iterator[type[httpretty.httpretty]]:
httpretty.reset()
with httpretty.enabled(allow_net_connect=False):
with httpretty.enabled(allow_net_connect=False, verbose=True):
yield httpretty


Expand Down
6 changes: 0 additions & 6 deletions tests/console/commands/test_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@
)


@pytest.fixture(autouse=True)
def mock_search_http_response(http: type[httpretty.httpretty]) -> None:
with FIXTURES_DIRECTORY.joinpath("search.html").open(encoding="utf-8") as f:
http.register_uri("GET", "https://pypi.org/search", f.read())


@pytest.fixture
def tester(command_tester_factory: CommandTesterFactory) -> CommandTester:
return command_tester_factory("search")
Expand Down
5 changes: 5 additions & 0 deletions tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
from tests.types import HTTPrettyResponse

FIXTURE_PATH = Path(__file__).parent / "fixtures"
FIXTURE_PATH_INSTALLATION = Path(__file__).parent / "installation" / "fixtures"
FIXTURE_PATH_DISTRIBUTIONS = FIXTURE_PATH / "distributions"
FIXTURE_PATH_REPOSITORIES = Path(__file__).parent / "repositories" / "fixtures"
FIXTURE_PATH_REPOSITORIES_LEGACY = FIXTURE_PATH_REPOSITORIES / "legacy"
FIXTURE_PATH_REPOSITORIES_PYPI = FIXTURE_PATH_REPOSITORIES / "pypi.org"

# Used as a mock for latest git revision.
MOCK_DEFAULT_GIT_REVISION = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
Expand Down
19 changes: 9 additions & 10 deletions tests/inspection/test_lazy_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from tests.types import HTTPPrettyRequestCallbackWrapper
from tests.types import HTTPrettyRequestCallback
from tests.types import HTTPrettyResponse
from tests.types import PackageDistributionLookup

class RequestCallbackFactory(Protocol):
def __call__(
Expand Down Expand Up @@ -110,7 +111,10 @@ def build_partial_response(


@pytest.fixture
def handle_request_factory(fixture_dir: FixtureDirGetter) -> RequestCallbackFactory:
def handle_request_factory(
fixture_dir: FixtureDirGetter,
package_distribution_lookup: PackageDistributionLookup,
) -> RequestCallbackFactory:
def _factory(
*,
accept_ranges: str | None = "bytes",
Expand All @@ -122,17 +126,12 @@ def handle_request(
) -> HTTPrettyResponse:
name = Path(urlparse(uri).path).name

wheel = Path(__file__).parents[1] / (
"repositories/fixtures/pypi.org/dists/" + name
wheel = package_distribution_lookup(name) or package_distribution_lookup(
"demo-0.1.0-py2.py3-none-any.whl"
)

if not wheel.exists():
wheel = fixture_dir("distributions") / name

if not wheel.exists():
wheel = (
fixture_dir("distributions") / "demo-0.1.0-py2.py3-none-any.whl"
)
if not wheel:
return 404, response_headers, b"Not Found"

wheel_bytes = wheel.read_bytes()

Expand Down
45 changes: 0 additions & 45 deletions tests/installation/conftest.py
Original file line number Diff line number Diff line change
@@ -1,45 +0,0 @@
from __future__ import annotations

import re

from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from urllib.parse import urlparse

import pytest


if TYPE_CHECKING:
from httpretty import httpretty
from httpretty.core import HTTPrettyRequest

from tests.types import FixtureDirGetter


@pytest.fixture
def mock_file_downloads(http: type[httpretty], fixture_dir: FixtureDirGetter) -> None:
def callback(
request: HTTPrettyRequest, uri: str, headers: dict[str, Any]
) -> list[int | dict[str, Any] | bytes]:
name = Path(urlparse(uri).path).name

fixture = Path(__file__).parent.parent.joinpath(
"repositories/fixtures/pypi.org/dists/" + name
)

if not fixture.exists():
fixture = fixture_dir("distributions") / name

if not fixture.exists():
fixture = (
fixture_dir("distributions") / "demo-0.1.0-py2.py3-none-any.whl"
)

return [200, headers, fixture.read_bytes()]

http.register_uri(
http.GET,
re.compile("^https://files.pythonhosted.org/.*$"),
body=callback,
)
32 changes: 16 additions & 16 deletions tests/installation/fixtures/old-lock.test
Original file line number Diff line number Diff line change
Expand Up @@ -79,34 +79,34 @@ content-hash = "123456789"

[metadata.files]
attrs = [
{file = "attrs-17.4.0-py2.py3-none-any.whl", hash = "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450"},
{file = "attrs-17.4.0.tar.gz", hash = "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9"},
{file = "attrs-17.4.0-py2.py3-none-any.whl", hash = "sha256:d38e57f381e891928357c68e300d28d3d4dcddc50486d5f8dfaf743d40477619"},
{file = "attrs-17.4.0.tar.gz", hash = "sha256:eb7536a1e6928190b3008c5b350bdf9850d619fff212341cd096f87a27a5e564"},
]
colorama = [
{file = "colorama-0.3.9-py2.py3-none-any.whl", hash = "sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda"},
{file = "colorama-0.3.9.tar.gz", hash = "sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1"},
{file = "colorama-0.3.9-py2.py3-none-any.whl", hash = "sha256:5b632359f1ed2b7676a869812ba0edaacb99be04679b29eb56c07a5e137ab5a2"},
{file = "colorama-0.3.9.tar.gz", hash = "sha256:4c5a15209723ce1330a5c193465fe221098f761e9640d823a2ce7c03f983137f"},
]
funcsigs = [
{file = "funcsigs-1.0.2-py2.py3-none-any.whl", hash = "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca"},
{file = "funcsigs-1.0.2.tar.gz", hash = "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"},
{file = "funcsigs-1.0.2-py2.py3-none-any.whl", hash = "sha256:510ab97424949e726b4b44294018e90142c9aadf8e737cf3a125b4cffed42e79"},
{file = "funcsigs-1.0.2.tar.gz", hash = "sha256:c55716fcd1228645c214b44568d1fb9af2e28668a9c58e72a17a89a75d24ecd6"},
]
more-itertools = [
{file = "more-itertools-4.1.0.tar.gz", hash = "sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44"},
{file = "more_itertools-4.1.0-py2-none-any.whl", hash = "sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e"},
{file = "more_itertools-4.1.0-py3-none-any.whl", hash = "sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea"},
{file = "more-itertools-4.1.0.tar.gz", hash = "sha256:bab2dc6f4be8f9a4a72177842c5283e2dff57c167439a03e3d8d901e854f0f2e"},
{file = "more_itertools-4.1.0-py2-none-any.whl", hash = "sha256:5dd7dfd88d2fdaea446da478ffef8d7151fdf26ee92ac7ed7b14e8d71efe4b62"},
{file = "more_itertools-4.1.0-py3-none-any.whl", hash = "sha256:29b1e1661aaa56875ce090fa219fa84dfc13daecb52cd4fae321f6f57b419ec4"},
]
pluggy = [
{file = "pluggy-0.6.0.tar.gz", hash = "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"},
{file = "pluggy-0.6.0.tar.gz", hash = "sha256:a982e208d054867661d27c6d2a86b17ba05fbb6b1bdc01f42660732dd107f865"},
]
py = [
{file = "py-1.5.3-py2.py3-none-any.whl", hash = "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"},
{file = "py-1.5.3.tar.gz", hash = "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881"},
{file = "py-1.5.3-py2.py3-none-any.whl", hash = "sha256:43ee6c7f95e0ec6a906de49906b79d138d89728fff17109d49f086abc2fdd985"},
{file = "py-1.5.3.tar.gz", hash = "sha256:2df2c513c3af11de15f58189ba5539ddc4768c6f33816dc5c03950c8bd6180fa"},
]
pytest = [
{file = "pytest-3.5.0-py2.py3-none-any.whl", hash = "sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c"},
{file = "pytest-3.5.0.tar.gz", hash = "sha256:fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1"},
{file = "pytest-3.5.0-py2.py3-none-any.whl", hash = "sha256:28e4d9c2ae3196d74805c2eba24f350ae4c791a5b9b397c79b41506a48dc64ca"},
{file = "pytest-3.5.0.tar.gz", hash = "sha256:677b1d6decd29c041fe64276f29f79fbe66e40c59e445eb251366b4a8ab8bf68"},
]
six = [
{file = "six-1.11.0-py2.py3-none-any.whl", hash = "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"},
{file = "six-1.11.0.tar.gz", hash = "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"},
{file = "six-1.11.0-py2.py3-none-any.whl", hash = "sha256:112f5b46e6aa106db3e4e2494a03694c938f41c4c4535edbdfc816c2e0cb50f2"},
{file = "six-1.11.0.tar.gz", hash = "sha256:268a4ccb159c1a2d2c79336b02e75058387b0cdbb4cea2f07846a758f48a356d"},
]
32 changes: 16 additions & 16 deletions tests/installation/fixtures/with-pypi-repository.test
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 1.5.0.dev0 and should not be changed by hand.
# This file is automatically @generated by Poetry 1.9.0.dev0 and should not be changed by hand.

[[package]]
name = "attrs"
Expand All @@ -7,8 +7,8 @@ description = "Classes Without Boilerplate"
optional = false
python-versions = "*"
files = [
{file = "attrs-17.4.0-py2.py3-none-any.whl", hash = "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450"},
{file = "attrs-17.4.0.tar.gz", hash = "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9"},
{file = "attrs-17.4.0-py2.py3-none-any.whl", hash = "sha256:d38e57f381e891928357c68e300d28d3d4dcddc50486d5f8dfaf743d40477619"},
{file = "attrs-17.4.0.tar.gz", hash = "sha256:eb7536a1e6928190b3008c5b350bdf9850d619fff212341cd096f87a27a5e564"},
]

[package.extras]
Expand All @@ -23,8 +23,8 @@ description = "Cross-platform colored terminal text."
optional = false
python-versions = "*"
files = [
{file = "colorama-0.3.9-py2.py3-none-any.whl", hash = "sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda"},
{file = "colorama-0.3.9.tar.gz", hash = "sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1"},
{file = "colorama-0.3.9-py2.py3-none-any.whl", hash = "sha256:5b632359f1ed2b7676a869812ba0edaacb99be04679b29eb56c07a5e137ab5a2"},
{file = "colorama-0.3.9.tar.gz", hash = "sha256:4c5a15209723ce1330a5c193465fe221098f761e9640d823a2ce7c03f983137f"},
]

[[package]]
Expand All @@ -34,9 +34,9 @@ description = "More routines for operating on iterables, beyond itertools"
optional = false
python-versions = "*"
files = [
{file = "more-itertools-4.1.0.tar.gz", hash = "sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44"},
{file = "more_itertools-4.1.0-py2-none-any.whl", hash = "sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e"},
{file = "more_itertools-4.1.0-py3-none-any.whl", hash = "sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea"},
{file = "more-itertools-4.1.0.tar.gz", hash = "sha256:bab2dc6f4be8f9a4a72177842c5283e2dff57c167439a03e3d8d901e854f0f2e"},
{file = "more_itertools-4.1.0-py2-none-any.whl", hash = "sha256:5dd7dfd88d2fdaea446da478ffef8d7151fdf26ee92ac7ed7b14e8d71efe4b62"},
{file = "more_itertools-4.1.0-py3-none-any.whl", hash = "sha256:29b1e1661aaa56875ce090fa219fa84dfc13daecb52cd4fae321f6f57b419ec4"},
]

[package.dependencies]
Expand All @@ -49,7 +49,7 @@ description = "plugin and hook calling mechanisms for python"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
{file = "pluggy-0.6.0.tar.gz", hash = "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"},
{file = "pluggy-0.6.0.tar.gz", hash = "sha256:a982e208d054867661d27c6d2a86b17ba05fbb6b1bdc01f42660732dd107f865"},
]

[[package]]
Expand All @@ -59,8 +59,8 @@ description = "library with cross-python path, ini-parsing, io, code, log facili
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
{file = "py-1.5.3-py2.py3-none-any.whl", hash = "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"},
{file = "py-1.5.3.tar.gz", hash = "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881"},
{file = "py-1.5.3-py2.py3-none-any.whl", hash = "sha256:43ee6c7f95e0ec6a906de49906b79d138d89728fff17109d49f086abc2fdd985"},
{file = "py-1.5.3.tar.gz", hash = "sha256:2df2c513c3af11de15f58189ba5539ddc4768c6f33816dc5c03950c8bd6180fa"},
]

[[package]]
Expand All @@ -70,8 +70,8 @@ description = "pytest: simple powerful testing with Python"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
{file = "pytest-3.5.0-py2.py3-none-any.whl", hash = "sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c"},
{file = "pytest-3.5.0.tar.gz", hash = "sha256:fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1"},
{file = "pytest-3.5.0-py2.py3-none-any.whl", hash = "sha256:28e4d9c2ae3196d74805c2eba24f350ae4c791a5b9b397c79b41506a48dc64ca"},
{file = "pytest-3.5.0.tar.gz", hash = "sha256:677b1d6decd29c041fe64276f29f79fbe66e40c59e445eb251366b4a8ab8bf68"},
]

[package.dependencies]
Expand All @@ -91,7 +91,7 @@ optional = false
python-versions = ">=3.7"
files = [
{file = "setuptools-67.6.1-py3-none-any.whl", hash = "sha256:e728ca814a823bf7bf60162daf9db95b93d532948c4c0bea762ce62f60189078"},
{file = "setuptools-67.6.1.tar.gz", hash = "sha256:257de92a9d50a60b8e22abfcbb771571fde0dbf3ec234463212027a4eeecbe9a"},
{file = "setuptools-67.6.1.tar.gz", hash = "sha256:a737d365c957dd3fced9ddd246118e95dce7a62c3dc49f37e7fdd9e93475d785"},
]

[package.extras]
Expand All @@ -106,8 +106,8 @@ description = "Python 2 and 3 compatibility utilities"
optional = false
python-versions = "*"
files = [
{file = "six-1.11.0-py2.py3-none-any.whl", hash = "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"},
{file = "six-1.11.0.tar.gz", hash = "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"},
{file = "six-1.11.0-py2.py3-none-any.whl", hash = "sha256:112f5b46e6aa106db3e4e2494a03694c938f41c4c4535edbdfc816c2e0cb50f2"},
{file = "six-1.11.0.tar.gz", hash = "sha256:268a4ccb159c1a2d2c79336b02e75058387b0cdbb4cea2f07846a758f48a356d"},
]

[metadata]
Expand Down
13 changes: 4 additions & 9 deletions tests/installation/test_chef.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,24 @@
from poetry.repositories import RepositoryPool
from poetry.utils.env import EnvManager
from poetry.utils.env import ephemeral_environment
from tests.repositories.test_pypi_repository import MockRepository


if TYPE_CHECKING:
from collections.abc import Collection

from pytest_mock import MockerFixture

from poetry.repositories.pypi_repository import PyPiRepository
from poetry.utils.cache import ArtifactCache
from tests.conftest import Config
from tests.types import FixtureDirGetter


@pytest.fixture()
def pool() -> RepositoryPool:
def pool(pypi_repository: PyPiRepository) -> RepositoryPool:
pool = RepositoryPool()

pool.add_repository(MockRepository())
pool.add_repository(pypi_repository)

return pool

Expand All @@ -50,9 +50,7 @@ def setup(mocker: MockerFixture, pool: RepositoryPool) -> None:
mocker.patch.object(Factory, "create_pool", return_value=pool)


def test_isolated_env_install_success(
pool: RepositoryPool, mock_file_downloads: None
) -> None:
def test_isolated_env_install_success(pool: RepositoryPool) -> None:
with ephemeral_environment(Path(sys.executable)) as venv:
env = IsolatedEnv(venv, pool)
assert "poetry-core" not in venv.run("pip", "freeze")
Expand Down Expand Up @@ -92,7 +90,6 @@ def test_prepare_sdist(
config_cache_dir: Path,
artifact_cache: ArtifactCache,
fixture_dir: FixtureDirGetter,
mock_file_downloads: None,
) -> None:
chef = Chef(
artifact_cache, EnvManager.get_system_env(), Factory.create_pool(config)
Expand All @@ -111,7 +108,6 @@ def test_prepare_directory(
config_cache_dir: Path,
artifact_cache: ArtifactCache,
fixture_dir: FixtureDirGetter,
mock_file_downloads: None,
) -> None:
chef = Chef(
artifact_cache, EnvManager.get_system_env(), Factory.create_pool(config)
Expand Down Expand Up @@ -155,7 +151,6 @@ def test_prepare_directory_editable(
config_cache_dir: Path,
artifact_cache: ArtifactCache,
fixture_dir: FixtureDirGetter,
mock_file_downloads: None,
) -> None:
chef = Chef(
artifact_cache, EnvManager.get_system_env(), Factory.create_pool(config)
Expand Down
Loading

0 comments on commit b146dc9

Please sign in to comment.