diff --git a/cibuildwheel/platforms/ios.py b/cibuildwheel/platforms/ios.py index dc4911f75..4837b67dc 100644 --- a/cibuildwheel/platforms/ios.py +++ b/cibuildwheel/platforms/ios.py @@ -559,19 +559,19 @@ def build(options: Options, tmp_path: Path) -> None: env=test_env, ) - if not build_options.test_sources: - # 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) + testbed_app_path = testbed_path / "iOSTestbed" / "app" # Copy the test sources to the testbed app - copy_test_sources( - build_options.test_sources, - build_options.package_dir, - testbed_path / "iOSTestbed" / "app", - ) + if build_options.test_sources: + copy_test_sources( + build_options.test_sources, + 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...") # 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...") + # 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) if test_command_parts[0:2] != ["python", "-m"]: first_part = test_command_parts[0] diff --git a/cibuildwheel/platforms/linux.py b/cibuildwheel/platforms/linux.py index 5ffd5a2ef..88809cc52 100644 --- a/cibuildwheel/platforms/linux.py +++ b/cibuildwheel/platforms/linux.py @@ -398,9 +398,10 @@ def build_in_container( wheel=wheel_to_test, ) + test_cwd = testing_temp_dir / "test_cwd" + container.call(["mkdir", "-p", test_cwd]) + if build_options.test_sources: - test_cwd = testing_temp_dir / "test_cwd" - container.call(["mkdir", "-p", test_cwd]) copy_test_sources( build_options.test_sources, build_options.package_dir, @@ -408,8 +409,9 @@ def build_in_container( copy_into=container.copy_into, ) else: - # There are no test sources. Run the tests in the project directory. - test_cwd = PurePosixPath(container_project_path) + # Use the test_fail.py file to raise a nice error if the user + # 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) diff --git a/cibuildwheel/platforms/macos.py b/cibuildwheel/platforms/macos.py index d64917368..25523bd6f 100644 --- a/cibuildwheel/platforms/macos.py +++ b/cibuildwheel/platforms/macos.py @@ -706,8 +706,9 @@ def build(options: Options, tmp_path: Path) -> None: wheel=repaired_wheel, ) + test_cwd = identifier_tmp_dir / "test_cwd" + if build_options.test_sources: - test_cwd = identifier_tmp_dir / "test_cwd" # only create test_cwd if it doesn't already exist - it # may have been created during a previous `testing_arch` if not test_cwd.exists(): @@ -718,8 +719,12 @@ def build(options: Options, tmp_path: Path) -> None: test_cwd, ) else: - # There are no test sources. Run the tests in the project directory. - test_cwd = Path.cwd() + # Use the test_fail.py file to raise a nice error if the user + # 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) diff --git a/cibuildwheel/platforms/pyodide.py b/cibuildwheel/platforms/pyodide.py index dc6b5c6a4..8dcbf20a0 100644 --- a/cibuildwheel/platforms/pyodide.py +++ b/cibuildwheel/platforms/pyodide.py @@ -522,17 +522,19 @@ def build(options: Options, tmp_path: Path) -> None: package=build_options.package_dir.resolve(), ) + test_cwd = identifier_tmp_dir / "test_cwd" + test_cwd.mkdir(exist_ok=True) + if build_options.test_sources: - test_cwd = identifier_tmp_dir / "test_cwd" - test_cwd.mkdir(exist_ok=True) copy_test_sources( build_options.test_sources, build_options.package_dir, test_cwd, ) else: - # There are no test sources. Run the tests in the project directory. - test_cwd = Path.cwd() + # Use the test_fail.py file to raise a nice error if the user + # 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) diff --git a/cibuildwheel/platforms/windows.py b/cibuildwheel/platforms/windows.py index 52e081f76..53efde048 100644 --- a/cibuildwheel/platforms/windows.py +++ b/cibuildwheel/platforms/windows.py @@ -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 # (this ensures that Python runs the tests against the installed wheel # and not the repo code) - test_command_prepared = prepare_command( - build_options.test_command, - project=Path.cwd(), - package=options.globals.package_dir.resolve(), - wheel=repaired_wheel, - ) + test_cwd = identifier_tmp_dir / "test_cwd" + test_cwd.mkdir() + if build_options.test_sources: - test_cwd = identifier_tmp_dir / "test_cwd" - test_cwd.mkdir() copy_test_sources( build_options.test_sources, build_options.package_dir, test_cwd, ) else: - # There are no test sources. Run the tests in the project directory. - test_cwd = Path.cwd() + # Use the test_fail.py file to raise a nice error if the user + # 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) # we're all done here; move it to output (remove if already exists) diff --git a/cibuildwheel/resources/testing_temp_dir_file.py b/cibuildwheel/resources/testing_temp_dir_file.py new file mode 100644 index 000000000..094f2f6fb --- /dev/null +++ b/cibuildwheel/resources/testing_temp_dir_file.py @@ -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) diff --git a/cibuildwheel/util/resources.py b/cibuildwheel/util/resources.py index a3cef7815..0cb09a26d 100644 --- a/cibuildwheel/util/resources.py +++ b/cibuildwheel/util/resources.py @@ -17,6 +17,7 @@ VIRTUALENV: Final[Path] = PATH / "virtualenv.toml" CIBUILDWHEEL_SCHEMA: Final[Path] = PATH / "cibuildwheel.schema.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 diff --git a/docs/configuration.md b/docs/configuration.md index 0a0ce985f..df806ddbc 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -17,7 +17,7 @@ cibuildwheel to run tests, add the following YAML to your CI config file: ```yaml env: CIBW_TEST_REQUIRES: pytest - CIBW_TEST_COMMAND: "pytest ./tests" + CIBW_TEST_COMMAND: "pytest {project}/tests" ``` !!! tab "Azure Pipelines" @@ -27,7 +27,7 @@ cibuildwheel to run tests, add the following YAML to your CI config file: ```yaml variables: CIBW_TEST_REQUIRES: pytest - CIBW_TEST_COMMAND: "pytest ./tests" + CIBW_TEST_COMMAND: "pytest {project}/tests" ``` !!! tab "Travis CI" @@ -38,18 +38,7 @@ cibuildwheel to run tests, add the following YAML to your CI config file: env: global: - CIBW_TEST_REQUIRES=pytest - - CIBW_TEST_COMMAND="pytest ./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" + - CIBW_TEST_COMMAND="pytest {project}/tests" ``` !!! tab "CircleCI" @@ -61,7 +50,7 @@ cibuildwheel to run tests, add the following YAML to your CI config file: job_name: environment: CIBW_TEST_REQUIRES: pytest - CIBW_TEST_COMMAND: "pytest ./tests" + CIBW_TEST_COMMAND: "pytest {project}/tests" ``` !!! tab "Gitlab CI" @@ -72,7 +61,7 @@ cibuildwheel to run tests, add the following YAML to your CI config file: linux: variables: CIBW_TEST_REQUIRES: pytest - CIBW_TEST_COMMAND: "pytest ./tests" + CIBW_TEST_COMMAND: "pytest {project}/tests" ``` !!! tab "Cirrus CI" @@ -82,7 +71,7 @@ cibuildwheel to run tests, add the following YAML to your CI config file: ```yaml env: CIBW_TEST_REQUIRES: pytest - CIBW_TEST_COMMAND: "pytest ./tests" + CIBW_TEST_COMMAND: "pytest {project}/tests" ``` ## Configuration file {: #configuration-file} diff --git a/docs/options.md b/docs/options.md index 89e782bf5..c70af3dd4 100644 --- a/docs/options.md +++ b/docs/options.md @@ -28,7 +28,7 @@ This option can also be set using the [command-line option](#command-line) `--pl ```bash export CIBW_BUILD='cp37-*' - export CIBW_TEST_COMMAND='pytest ./tests' + export CIBW_TEST_COMMAND='pytest {project}/tests' 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 set, your wheel will not be installed after building. -By default, tests are executed from your project directory. When specifying -`test-command`, you can optionally use the placeholders `{package}` and -`{project}` to pass in the location of your test code: +To ensure the wheel is imported by your tests (instead of your source copy), +**Tests are executed from a temporary directory**, outside of your source +tree. To access your test code, you have a couple of options: -- `{package}` is the path to the package being built - the `package_dir` - argument supplied to cibuildwheel on the command line. -- `{project}` is an absolute path to the project root - the working directory - where cibuildwheel was called. +- You can use the [`test-sources`](#test-sources) setting to copy specific + files from your source tree into the temporary directory. When using + test-sources, use relative paths in your test command, as if they were + relative to the project root. -Using `{package}` or `{project}` used to be required, but since cibuildwheel -3.0, tests are run from the project root by default. This means that you can -use relative paths in your test command, and they will be relative to the -project root. +- You can use the `{package}` or `{project}` placeholders in your + `test-command` to refer to the package being built or the project root, + respectively. -Alternatively, you can use the [`test-sources`](#test-sources) setting to -create a temporary folder populated with a specific subset of project files to -run your test suite. + - `{package}` is the path to the package being built - the `package_dir` + argument supplied to cibuildwheel on the command line. + - `{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`. @@ -1318,18 +1318,18 @@ Platform-specific environment variables are also available:
```toml [tool.cibuildwheel] # 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 test-command = "echo Wheel installed" # Multiline example test-command = [ - "pytest ./tests", - "python ./test.py", + "pytest {project}/tests", + "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] test-sources = ["tests"] test-command = "python -m pytest ./tests" @@ -1341,17 +1341,17 @@ Platform-specific environment variables are also available:
```yaml # 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 CIBW_TEST_COMMAND: "echo Wheel installed" # Multi-line example - join with && on all platforms CIBW_TEST_COMMAND: > - pytest ./tests && - python ./test.py + pytest {project}/tests && + 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_COMMAND_IOS: python -m pytest ./tests ``` diff --git a/test/test_abi_variants.py b/test/test_abi_variants.py index f64f42485..2a849f3a2 100644 --- a/test/test_abi_variants.py +++ b/test/test_abi_variants.py @@ -187,7 +187,7 @@ def test_abi_none(tmp_path, capfd): project_dir, add_env={ "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 "CIBW_BUILD": "cp38-* cp{}{}-* cp313t-* pp310-*".format(*utils.SINGLE_PYTHON_VERSION), "CIBW_ENABLE": "all", diff --git a/test/test_before_test.py b/test/test_before_test.py index c6ed5a7bb..3c722d089 100644 --- a/test/test_before_test.py +++ b/test/test_before_test.py @@ -62,10 +62,10 @@ def test(tmp_path, build_frontend_env): "CIBW_TEST_REQUIRES": "pytest", # the 'false ||' bit is to ensure this command runs in a shell on # 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 # 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, }, ) diff --git a/test/test_emulation.py b/test/test_emulation.py index 9749d9da0..4a749cfa3 100644 --- a/test/test_emulation.py +++ b/test/test_emulation.py @@ -32,7 +32,7 @@ def test(tmp_path, request): project_dir, add_env={ "CIBW_TEST_REQUIRES": "pytest", - "CIBW_TEST_COMMAND": "pytest ./test", + "CIBW_TEST_COMMAND": "pytest {project}/test", "CIBW_ARCHS": archs, # TODO remove me once proper support is added "CIBW_MANYLINUX_RISCV64_IMAGE": "ghcr.io/mayeut/manylinux_2_35:2025.05.11-1", diff --git a/test/test_ios.py b/test/test_ios.py index 39d54ae91..9ee588b26 100644 --- a/test/test_ios.py +++ b/test/test_ios.py @@ -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 +@pytest.mark.serial 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": pytest.skip("this test can only run on macOS") if utils.get_xcode_version() < (13, 0): @@ -109,13 +110,47 @@ def test_no_test_sources(tmp_path, capfd): add_env={ "CIBW_PLATFORM": "ios", "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. + captured = capfd.readouterr() + 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 "Testing on iOS requires a definition of test-sources." in captured.err + assert "iOS tests cannot use placeholders" in captured.out + captured.err def test_missing_xbuild_tool(tmp_path, capfd): diff --git a/test/test_macos_archs.py b/test/test_macos_archs.py index f38cff567..f799e55b0 100644 --- a/test/test_macos_archs.py +++ b/test/test_macos_archs.py @@ -42,11 +42,9 @@ def test_cross_compiled_build(tmp_path): @pytest.mark.parametrize( "test_config", [ - # Run the test suite in the project folder { "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_SOURCES": "tests", diff --git a/test/test_pyodide.py b/test/test_pyodide.py index e1dbbd56e..39bc2be32 100644 --- a/test/test_pyodide.py +++ b/test/test_pyodide.py @@ -129,7 +129,7 @@ def test_filter(): add_args=["--platform", "pyodide"], add_env={ "CIBW_TEST_REQUIRES": "pytest", - "CIBW_TEST_COMMAND": "python -m pytest", + "CIBW_TEST_COMMAND": "python -m pytest {project}", }, ) # check that the expected wheels are produced diff --git a/test/test_testing.py b/test/test_testing.py index 88054c545..f12e7b5d5 100644 --- a/test/test_testing.py +++ b/test/test_testing.py @@ -86,10 +86,10 @@ def test(tmp_path): "CIBW_TEST_REQUIRES": "pytest", # the 'false ||' bit is to ensure this command runs in a shell on # 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 # 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", # the 'false ||' bit is to ensure this command runs in a shell on # 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 # 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, ) @@ -143,10 +143,10 @@ def test_dependency_groups(tmp_path): "CIBW_TEST_GROUPS": "dev", # the 'false ||' bit is to ensure this command runs in a shell on # 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 # 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, ) @@ -178,7 +178,7 @@ def test_failing_test(tmp_path): output_dir=output_dir, add_env={ "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 # always runs in x86_64, so the arm64 tests are not run. See # #1169 for reasons why. That means the build succeeds, which @@ -191,28 +191,40 @@ def test_failing_test(tmp_path): @pytest.mark.parametrize("test_runner", ["pytest", "unittest"]) -def test_bare_pytest_invocation(tmp_path: Path, test_runner: str) -> None: - """Check that if a user runs a bare test suite, it runs in the project folder""" +def test_bare_pytest_invocation( + 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_with_a_test.generate(project_dir) + output_dir = tmp_path / "output" - actual_wheels = utils.cibuildwheel_run( - project_dir, - add_env={ - "CIBW_TEST_REQUIRES": "pytest" if test_runner == "pytest" else "", - "CIBW_TEST_COMMAND": ( - # pytest fails on GraalPy 24.2.0 on Windows so we skip it there - # until https://github.com/oracle/graalpython/issues/490 fixed - "graalpy.exe -c 1 || python -m pytest" - if test_runner == "pytest" - else "python -m unittest discover test spam_test.py" - ), - }, - ) + with pytest.raises(subprocess.CalledProcessError): + utils.cibuildwheel_run( + project_dir, + output_dir=output_dir, + add_env={ + "CIBW_TEST_REQUIRES": "pytest" if test_runner == "pytest" else "", + "CIBW_TEST_COMMAND": ( + "python -m pytest" if test_runner == "pytest" else "python -m unittest" + ), + # Skip CPython 3.8 on macOS arm64, see comment above in + # 'test_failing_test' + "CIBW_SKIP": "cp38-macosx_arm64", + }, + ) - # check that we got the right wheels - expected_wheels = utils.expected_wheels("spam", "0.1.0") - assert set(actual_wheels) == set(expected_wheels) + 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 + ) def test_test_sources(tmp_path):