Revert to running tests from from a temp dir when test-sources is unset (#2420)
* Revert to running tests from from a temp dir when test-sources is unset
* Fix placeholders error message, add test for it
* Add back {project} placeholders to CIBW_TEST_COMMAND in tests & docs
* Update test/test_before_test.py
---------
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
This commit is contained in:
co-authored by
Henry Schreiner
parent
7298563b25
commit
6379772957
@@ -559,19 +559,19 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
env=test_env,
|
env=test_env,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not build_options.test_sources:
|
testbed_app_path = testbed_path / "iOSTestbed" / "app"
|
||||||
# iOS requires an explicit test-sources, as the project directory
|
|
||||||
# isn't visible on the simulator.
|
|
||||||
|
|
||||||
msg = "Testing on iOS requires a definition of test-sources."
|
|
||||||
raise errors.FatalError(msg)
|
|
||||||
|
|
||||||
# Copy the test sources to the testbed app
|
# Copy the test sources to the testbed app
|
||||||
copy_test_sources(
|
if build_options.test_sources:
|
||||||
build_options.test_sources,
|
copy_test_sources(
|
||||||
build_options.package_dir,
|
build_options.test_sources,
|
||||||
testbed_path / "iOSTestbed" / "app",
|
build_options.package_dir,
|
||||||
)
|
testbed_app_path,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
(testbed_app_path / "test_fail.py").write_text(
|
||||||
|
resources.TEST_FAIL_CWD_FILE.read_text()
|
||||||
|
)
|
||||||
|
|
||||||
log.step("Installing test requirements...")
|
log.step("Installing test requirements...")
|
||||||
# Install the compiled wheel (with any test extras), plus
|
# Install the compiled wheel (with any test extras), plus
|
||||||
@@ -598,6 +598,26 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
|
|
||||||
log.step("Running test suite...")
|
log.step("Running test suite...")
|
||||||
|
|
||||||
|
# iOS doesn't support placeholders in the test command,
|
||||||
|
# because the source dir isn't visible on the simulator.
|
||||||
|
if (
|
||||||
|
"{project}" in build_options.test_command
|
||||||
|
or "{package}" in build_options.test_command
|
||||||
|
):
|
||||||
|
msg = unwrap_preserving_paragraphs(
|
||||||
|
f"""
|
||||||
|
iOS tests configured with a test command that uses the "{{project}}" or
|
||||||
|
"{{package}}" placeholder. iOS tests cannot use placeholders, because the
|
||||||
|
source directory is not visible on the simulator.
|
||||||
|
|
||||||
|
In addition, iOS tests must run as a Python module, so the test command
|
||||||
|
must begin with 'python -m'.
|
||||||
|
|
||||||
|
Test command: {build_options.test_command!r}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
raise errors.FatalError(msg)
|
||||||
|
|
||||||
test_command_parts = shlex.split(build_options.test_command)
|
test_command_parts = shlex.split(build_options.test_command)
|
||||||
if test_command_parts[0:2] != ["python", "-m"]:
|
if test_command_parts[0:2] != ["python", "-m"]:
|
||||||
first_part = test_command_parts[0]
|
first_part = test_command_parts[0]
|
||||||
|
|||||||
@@ -398,9 +398,10 @@ def build_in_container(
|
|||||||
wheel=wheel_to_test,
|
wheel=wheel_to_test,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
test_cwd = testing_temp_dir / "test_cwd"
|
||||||
|
container.call(["mkdir", "-p", test_cwd])
|
||||||
|
|
||||||
if build_options.test_sources:
|
if build_options.test_sources:
|
||||||
test_cwd = testing_temp_dir / "test_cwd"
|
|
||||||
container.call(["mkdir", "-p", test_cwd])
|
|
||||||
copy_test_sources(
|
copy_test_sources(
|
||||||
build_options.test_sources,
|
build_options.test_sources,
|
||||||
build_options.package_dir,
|
build_options.package_dir,
|
||||||
@@ -408,8 +409,9 @@ def build_in_container(
|
|||||||
copy_into=container.copy_into,
|
copy_into=container.copy_into,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# There are no test sources. Run the tests in the project directory.
|
# Use the test_fail.py file to raise a nice error if the user
|
||||||
test_cwd = PurePosixPath(container_project_path)
|
# tries to run tests in the cwd
|
||||||
|
container.copy_into(resources.TEST_FAIL_CWD_FILE, test_cwd / "test_fail.py")
|
||||||
|
|
||||||
container.call(["sh", "-c", test_command_prepared], cwd=test_cwd, env=virtualenv_env)
|
container.call(["sh", "-c", test_command_prepared], cwd=test_cwd, env=virtualenv_env)
|
||||||
|
|
||||||
|
|||||||
@@ -706,8 +706,9 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
wheel=repaired_wheel,
|
wheel=repaired_wheel,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
test_cwd = identifier_tmp_dir / "test_cwd"
|
||||||
|
|
||||||
if build_options.test_sources:
|
if build_options.test_sources:
|
||||||
test_cwd = identifier_tmp_dir / "test_cwd"
|
|
||||||
# only create test_cwd if it doesn't already exist - it
|
# only create test_cwd if it doesn't already exist - it
|
||||||
# may have been created during a previous `testing_arch`
|
# may have been created during a previous `testing_arch`
|
||||||
if not test_cwd.exists():
|
if not test_cwd.exists():
|
||||||
@@ -718,8 +719,12 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
test_cwd,
|
test_cwd,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# There are no test sources. Run the tests in the project directory.
|
# Use the test_fail.py file to raise a nice error if the user
|
||||||
test_cwd = Path.cwd()
|
# tries to run tests in the cwd
|
||||||
|
test_cwd.mkdir(exist_ok=True)
|
||||||
|
(test_cwd / "test_fail.py").write_text(
|
||||||
|
resources.TEST_FAIL_CWD_FILE.read_text()
|
||||||
|
)
|
||||||
|
|
||||||
shell_with_arch(test_command_prepared, cwd=test_cwd, env=virtualenv_env)
|
shell_with_arch(test_command_prepared, cwd=test_cwd, env=virtualenv_env)
|
||||||
|
|
||||||
|
|||||||
@@ -523,17 +523,19 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
package=build_options.package_dir.resolve(),
|
package=build_options.package_dir.resolve(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
test_cwd = identifier_tmp_dir / "test_cwd"
|
||||||
|
test_cwd.mkdir(exist_ok=True)
|
||||||
|
|
||||||
if build_options.test_sources:
|
if build_options.test_sources:
|
||||||
test_cwd = identifier_tmp_dir / "test_cwd"
|
|
||||||
test_cwd.mkdir(exist_ok=True)
|
|
||||||
copy_test_sources(
|
copy_test_sources(
|
||||||
build_options.test_sources,
|
build_options.test_sources,
|
||||||
build_options.package_dir,
|
build_options.package_dir,
|
||||||
test_cwd,
|
test_cwd,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# There are no test sources. Run the tests in the project directory.
|
# Use the test_fail.py file to raise a nice error if the user
|
||||||
test_cwd = Path.cwd()
|
# tries to run tests in the cwd
|
||||||
|
(test_cwd / "test_fail.py").write_text(resources.TEST_FAIL_CWD_FILE.read_text())
|
||||||
|
|
||||||
shell(test_command_prepared, cwd=test_cwd, env=virtualenv_env)
|
shell(test_command_prepared, cwd=test_cwd, env=virtualenv_env)
|
||||||
|
|
||||||
|
|||||||
@@ -588,24 +588,26 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
# run the tests from a temp dir, with an absolute path in the command
|
# run the tests from a temp dir, with an absolute path in the command
|
||||||
# (this ensures that Python runs the tests against the installed wheel
|
# (this ensures that Python runs the tests against the installed wheel
|
||||||
# and not the repo code)
|
# and not the repo code)
|
||||||
test_command_prepared = prepare_command(
|
test_cwd = identifier_tmp_dir / "test_cwd"
|
||||||
build_options.test_command,
|
test_cwd.mkdir()
|
||||||
project=Path.cwd(),
|
|
||||||
package=options.globals.package_dir.resolve(),
|
|
||||||
wheel=repaired_wheel,
|
|
||||||
)
|
|
||||||
if build_options.test_sources:
|
if build_options.test_sources:
|
||||||
test_cwd = identifier_tmp_dir / "test_cwd"
|
|
||||||
test_cwd.mkdir()
|
|
||||||
copy_test_sources(
|
copy_test_sources(
|
||||||
build_options.test_sources,
|
build_options.test_sources,
|
||||||
build_options.package_dir,
|
build_options.package_dir,
|
||||||
test_cwd,
|
test_cwd,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# There are no test sources. Run the tests in the project directory.
|
# Use the test_fail.py file to raise a nice error if the user
|
||||||
test_cwd = Path.cwd()
|
# tries to run tests in the cwd
|
||||||
|
(test_cwd / "test_fail.py").write_text(resources.TEST_FAIL_CWD_FILE.read_text())
|
||||||
|
|
||||||
|
test_command_prepared = prepare_command(
|
||||||
|
build_options.test_command,
|
||||||
|
project=Path.cwd(),
|
||||||
|
package=options.globals.package_dir.resolve(),
|
||||||
|
wheel=repaired_wheel,
|
||||||
|
)
|
||||||
shell(test_command_prepared, cwd=test_cwd, env=virtualenv_env)
|
shell(test_command_prepared, cwd=test_cwd, env=virtualenv_env)
|
||||||
|
|
||||||
# we're all done here; move it to output (remove if already exists)
|
# we're all done here; move it to output (remove if already exists)
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# this file is copied to the testing cwd, to raise the below error message if
|
||||||
|
# pytest/unittest is run from there.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from typing import NoReturn
|
||||||
|
|
||||||
|
|
||||||
|
class TestStringMethods(unittest.TestCase):
|
||||||
|
def test_fail(self) -> NoReturn:
|
||||||
|
if sys.platform == "ios":
|
||||||
|
msg = (
|
||||||
|
"You tried to run tests from the testbed app's working "
|
||||||
|
"directory, without specifying `test-sources`. "
|
||||||
|
"On iOS, you must copy your test files to the testbed app by "
|
||||||
|
"setting the `test-sources` option in your cibuildwheel "
|
||||||
|
"configuration."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
msg = (
|
||||||
|
"cibuildwheel executes tests from a different working directory to "
|
||||||
|
"your project. This ensures only your wheel is imported, preventing "
|
||||||
|
"Python from accessing files that haven't been packaged into the "
|
||||||
|
"wheel. "
|
||||||
|
"\n\n"
|
||||||
|
"Please specify a path to your tests when invoking pytest "
|
||||||
|
"using the {project} placeholder, e.g. `pytest {project}` or "
|
||||||
|
"`pytest {project}/tests`. cibuildwheel will replace {project} with "
|
||||||
|
"the path to your project. "
|
||||||
|
"\n\n"
|
||||||
|
"Alternatively, you can specify your test files using the "
|
||||||
|
"`test-sources` option, and cibuildwheel will copy them to the "
|
||||||
|
"working directory for testing."
|
||||||
|
)
|
||||||
|
|
||||||
|
self.fail(msg)
|
||||||
@@ -17,6 +17,7 @@ CONSTRAINTS: Final[Path] = PATH / "constraints.txt"
|
|||||||
VIRTUALENV: Final[Path] = PATH / "virtualenv.toml"
|
VIRTUALENV: Final[Path] = PATH / "virtualenv.toml"
|
||||||
CIBUILDWHEEL_SCHEMA: Final[Path] = PATH / "cibuildwheel.schema.json"
|
CIBUILDWHEEL_SCHEMA: Final[Path] = PATH / "cibuildwheel.schema.json"
|
||||||
PYTHON_BUILD_STANDALONE_RELEASES: Final[Path] = PATH / "python-build-standalone-releases.json"
|
PYTHON_BUILD_STANDALONE_RELEASES: Final[Path] = PATH / "python-build-standalone-releases.json"
|
||||||
|
TEST_FAIL_CWD_FILE: Final[Path] = PATH / "testing_temp_dir_file.py"
|
||||||
|
|
||||||
|
|
||||||
# this value is cached because it's used a lot in unit tests
|
# this value is cached because it's used a lot in unit tests
|
||||||
|
|||||||
+6
-17
@@ -17,7 +17,7 @@ cibuildwheel to run tests, add the following YAML to your CI config file:
|
|||||||
```yaml
|
```yaml
|
||||||
env:
|
env:
|
||||||
CIBW_TEST_REQUIRES: pytest
|
CIBW_TEST_REQUIRES: pytest
|
||||||
CIBW_TEST_COMMAND: "pytest ./tests"
|
CIBW_TEST_COMMAND: "pytest {project}/tests"
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! tab "Azure Pipelines"
|
!!! tab "Azure Pipelines"
|
||||||
@@ -27,7 +27,7 @@ cibuildwheel to run tests, add the following YAML to your CI config file:
|
|||||||
```yaml
|
```yaml
|
||||||
variables:
|
variables:
|
||||||
CIBW_TEST_REQUIRES: pytest
|
CIBW_TEST_REQUIRES: pytest
|
||||||
CIBW_TEST_COMMAND: "pytest ./tests"
|
CIBW_TEST_COMMAND: "pytest {project}/tests"
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! tab "Travis CI"
|
!!! tab "Travis CI"
|
||||||
@@ -38,18 +38,7 @@ cibuildwheel to run tests, add the following YAML to your CI config file:
|
|||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- CIBW_TEST_REQUIRES=pytest
|
- CIBW_TEST_REQUIRES=pytest
|
||||||
- CIBW_TEST_COMMAND="pytest ./tests"
|
- CIBW_TEST_COMMAND="pytest {project}/tests"
|
||||||
```
|
|
||||||
|
|
||||||
!!! tab "AppVeyor"
|
|
||||||
|
|
||||||
> appveyor.yml ([docs](https://www.appveyor.com/docs/build-configuration/#environment-variables))
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
environment:
|
|
||||||
global:
|
|
||||||
CIBW_TEST_REQUIRES: pytest
|
|
||||||
CIBW_TEST_COMMAND: "pytest {project}\\tests"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! tab "CircleCI"
|
!!! tab "CircleCI"
|
||||||
@@ -61,7 +50,7 @@ cibuildwheel to run tests, add the following YAML to your CI config file:
|
|||||||
job_name:
|
job_name:
|
||||||
environment:
|
environment:
|
||||||
CIBW_TEST_REQUIRES: pytest
|
CIBW_TEST_REQUIRES: pytest
|
||||||
CIBW_TEST_COMMAND: "pytest ./tests"
|
CIBW_TEST_COMMAND: "pytest {project}/tests"
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! tab "Gitlab CI"
|
!!! tab "Gitlab CI"
|
||||||
@@ -72,7 +61,7 @@ cibuildwheel to run tests, add the following YAML to your CI config file:
|
|||||||
linux:
|
linux:
|
||||||
variables:
|
variables:
|
||||||
CIBW_TEST_REQUIRES: pytest
|
CIBW_TEST_REQUIRES: pytest
|
||||||
CIBW_TEST_COMMAND: "pytest ./tests"
|
CIBW_TEST_COMMAND: "pytest {project}/tests"
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! tab "Cirrus CI"
|
!!! tab "Cirrus CI"
|
||||||
@@ -82,7 +71,7 @@ cibuildwheel to run tests, add the following YAML to your CI config file:
|
|||||||
```yaml
|
```yaml
|
||||||
env:
|
env:
|
||||||
CIBW_TEST_REQUIRES: pytest
|
CIBW_TEST_REQUIRES: pytest
|
||||||
CIBW_TEST_COMMAND: "pytest ./tests"
|
CIBW_TEST_COMMAND: "pytest {project}/tests"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration file {: #configuration-file}
|
## Configuration file {: #configuration-file}
|
||||||
|
|||||||
+23
-23
@@ -28,7 +28,7 @@ This option can also be set using the [command-line option](#command-line) `--pl
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
export CIBW_BUILD='cp37-*'
|
export CIBW_BUILD='cp37-*'
|
||||||
export CIBW_TEST_COMMAND='pytest ./tests'
|
export CIBW_TEST_COMMAND='pytest {project}/tests'
|
||||||
cibuildwheel --platform linux .
|
cibuildwheel --platform linux .
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1284,23 +1284,23 @@ Shell command to run tests after the build. The wheel will be installed
|
|||||||
automatically and available for import from the tests. If this variable is not
|
automatically and available for import from the tests. If this variable is not
|
||||||
set, your wheel will not be installed after building.
|
set, your wheel will not be installed after building.
|
||||||
|
|
||||||
By default, tests are executed from your project directory. When specifying
|
To ensure the wheel is imported by your tests (instead of your source copy),
|
||||||
`test-command`, you can optionally use the placeholders `{package}` and
|
**Tests are executed from a temporary directory**, outside of your source
|
||||||
`{project}` to pass in the location of your test code:
|
tree. To access your test code, you have a couple of options:
|
||||||
|
|
||||||
- `{package}` is the path to the package being built - the `package_dir`
|
- You can use the [`test-sources`](#test-sources) setting to copy specific
|
||||||
argument supplied to cibuildwheel on the command line.
|
files from your source tree into the temporary directory. When using
|
||||||
- `{project}` is an absolute path to the project root - the working directory
|
test-sources, use relative paths in your test command, as if they were
|
||||||
where cibuildwheel was called.
|
relative to the project root.
|
||||||
|
|
||||||
Using `{package}` or `{project}` used to be required, but since cibuildwheel
|
- You can use the `{package}` or `{project}` placeholders in your
|
||||||
3.0, tests are run from the project root by default. This means that you can
|
`test-command` to refer to the package being built or the project root,
|
||||||
use relative paths in your test command, and they will be relative to the
|
respectively.
|
||||||
project root.
|
|
||||||
|
|
||||||
Alternatively, you can use the [`test-sources`](#test-sources) setting to
|
- `{package}` is the path to the package being built - the `package_dir`
|
||||||
create a temporary folder populated with a specific subset of project files to
|
argument supplied to cibuildwheel on the command line.
|
||||||
run your test suite.
|
- `{project}` is an absolute path to the project root - the working
|
||||||
|
directory where cibuildwheel was called.
|
||||||
|
|
||||||
On all platforms other than iOS, the command is run in a shell, so you can write things like `cmd1 && cmd2`.
|
On all platforms other than iOS, the command is run in a shell, so you can write things like `cmd1 && cmd2`.
|
||||||
|
|
||||||
@@ -1318,18 +1318,18 @@ Platform-specific environment variables are also available:<br/>
|
|||||||
```toml
|
```toml
|
||||||
[tool.cibuildwheel]
|
[tool.cibuildwheel]
|
||||||
# Run the package tests using `pytest`
|
# Run the package tests using `pytest`
|
||||||
test-command = "pytest ./tests"
|
test-command = "pytest {project}/tests"
|
||||||
|
|
||||||
# Trigger an install of the package, but run nothing of note
|
# Trigger an install of the package, but run nothing of note
|
||||||
test-command = "echo Wheel installed"
|
test-command = "echo Wheel installed"
|
||||||
|
|
||||||
# Multiline example
|
# Multiline example
|
||||||
test-command = [
|
test-command = [
|
||||||
"pytest ./tests",
|
"pytest {project}/tests",
|
||||||
"python ./test.py",
|
"python {project}/test.py",
|
||||||
]
|
]
|
||||||
|
|
||||||
# run tests on ios
|
# run tests on ios - when test-sources is set, use relative paths, not {project} or {package}
|
||||||
[tool.cibuildwheel.ios]
|
[tool.cibuildwheel.ios]
|
||||||
test-sources = ["tests"]
|
test-sources = ["tests"]
|
||||||
test-command = "python -m pytest ./tests"
|
test-command = "python -m pytest ./tests"
|
||||||
@@ -1341,17 +1341,17 @@ Platform-specific environment variables are also available:<br/>
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# Run the package tests using `pytest`
|
# Run the package tests using `pytest`
|
||||||
CIBW_TEST_COMMAND: pytest ./tests
|
CIBW_TEST_COMMAND: pytest {project}/tests
|
||||||
|
|
||||||
# Trigger an install of the package, but run nothing of note
|
# Trigger an install of the package, but run nothing of note
|
||||||
CIBW_TEST_COMMAND: "echo Wheel installed"
|
CIBW_TEST_COMMAND: "echo Wheel installed"
|
||||||
|
|
||||||
# Multi-line example - join with && on all platforms
|
# Multi-line example - join with && on all platforms
|
||||||
CIBW_TEST_COMMAND: >
|
CIBW_TEST_COMMAND: >
|
||||||
pytest ./tests &&
|
pytest {project}/tests &&
|
||||||
python ./test.py
|
python {project}/test.py
|
||||||
|
|
||||||
# run tests on ios
|
# run tests on ios - when test-sources is set, use relative paths, not {project} or {package}
|
||||||
CIBW_TEST_SOURCES_IOS: tests
|
CIBW_TEST_SOURCES_IOS: tests
|
||||||
CIBW_TEST_COMMAND_IOS: python -m pytest ./tests
|
CIBW_TEST_COMMAND_IOS: python -m pytest ./tests
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ def test_abi_none(tmp_path, capfd):
|
|||||||
project_dir,
|
project_dir,
|
||||||
add_env={
|
add_env={
|
||||||
"CIBW_TEST_REQUIRES": "pytest",
|
"CIBW_TEST_REQUIRES": "pytest",
|
||||||
"CIBW_TEST_COMMAND": f"{utils.invoke_pytest()} ./test",
|
"CIBW_TEST_COMMAND": f"{utils.invoke_pytest()} {{project}}/test",
|
||||||
# limit the number of builds for test performance reasons
|
# limit the number of builds for test performance reasons
|
||||||
"CIBW_BUILD": "cp38-* cp{}{}-* cp313t-* pp310-*".format(*utils.SINGLE_PYTHON_VERSION),
|
"CIBW_BUILD": "cp38-* cp{}{}-* cp313t-* pp310-*".format(*utils.SINGLE_PYTHON_VERSION),
|
||||||
"CIBW_ENABLE": "all",
|
"CIBW_ENABLE": "all",
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ def test(tmp_path, build_frontend_env):
|
|||||||
"CIBW_TEST_REQUIRES": "pytest",
|
"CIBW_TEST_REQUIRES": "pytest",
|
||||||
# the 'false ||' bit is to ensure this command runs in a shell on
|
# the 'false ||' bit is to ensure this command runs in a shell on
|
||||||
# mac/linux.
|
# mac/linux.
|
||||||
"CIBW_TEST_COMMAND": f"false || {utils.invoke_pytest()} ./test",
|
"CIBW_TEST_COMMAND": f"false || {utils.invoke_pytest()} {{project}}/test",
|
||||||
# pytest fails on GraalPy 24.2.0 on Windows so we skip it there
|
# pytest fails on GraalPy 24.2.0 on Windows so we skip it there
|
||||||
# until https://github.com/oracle/graalpython/issues/490 is fixed
|
# until https://github.com/oracle/graalpython/issues/490 is fixed
|
||||||
"CIBW_TEST_COMMAND_WINDOWS": "where graalpy || pytest ./test",
|
"CIBW_TEST_COMMAND_WINDOWS": "where graalpy || pytest {project}/test",
|
||||||
**build_frontend_env,
|
**build_frontend_env,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ def test(tmp_path, request):
|
|||||||
project_dir,
|
project_dir,
|
||||||
add_env={
|
add_env={
|
||||||
"CIBW_TEST_REQUIRES": "pytest",
|
"CIBW_TEST_REQUIRES": "pytest",
|
||||||
"CIBW_TEST_COMMAND": "pytest ./test",
|
"CIBW_TEST_COMMAND": "pytest {project}/test",
|
||||||
"CIBW_ARCHS": archs,
|
"CIBW_ARCHS": archs,
|
||||||
# TODO remove me once proper support is added
|
# TODO remove me once proper support is added
|
||||||
"CIBW_MANYLINUX_RISCV64_IMAGE": "ghcr.io/mayeut/manylinux_2_35:2025.05.11-1",
|
"CIBW_MANYLINUX_RISCV64_IMAGE": "ghcr.io/mayeut/manylinux_2_35:2025.05.11-1",
|
||||||
|
|||||||
+38
-3
@@ -91,8 +91,9 @@ def test_ios_platforms(tmp_path, build_config, monkeypatch, capfd):
|
|||||||
assert "'does-exist' will be included in the cross-build environment" in captured.out
|
assert "'does-exist' will be included in the cross-build environment" in captured.out
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.serial
|
||||||
def test_no_test_sources(tmp_path, capfd):
|
def test_no_test_sources(tmp_path, capfd):
|
||||||
"""Build will fail if test-sources isn't defined."""
|
"""Build will provide a helpful error if pytest is run and test-sources is not defined."""
|
||||||
if utils.get_platform() != "macos":
|
if utils.get_platform() != "macos":
|
||||||
pytest.skip("this test can only run on macOS")
|
pytest.skip("this test can only run on macOS")
|
||||||
if utils.get_xcode_version() < (13, 0):
|
if utils.get_xcode_version() < (13, 0):
|
||||||
@@ -109,13 +110,47 @@ def test_no_test_sources(tmp_path, capfd):
|
|||||||
add_env={
|
add_env={
|
||||||
"CIBW_PLATFORM": "ios",
|
"CIBW_PLATFORM": "ios",
|
||||||
"CIBW_BUILD": "cp313-*",
|
"CIBW_BUILD": "cp313-*",
|
||||||
"CIBW_TEST_COMMAND": "python -m tests",
|
"CIBW_TEST_REQUIRES": "pytest",
|
||||||
|
"CIBW_TEST_COMMAND": "python -m pytest",
|
||||||
|
"CIBW_XBUILD_TOOLS": "",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# The error message indicates the configuration issue.
|
# The error message indicates the configuration issue.
|
||||||
captured = capfd.readouterr()
|
captured = capfd.readouterr()
|
||||||
assert "Testing on iOS requires a definition of test-sources." in captured.err
|
assert (
|
||||||
|
"you must copy your test files to the testbed app by setting the `test-sources` option"
|
||||||
|
in captured.out + captured.err
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ios_testing_with_placeholder(tmp_path, capfd):
|
||||||
|
"""Build will run tests with the {project} placeholder."""
|
||||||
|
if utils.get_platform() != "macos":
|
||||||
|
pytest.skip("this test can only run on macOS")
|
||||||
|
if utils.get_xcode_version() < (13, 0):
|
||||||
|
pytest.skip("this test only works with Xcode 13.0 or greater")
|
||||||
|
|
||||||
|
project_dir = tmp_path / "project"
|
||||||
|
basic_project = test_projects.new_c_project()
|
||||||
|
basic_project.files.update(basic_project_files)
|
||||||
|
basic_project.generate(project_dir)
|
||||||
|
|
||||||
|
with pytest.raises(subprocess.CalledProcessError):
|
||||||
|
utils.cibuildwheel_run(
|
||||||
|
project_dir,
|
||||||
|
add_env={
|
||||||
|
"CIBW_PLATFORM": "ios",
|
||||||
|
"CIBW_BUILD": "cp313-*",
|
||||||
|
"CIBW_TEST_REQUIRES": "pytest",
|
||||||
|
"CIBW_TEST_COMMAND": "pytest {project}/tests",
|
||||||
|
"CIBW_XBUILD_TOOLS": "",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# The error message indicates the configuration issue.
|
||||||
|
captured = capfd.readouterr()
|
||||||
|
assert "iOS tests cannot use placeholders" in captured.out + captured.err
|
||||||
|
|
||||||
|
|
||||||
def test_missing_xbuild_tool(tmp_path, capfd):
|
def test_missing_xbuild_tool(tmp_path, capfd):
|
||||||
|
|||||||
@@ -42,11 +42,9 @@ def test_cross_compiled_build(tmp_path):
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"test_config",
|
"test_config",
|
||||||
[
|
[
|
||||||
# Run the test suite in the project folder
|
|
||||||
{
|
{
|
||||||
"CIBW_TEST_COMMAND": '''python -c "import platform; print('running tests on ' + platform.machine())"''',
|
"CIBW_TEST_COMMAND": '''python -c "import platform; print('running tests on ' + platform.machine())"''',
|
||||||
},
|
},
|
||||||
# Nominate the set of test sources to copy
|
|
||||||
{
|
{
|
||||||
"CIBW_TEST_COMMAND": "python tests/test_suite.py",
|
"CIBW_TEST_COMMAND": "python tests/test_suite.py",
|
||||||
"CIBW_TEST_SOURCES": "tests",
|
"CIBW_TEST_SOURCES": "tests",
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ def test_pyodide_build_and_test(tmp_path, expect_failure):
|
|||||||
add_args=["--platform", "pyodide"],
|
add_args=["--platform", "pyodide"],
|
||||||
add_env={
|
add_env={
|
||||||
"CIBW_TEST_REQUIRES": "pytest",
|
"CIBW_TEST_REQUIRES": "pytest",
|
||||||
"CIBW_TEST_COMMAND": "python -m pytest",
|
"CIBW_TEST_COMMAND": "python -m pytest {project}",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
# check that the expected wheels are produced
|
# check that the expected wheels are produced
|
||||||
|
|||||||
+37
-25
@@ -86,10 +86,10 @@ def test(tmp_path):
|
|||||||
"CIBW_TEST_REQUIRES": "pytest",
|
"CIBW_TEST_REQUIRES": "pytest",
|
||||||
# the 'false ||' bit is to ensure this command runs in a shell on
|
# the 'false ||' bit is to ensure this command runs in a shell on
|
||||||
# mac/linux.
|
# mac/linux.
|
||||||
"CIBW_TEST_COMMAND": f"false || {utils.invoke_pytest()} ./test",
|
"CIBW_TEST_COMMAND": f"false || {utils.invoke_pytest()} {{project}}/test",
|
||||||
# pytest fails on GraalPy 24.2.0 on Windows so we skip it there
|
# pytest fails on GraalPy 24.2.0 on Windows so we skip it there
|
||||||
# until https://github.com/oracle/graalpython/issues/490 is fixed
|
# until https://github.com/oracle/graalpython/issues/490 is fixed
|
||||||
"CIBW_TEST_COMMAND_WINDOWS": "COLOR 00 || where graalpy || pytest ./test",
|
"CIBW_TEST_COMMAND_WINDOWS": "COLOR 00 || where graalpy || pytest {project}/test",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -109,10 +109,10 @@ def test_extras_require(tmp_path):
|
|||||||
"CIBW_TEST_EXTRAS": "test",
|
"CIBW_TEST_EXTRAS": "test",
|
||||||
# the 'false ||' bit is to ensure this command runs in a shell on
|
# the 'false ||' bit is to ensure this command runs in a shell on
|
||||||
# mac/linux.
|
# mac/linux.
|
||||||
"CIBW_TEST_COMMAND": f"false || {utils.invoke_pytest()} ./test",
|
"CIBW_TEST_COMMAND": f"false || {utils.invoke_pytest()} {{project}}/test",
|
||||||
# pytest fails on GraalPy 24.2.0 on Windows so we skip it there
|
# pytest fails on GraalPy 24.2.0 on Windows so we skip it there
|
||||||
# until https://github.com/oracle/graalpython/issues/490 is fixed
|
# until https://github.com/oracle/graalpython/issues/490 is fixed
|
||||||
"CIBW_TEST_COMMAND_WINDOWS": "COLOR 00 || where graalpy || pytest ./test",
|
"CIBW_TEST_COMMAND_WINDOWS": "COLOR 00 || where graalpy || pytest {project}/test",
|
||||||
},
|
},
|
||||||
single_python=True,
|
single_python=True,
|
||||||
)
|
)
|
||||||
@@ -143,10 +143,10 @@ def test_dependency_groups(tmp_path):
|
|||||||
"CIBW_TEST_GROUPS": "dev",
|
"CIBW_TEST_GROUPS": "dev",
|
||||||
# the 'false ||' bit is to ensure this command runs in a shell on
|
# the 'false ||' bit is to ensure this command runs in a shell on
|
||||||
# mac/linux.
|
# mac/linux.
|
||||||
"CIBW_TEST_COMMAND": f"false || {utils.invoke_pytest()} ./test",
|
"CIBW_TEST_COMMAND": f"false || {utils.invoke_pytest()} {{project}}/test",
|
||||||
# pytest fails on GraalPy 24.2.0 on Windows so we skip it there
|
# pytest fails on GraalPy 24.2.0 on Windows so we skip it there
|
||||||
# until https://github.com/oracle/graalpython/issues/490 is fixed
|
# until https://github.com/oracle/graalpython/issues/490 is fixed
|
||||||
"CIBW_TEST_COMMAND_WINDOWS": "COLOR 00 || where graalpy || pytest ./test",
|
"CIBW_TEST_COMMAND_WINDOWS": "COLOR 00 || where graalpy || pytest {project}/test",
|
||||||
},
|
},
|
||||||
single_python=True,
|
single_python=True,
|
||||||
)
|
)
|
||||||
@@ -178,7 +178,7 @@ def test_failing_test(tmp_path):
|
|||||||
output_dir=output_dir,
|
output_dir=output_dir,
|
||||||
add_env={
|
add_env={
|
||||||
"CIBW_TEST_REQUIRES": "pytest",
|
"CIBW_TEST_REQUIRES": "pytest",
|
||||||
"CIBW_TEST_COMMAND": f"{utils.invoke_pytest()} ./test",
|
"CIBW_TEST_COMMAND": f"{utils.invoke_pytest()} {{project}}/test",
|
||||||
# CPython 3.8 when running on macOS arm64 is unusual. The build
|
# CPython 3.8 when running on macOS arm64 is unusual. The build
|
||||||
# always runs in x86_64, so the arm64 tests are not run. See
|
# always runs in x86_64, so the arm64 tests are not run. See
|
||||||
# #1169 for reasons why. That means the build succeeds, which
|
# #1169 for reasons why. That means the build succeeds, which
|
||||||
@@ -191,29 +191,41 @@ def test_failing_test(tmp_path):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("test_runner", ["pytest", "unittest"])
|
@pytest.mark.parametrize("test_runner", ["pytest", "unittest"])
|
||||||
def test_bare_pytest_invocation(tmp_path: Path, test_runner: str) -> None:
|
def test_bare_pytest_invocation(
|
||||||
"""Check that if a user runs a bare test suite, it runs in the project folder"""
|
tmp_path: Path, capfd: pytest.CaptureFixture[str], test_runner: str
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Check that if a user runs pytest in the the test cwd without setting
|
||||||
|
test-sources, it raises a helpful error
|
||||||
|
"""
|
||||||
project_dir = tmp_path / "project"
|
project_dir = tmp_path / "project"
|
||||||
project_with_a_test.generate(project_dir)
|
project_with_a_test.generate(project_dir)
|
||||||
|
output_dir = tmp_path / "output"
|
||||||
|
|
||||||
actual_wheels = utils.cibuildwheel_run(
|
with pytest.raises(subprocess.CalledProcessError):
|
||||||
project_dir,
|
utils.cibuildwheel_run(
|
||||||
add_env={
|
project_dir,
|
||||||
"CIBW_TEST_REQUIRES": "pytest" if test_runner == "pytest" else "",
|
output_dir=output_dir,
|
||||||
"CIBW_TEST_COMMAND": (
|
add_env={
|
||||||
# pytest fails on GraalPy 24.2.0 on Windows so we skip it there
|
"CIBW_TEST_REQUIRES": "pytest" if test_runner == "pytest" else "",
|
||||||
# until https://github.com/oracle/graalpython/issues/490 fixed
|
"CIBW_TEST_COMMAND": (
|
||||||
"graalpy.exe -c 1 || python -m pytest"
|
"python -m pytest" if test_runner == "pytest" else "python -m unittest"
|
||||||
if test_runner == "pytest"
|
),
|
||||||
else "python -m unittest discover test spam_test.py"
|
# Skip CPython 3.8 on macOS arm64, see comment above in
|
||||||
),
|
# 'test_failing_test'
|
||||||
},
|
"CIBW_SKIP": "cp38-macosx_arm64",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(list(output_dir.iterdir())) == 0
|
||||||
|
|
||||||
|
captured = capfd.readouterr()
|
||||||
|
|
||||||
|
assert (
|
||||||
|
"Please specify a path to your tests when invoking pytest using the {project} placeholder"
|
||||||
|
in captured.out + captured.err
|
||||||
)
|
)
|
||||||
|
|
||||||
# check that we got the right wheels
|
|
||||||
expected_wheels = utils.expected_wheels("spam", "0.1.0")
|
|
||||||
assert set(actual_wheels) == set(expected_wheels)
|
|
||||||
|
|
||||||
|
|
||||||
def test_test_sources(tmp_path):
|
def test_test_sources(tmp_path):
|
||||||
project_dir = tmp_path / "project"
|
project_dir = tmp_path / "project"
|
||||||
|
|||||||
Reference in New Issue
Block a user