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:
parent
a536f49d91
commit
15e0e951e8
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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]"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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`:
|
||||||
|
|
|
@ -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"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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*"])
|
||||||
|
|
||||||
|
|
|
@ -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. "
|
||||||
|
|
|
@ -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)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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*",
|
||||||
|
|
2
tox.ini
2
tox.ini
|
@ -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 =
|
||||||
|
|
Loading…
Reference in New Issue