Skip to content

Commit 1bc7e90

Browse files
authored
Improve integration test options (#2385)
* Improve integration test options - Keep the platform and enable options in os.environ, don't duplicate state in utils - Provide more user-friendly options for setting enable and platform in integration tests * Ensure that CIBW_ENABLE is set in the test process * Use get_enable_groups() where necessary
1 parent 166465b commit 1bc7e90

24 files changed

+130
-75
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ jobs:
8383
CIBW_ENABLE=all
8484
else
8585
# get the default CIBW_ENABLE value from the test module
86-
CIBW_ENABLE=$(uv run --no-sync python -c 'import sys, test.conftest as c; sys.stdout.write(c.DEFAULT_CIBW_ENABLE)')
86+
CIBW_ENABLE=$(uv run --no-sync python -c 'import sys, test.utils as c; sys.stdout.write(c.DEFAULT_CIBW_ENABLE)')
8787
8888
# if this is a PR, check for labels
8989
if [[ -n "$GITHUB_PR_LABEL_CI_PYPY" ]]; then

docs/contributing.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ nox -s tests -- test -k before_build
7878

7979
A few notes-
8080

81-
- Because they run inside a container, Linux tests can run on all platforms where Docker is installed, so they're convenient for running integration tests locally. Set CIBW_PLATFORM to do this: `CIBW_PLATFORM=linux nox -s tests -- test`.
81+
- Because they run inside a container, Linux tests can run on all platforms where Docker is installed, so they're convenient for running integration tests locally. Set the `--platform` flag on pytest to do this: `nox -s tests -- test --platform linux`.
8282

8383
- Running the macOS integration tests requires _system installs_ of Python from python.org for all the versions that are tested. We won't attempt to install these when running locally, but you can do so manually using the URL in the error message that is printed when the install is not found.
8484

85-
- The 'enable groups' run by default are just 'cpython-prerelease' and 'cpython-freethreading'. You can add other groups like pypy or graalpy by setting the [CIBW_ENABLE](options.md#enable) environment variable. On GitHub PRs, you can add a label to the PR to enable these groups.
85+
- The ['enable groups'](options.md#enable) run by default are just 'cpython-prerelease' and 'cpython-freethreading'. You can add other groups like pypy or graalpy by passing the `--enable` argument to pytest, i.e. `nox -s tests -- test --enable pypy`. On GitHub PRs, you can add a label to the PR to enable these groups.
8686

8787
#### Running pytest directly
8888

test/conftest.py

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@
99
from cibuildwheel.architecture import Architecture
1010
from cibuildwheel.ci import detect_ci_provider
1111
from cibuildwheel.options import CommandLineArguments, Options
12+
from cibuildwheel.selector import EnableGroup
13+
from cibuildwheel.typing import PLATFORMS
1214
from cibuildwheel.venv import find_uv
1315

14-
from .utils import EMULATED_ARCHS, platform
15-
16-
# default to just cpython
17-
DEFAULT_CIBW_ENABLE = "cpython-freethreading cpython-prerelease cpython-experimental-riscv64"
16+
from .utils import DEFAULT_CIBW_ENABLE, EMULATED_ARCHS, get_platform
1817

1918

2019
def pytest_addoption(parser: pytest.Parser) -> None:
@@ -32,8 +31,47 @@ def pytest_addoption(parser: pytest.Parser) -> None:
3231
default=False,
3332
help="macOS cp38 uses the universal2 installer",
3433
)
34+
parser.addoption(
35+
"--enable",
36+
action="store",
37+
default=None,
38+
help="Set the CIBW_ENABLE environment variable for all tests.",
39+
)
40+
parser.addoption(
41+
"--platform",
42+
action="store",
43+
default=None,
44+
help="Set the CIBW_PLATFORM environment variable for all tests.",
45+
)
46+
47+
48+
def pytest_configure(config):
49+
flag_enable = config.getoption("--enable")
50+
flag_platform = config.getoption("--platform")
51+
52+
if flag_enable is not None and "CIBW_ENABLE" in os.environ:
53+
msg = (
54+
"Both --enable pytest option and CIBW_ENABLE environment variable are set. "
55+
"Please specify only one."
56+
)
57+
raise pytest.UsageError(msg)
58+
if flag_platform is not None and "CIBW_PLATFORM" in os.environ:
59+
msg = (
60+
"Both --platform pytest option and CIBW_PLATFORM environment variable are set. "
61+
"Please specify only one."
62+
)
63+
raise pytest.UsageError(msg)
64+
65+
if flag_enable is not None:
66+
EnableGroup.parse_option_value(flag_enable)
67+
os.environ["CIBW_ENABLE"] = flag_enable
68+
if flag_enable is None and "CIBW_ENABLE" not in os.environ:
69+
# Set default value for CIBW_ENABLE
70+
os.environ["CIBW_ENABLE"] = DEFAULT_CIBW_ENABLE
3571

36-
os.environ.setdefault("CIBW_ENABLE", DEFAULT_CIBW_ENABLE)
72+
if flag_platform is not None:
73+
assert flag_platform in PLATFORMS, f"Invalid platform: {flag_platform}"
74+
os.environ["CIBW_PLATFORM"] = flag_platform
3775

3876

3977
def docker_warmup(request: pytest.FixtureRequest) -> None:
@@ -91,7 +129,7 @@ def docker_warmup_fixture(
91129
request: pytest.FixtureRequest, tmp_path_factory: pytest.TempPathFactory, worker_id: str
92130
) -> None:
93131
# if we're in CI testing linux, let's warm-up docker images
94-
if detect_ci_provider() is None or platform != "linux":
132+
if detect_ci_provider() is None or get_platform() != "linux":
95133
return None
96134
if request.config.getoption("--run-emulation", default=None) is not None:
97135
# emulation tests only run one test in CI, caching the image only slows down the test
@@ -116,7 +154,7 @@ def docker_warmup_fixture(
116154
@pytest.fixture(params=["pip", "build"])
117155
def build_frontend_env_nouv(request: pytest.FixtureRequest) -> dict[str, str]:
118156
frontend = request.param
119-
if platform == "pyodide" and frontend == "pip":
157+
if get_platform() == "pyodide" and frontend == "pip":
120158
pytest.skip("Can't use pip as build frontend for pyodide platform")
121159

122160
return {"CIBW_BUILD_FRONTEND": frontend}
@@ -125,7 +163,7 @@ def build_frontend_env_nouv(request: pytest.FixtureRequest) -> dict[str, str]:
125163
@pytest.fixture
126164
def build_frontend_env(build_frontend_env_nouv: dict[str, str]) -> dict[str, str]:
127165
frontend = build_frontend_env_nouv["CIBW_BUILD_FRONTEND"]
128-
if frontend != "build" or platform == "pyodide" or find_uv() is None:
166+
if frontend != "build" or get_platform() == "pyodide" or find_uv() is None:
129167
return build_frontend_env_nouv
130168

131169
return {"CIBW_BUILD_FRONTEND": "build[uv]"}
@@ -134,7 +172,7 @@ def build_frontend_env(build_frontend_env_nouv: dict[str, str]) -> dict[str, str
134172
@pytest.fixture
135173
def docker_cleanup() -> Generator[None, None, None]:
136174
def get_images() -> set[str]:
137-
if detect_ci_provider() is None or platform != "linux":
175+
if detect_ci_provider() is None or get_platform() != "linux":
138176
return set()
139177
images = subprocess.run(
140178
["docker", "image", "ls", "--format", "{{json .ID}}"],

test/test_0_basic.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import os
21
import textwrap
32

43
import pytest
@@ -40,7 +39,7 @@ def test(tmp_path, build_frontend_env, capfd):
4039
expected_wheels = utils.expected_wheels("spam", "0.1.0")
4140
assert set(actual_wheels) == set(expected_wheels)
4241

43-
enable_groups = EnableGroup.parse_option_value(os.environ.get("CIBW_ENABLE", ""))
42+
enable_groups = utils.get_enable_groups()
4443
if EnableGroup.GraalPy not in enable_groups:
4544
# Verify pip warning not shown
4645
captured = capfd.readouterr()

test/test_abi_variants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def test_abi3(tmp_path):
4747
)
4848

4949
# check that the expected wheels are produced
50-
if utils.platform == "pyodide":
50+
if utils.get_platform() == "pyodide":
5151
# there's only 1 possible configuration for pyodide, cp312
5252
expected_wheels = utils.expected_wheels("spam", "0.1.0", python_abi_tags=["cp310-abi3"])
5353
else:
@@ -196,7 +196,7 @@ def test_abi_none(tmp_path, capfd):
196196
# check that each wheel was built once, and reused
197197
captured = capfd.readouterr()
198198
assert "Building wheel..." in captured.out
199-
if utils.platform == "pyodide":
199+
if utils.get_platform() == "pyodide":
200200
# there's only 1 possible configuration for pyodide, we won't see the message expected on following builds
201201
assert "Found previously built wheel" not in captured.out
202202
else:

test/test_before_build.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from . import test_projects, utils
77

88
# pyodide does not support building without isolation, need to check the base_prefix
9-
SYS_PREFIX = f"sys.{'base_' if utils.platform == 'pyodide' else ''}prefix"
9+
SYS_PREFIX = f"sys.{'base_' if utils.get_platform() == 'pyodide' else ''}prefix"
1010

1111

1212
project_with_before_build_asserts = test_projects.new_c_project(
@@ -45,7 +45,7 @@ def test(tmp_path):
4545
f'''python -c "import pathlib, sys; pathlib.Path('{{project}}/pythonprefix_bb.txt').write_text({SYS_PREFIX})"'''
4646
)
4747
frontend = "build"
48-
if utils.platform != "pyodide":
48+
if utils.get_platform() != "pyodide":
4949
before_build = f"python -m pip install setuptools && {before_build}"
5050
frontend = f"{frontend};args: --no-isolation"
5151

test/test_before_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def test(tmp_path, build_frontend_env):
4343
'''python -c "import pathlib, sys; pathlib.Path('{project}/pythonprefix_bt.txt').write_text(sys.prefix)"''',
4444
]
4545

46-
if utils.platform == "pyodide":
46+
if utils.get_platform() == "pyodide":
4747
before_test_steps.extend(
4848
["pyodide build {project}/dependency", "pip install --find-links dist/ spam"]
4949
)

test/test_build_frontend_args.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def test_build_frontend_args(tmp_path, capfd, frontend_name):
2020

2121
# the build will fail because the frontend is called with '-h' - it prints the help message
2222
add_env = {"CIBW_BUILD_FRONTEND": f"{frontend_name}; args: -h"}
23-
if utils.platform == "pyodide":
23+
if utils.get_platform() == "pyodide":
2424
add_env["TERM"] = "dumb" # disable color / style
2525
add_env["NO_COLOR"] = "1"
2626
with pytest.raises(subprocess.CalledProcessError):
@@ -33,7 +33,7 @@ def test_build_frontend_args(tmp_path, capfd, frontend_name):
3333
if frontend_name == "pip":
3434
assert "Usage:" in captured.out
3535
assert "Wheel Options:" in captured.out
36-
elif utils.platform == "pyodide":
36+
elif utils.get_platform() == "pyodide":
3737
assert "Usage: pyodide build" in captured.out
3838
else:
3939
assert "usage:" in captured.out

test/test_container_engine.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77

88
def test_podman(tmp_path, capfd, request):
9-
if utils.platform != "linux":
9+
if utils.get_platform() != "linux":
1010
pytest.skip("the test is only relevant to the linux build")
1111

1212
if not request.config.getoption("--run-podman"):
@@ -36,7 +36,7 @@ def test_podman(tmp_path, capfd, request):
3636

3737

3838
def test_create_args(tmp_path, capfd):
39-
if utils.platform != "linux":
39+
if utils.get_platform() != "linux":
4040
pytest.skip("the test is only relevant to the linux build")
4141

4242
project_dir = tmp_path / "project"

test/test_container_images.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
@pytest.mark.usefixtures("docker_cleanup")
2525
def test(tmp_path):
26-
if utils.platform != "linux":
26+
if utils.get_platform() != "linux":
2727
pytest.skip("the test is only relevant to the linux build")
2828
if platform.machine() not in ["x86_64", "i686"]:
2929
pytest.skip(

0 commit comments

Comments
 (0)