Make use of `-I` in all Python invocations

This helps prevent testing the non-installed source.
Additionally, the patch updates the docs to demonstrate a more
predictable runpy-style invocation method.
This commit is contained in:
Sviatoslav Sydorenko 2023-12-07 02:07:09 +01:00
parent a536f49d91
commit 15e0e951e8
No known key found for this signature in database
GPG Key ID: 9345E8FEA89CA455
15 changed files with 35 additions and 36 deletions

View File

@ -79,7 +79,7 @@ jobs:
- name: Install tox - name: Install tox
run: | run: |
python -m pip install --upgrade pip python -Im pip install --upgrade pip
pip install --upgrade tox pip install --upgrade tox
- name: Publish GitHub release notes - name: Publish GitHub release notes

View File

@ -38,7 +38,7 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -Im pip install --upgrade pip
pip install --upgrade setuptools tox pip install --upgrade setuptools tox
- name: Prepare release PR (minor/patch release) - name: Prepare release PR (minor/patch release)

View File

@ -186,7 +186,7 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -Im pip install --upgrade pip
pip install tox coverage pip install tox coverage
- name: Test without coverage - name: Test without coverage
@ -201,7 +201,7 @@ jobs:
- name: Generate coverage report - name: Generate coverage report
if: "matrix.use_coverage" if: "matrix.use_coverage"
run: python -m coverage xml run: python -Im coverage xml
- name: Upload coverage to Codecov - name: Upload coverage to Codecov
if: "matrix.use_coverage" if: "matrix.use_coverage"

View File

@ -38,7 +38,7 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -Im pip install --upgrade pip
pip install packaging requests tabulate[widechars] tqdm requests-cache platformdirs pip install packaging requests tabulate[widechars] tqdm requests-cache platformdirs

View File

@ -299,7 +299,7 @@ Here is a simple overview, with pytest-specific bits:
#. If instead of using ``tox`` you prefer to run the tests directly, then we suggest to create a virtual environment and use #. If instead of using ``tox`` you prefer to run the tests directly, then we suggest to create a virtual environment and use
an editable install with the ``testing`` extra:: an editable install with the ``testing`` extra::
$ python3 -m venv .venv $ python3 -Im venv .venv
$ source .venv/bin/activate # Linux $ source .venv/bin/activate # Linux
$ .venv/Scripts/activate.bat # Windows $ .venv/Scripts/activate.bat # Windows
$ pip install -e ".[testing]" $ pip install -e ".[testing]"

View File

@ -137,7 +137,7 @@ which are better explained in this excellent `blog post`_ by Ionel Cristian Măr
directory) you can rely on the fact that Python by default puts the current directory in ``sys.path`` to directory) you can rely on the fact that Python by default puts the current directory in ``sys.path`` to
import your package and run ``python -m pytest`` to execute the tests against the local copy directly. import your package and run ``python -m pytest`` to execute the tests against the local copy directly.
See :ref:`pytest vs python -m pytest` for more information about the difference between calling ``pytest`` and See :ref:`pytest vs python -Im pytest` for more information about the difference between calling ``pytest`` and
``python -m pytest``. ``python -m pytest``.
Tests as part of application code Tests as part of application code

View File

@ -130,13 +130,13 @@ imported in the global import namespace.
This is also discussed in details in :ref:`test discovery`. This is also discussed in details in :ref:`test discovery`.
.. _`pytest vs python -m pytest`: .. _`pytest vs python -Im pytest`:
Invoking ``pytest`` versus ``python -m pytest`` Invoking ``pytest`` versus ``python -Im pytest``
----------------------------------------------- ------------------------------------------------
Running pytest with ``pytest [...]`` instead of ``python -m pytest [...]`` yields nearly Running pytest with ``pytest [...]`` instead of ``python -Im pytest [...]`` yields nearly
equivalent behaviour, except that the latter will add the current directory to ``sys.path``, which equivalent behaviour, except that the latter will add the current directory to ``sys.path``
is standard ``python`` behavior. in case when ``-I`` is omitted, which is standard ``python`` behavior.
See also :ref:`invoke-python`. See also :ref:`invoke-python`.

View File

@ -158,17 +158,20 @@ Other ways of calling pytest
.. _invoke-python: .. _invoke-python:
Calling pytest through ``python -m pytest`` Calling pytest through ``python -Im pytest``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can invoke testing through the Python interpreter from the command line: You can invoke testing through the Python interpreter from the command line:
.. code-block:: text .. code-block:: text
python -m pytest [...] python -Im pytest [...]
This is almost equivalent to invoking the command line script ``pytest [...]`` This is equivalent to invoking the command line script ``pytest [...]``
directly, except that calling via ``python`` will also add the current directory to ``sys.path``. directly, for as long as ``-I`` is used. Dropping it will also add the current
directory to ``sys.path``, which may have a side effect of not `testing your
project as installed
<https://blog.ganssle.io/articles/2019/08/test-as-installed.html>`__.
.. _`pytest.main-usage`: .. _`pytest.main-usage`:

View File

@ -97,7 +97,7 @@ def pytest_addoption(parser: Parser) -> None:
choices=("inprocess", "subprocess"), choices=("inprocess", "subprocess"),
help=( help=(
"Run pytest sub runs in tests using an 'inprocess' " "Run pytest sub runs in tests using an 'inprocess' "
"or 'subprocess' (python -m main) method" "or 'subprocess' (python -Im main) method"
), ),
) )

View File

@ -589,17 +589,17 @@ class TestInvocationVariants:
def test_python_minus_m_invocation_ok(self, pytester: Pytester) -> None: def test_python_minus_m_invocation_ok(self, pytester: Pytester) -> None:
p1 = pytester.makepyfile("def test_hello(): pass") p1 = pytester.makepyfile("def test_hello(): pass")
res = pytester.run(sys.executable, "-m", "pytest", str(p1)) res = pytester.run(sys.executable, "-Im", "pytest", str(p1))
assert res.ret == 0 assert res.ret == 0
def test_python_minus_m_invocation_fail(self, pytester: Pytester) -> None: def test_python_minus_m_invocation_fail(self, pytester: Pytester) -> None:
p1 = pytester.makepyfile("def test_fail(): 0/0") p1 = pytester.makepyfile("def test_fail(): 0/0")
res = pytester.run(sys.executable, "-m", "pytest", str(p1)) res = pytester.run(sys.executable, "-Im", "pytest", str(p1))
assert res.ret == 1 assert res.ret == 1
def test_python_pytest_package(self, pytester: Pytester) -> None: def test_python_pytest_package(self, pytester: Pytester) -> None:
p1 = pytester.makepyfile("def test_pass(): pass") p1 = pytester.makepyfile("def test_pass(): pass")
res = pytester.run(sys.executable, "-m", "pytest", str(p1)) res = pytester.run(sys.executable, "-Im", "pytest", str(p1))
assert res.ret == 0 assert res.ret == 0
res.stdout.fnmatch_lines(["*1 passed*"]) res.stdout.fnmatch_lines(["*1 passed*"])

View File

@ -1702,18 +1702,18 @@ def test_exception_handling_no_traceback(pytester: Pytester) -> None:
"cmdline_args, warning_output", "cmdline_args, warning_output",
[ [
( (
["-OO", "-m", "pytest", "-h"], ["-OO", "-Im", "pytest", "-h"],
["warning :*PytestConfigWarning:*assert statements are not executed*"], ["warning :*PytestConfigWarning:*assert statements are not executed*"],
), ),
( (
["-OO", "-m", "pytest"], ["-OO", "-Im", "pytest"],
[ [
"=*= warnings summary =*=", "=*= warnings summary =*=",
"*PytestConfigWarning:*assert statements are not executed*", "*PytestConfigWarning:*assert statements are not executed*",
], ],
), ),
( (
["-OO", "-m", "pytest", "--assert=plain"], ["-OO", "-Im", "pytest", "--assert=plain"],
[ [
"=*= warnings summary =*=", "=*= warnings summary =*=",
"*PytestConfigWarning: ASSERTIONS ARE NOT EXECUTED and FAILING TESTS WILL PASS. " "*PytestConfigWarning: ASSERTIONS ARE NOT EXECUTED and FAILING TESTS WILL PASS. "

View File

@ -317,7 +317,7 @@ def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None:
# http://stackoverflow.com/q/12589419/1307905 # http://stackoverflow.com/q/12589419/1307905
# so we use bash # so we use bash
fp.write( fp.write(
'COMP_WORDBREAKS="$COMP_WORDBREAKS" {} -m pytest 8>&1 9>&2'.format( 'COMP_WORDBREAKS="$COMP_WORDBREAKS" {} -Im pytest 8>&1 9>&2'.format(
shlex.quote(sys.executable) shlex.quote(sys.executable)
) )
) )

View File

@ -313,6 +313,6 @@ def test_show_fixture_action_with_bytes(pytester: Pytester) -> None:
""" """
) )
result = pytester.run( result = pytester.run(
sys.executable, "-bb", "-m", "pytest", "--setup-show", str(test_file) sys.executable, "-bb", "-Im", "pytest", "--setup-show", str(test_file)
) )
assert result.ret == 0 assert result.ret == 0

View File

@ -792,7 +792,7 @@ def test_warning_on_testpaths_not_found(pytester: Pytester) -> None:
) )
def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) -> None: def test_resource_warning(pytester: Pytester) -> None:
# Some platforms (notably PyPy) don't have tracemalloc. # Some platforms (notably PyPy) don't have tracemalloc.
# We choose to explicitly not skip this in case tracemalloc is not # We choose to explicitly not skip this in case tracemalloc is not
# available, using `importorskip("tracemalloc")` for example, # available, using `importorskip("tracemalloc")` for example,
@ -804,10 +804,6 @@ def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) -
except ImportError: except ImportError:
has_tracemalloc = False has_tracemalloc = False
# Explicitly disable PYTHONTRACEMALLOC in case pytest's test suite is running
# with it enabled.
monkeypatch.delenv("PYTHONTRACEMALLOC", raising=False)
pytester.makepyfile( pytester.makepyfile(
""" """
def open_file(p): def open_file(p):
@ -820,7 +816,9 @@ def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) -
open_file(p) open_file(p)
""" """
) )
result = pytester.run(sys.executable, "-Xdev", "-m", "pytest") # Explicitly disable PYTHONTRACEMALLOC in case pytest's test suite is running
# with it enabled.
result = pytester.run(sys.executable, "-Xdev", "-Xtracemalloc=0", "-Im", "pytest")
expected_extra = ( expected_extra = (
[ [
"*ResourceWarning* unclosed file*", "*ResourceWarning* unclosed file*",
@ -832,9 +830,7 @@ def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) -
) )
result.stdout.fnmatch_lines([*expected_extra, "*1 passed*"]) result.stdout.fnmatch_lines([*expected_extra, "*1 passed*"])
monkeypatch.setenv("PYTHONTRACEMALLOC", "20") result = pytester.run(sys.executable, "-Xdev", "-Xtracemalloc=20", "-Im", "pytest")
result = pytester.run(sys.executable, "-Xdev", "-m", "pytest")
expected_extra = ( expected_extra = (
[ [
"*ResourceWarning* unclosed file*", "*ResourceWarning* unclosed file*",

View File

@ -129,7 +129,7 @@ setenv =
pip_pre=true pip_pre=true
# use latest pip to get new dependency resolver (#7783) # use latest pip to get new dependency resolver (#7783)
download=true download=true
install_command=python -m pip install {opts} {packages} install_command=python -Im pip install {opts} {packages}
changedir = testing/plugins_integration changedir = testing/plugins_integration
deps = -rtesting/plugins_integration/requirements.txt deps = -rtesting/plugins_integration/requirements.txt
setenv = setenv =