Skip to content

Commit

Permalink
Make use of -I in all Python invocations
Browse files Browse the repository at this point in the history
This helps prevent testing the non-installed source.
Additionally, the patch updates the docs to demonstrate a more
predictable runpy-style invocation method.
  • Loading branch information
webknjaz committed Dec 7, 2023
1 parent a536f49 commit d3322f5
Show file tree
Hide file tree
Showing 15 changed files with 35 additions and 36 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ jobs:

- name: Install tox
run: |
python -m pip install --upgrade pip
python -Im pip install --upgrade pip
pip install --upgrade tox
- name: Publish GitHub release notes
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/prepare-release-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -Im pip install --upgrade pip
pip install --upgrade setuptools tox
- name: Prepare release PR (minor/patch release)
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ jobs:

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -Im pip install --upgrade pip
pip install tox coverage
- name: Test without coverage
Expand All @@ -201,7 +201,7 @@ jobs:

- name: Generate coverage report
if: "matrix.use_coverage"
run: python -m coverage xml
run: python -Im coverage xml

- name: Upload coverage to Codecov
if: "matrix.use_coverage"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/update-plugin-list.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -Im pip install --upgrade pip
pip install packaging requests tabulate[widechars] tqdm requests-cache platformdirs
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
an editable install with the ``testing`` extra::

$ python3 -m venv .venv
$ python3 -Im venv .venv
$ source .venv/bin/activate # Linux
$ .venv/Scripts/activate.bat # Windows
$ pip install -e ".[testing]"
Expand Down
2 changes: 1 addition & 1 deletion doc/en/explanation/goodpractices.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
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``.

Tests as part of application code
Expand Down
12 changes: 6 additions & 6 deletions doc/en/explanation/pythonpath.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,13 @@ imported in the global import namespace.

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
equivalent behaviour, except that the latter will add the current directory to ``sys.path``, which
is standard ``python`` behavior.
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``
in case when ``-I`` is omitted, which is standard ``python`` behavior.

See also :ref:`invoke-python`.
11 changes: 7 additions & 4 deletions doc/en/how-to/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,20 @@ Other ways of calling pytest

.. _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:

.. code-block:: text
python -m pytest [...]
python -Im pytest [...]
This is almost equivalent to invoking the command line script ``pytest [...]``
directly, except that calling via ``python`` will also add the current directory to ``sys.path``.
This is equivalent to invoking the command line script ``pytest [...]``
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`:
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/pytester.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def pytest_addoption(parser: Parser) -> None:
choices=("inprocess", "subprocess"),
help=(
"Run pytest sub runs in tests using an 'inprocess' "
"or 'subprocess' (python -m main) method"
"or 'subprocess' (python -Im main) method"
),
)

Expand Down
6 changes: 3 additions & 3 deletions testing/acceptance_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,17 +589,17 @@ def test_hello():

def test_python_minus_m_invocation_ok(self, pytester: Pytester) -> None:
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

def test_python_minus_m_invocation_fail(self, pytester: Pytester) -> None:
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

def test_python_pytest_package(self, pytester: Pytester) -> None:
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
res.stdout.fnmatch_lines(["*1 passed*"])

Expand Down
6 changes: 3 additions & 3 deletions testing/test_assertion.py
Original file line number Diff line number Diff line change
Expand Up @@ -1702,18 +1702,18 @@ def test_multitask_job():
"cmdline_args, warning_output",
[
(
["-OO", "-m", "pytest", "-h"],
["-OO", "-Im", "pytest", "-h"],
["warning :*PytestConfigWarning:*assert statements are not executed*"],
),
(
["-OO", "-m", "pytest"],
["-OO", "-Im", "pytest"],
[
"=*= warnings summary =*=",
"*PytestConfigWarning:*assert statements are not executed*",
],
),
(
["-OO", "-m", "pytest", "--assert=plain"],
["-OO", "-Im", "pytest", "--assert=plain"],
[
"=*= warnings summary =*=",
"*PytestConfigWarning: ASSERTIONS ARE NOT EXECUTED and FAILING TESTS WILL PASS. "
Expand Down
2 changes: 1 addition & 1 deletion testing/test_parseopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None:
# http://stackoverflow.com/q/12589419/1307905
# so we use bash
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)
)
)
Expand Down
2 changes: 1 addition & 1 deletion testing/test_setuponly.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,6 @@ def test_data(data):
"""
)
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
14 changes: 5 additions & 9 deletions testing/test_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
# We choose to explicitly not skip this in case tracemalloc is not
# available, using `importorskip("tracemalloc")` for example,
Expand All @@ -804,10 +804,6 @@ def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) -
except ImportError:
has_tracemalloc = False

# Explicitly disable PYTHONTRACEMALLOC in case pytest's test suite is running
# with it enabled.
monkeypatch.delenv("PYTHONTRACEMALLOC", raising=False)

pytester.makepyfile(
"""
def open_file(p):
Expand All @@ -820,7 +816,9 @@ def test_resource_warning(tmp_path):
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 = (
[
"*ResourceWarning* unclosed file*",
Expand All @@ -832,9 +830,7 @@ def test_resource_warning(tmp_path):
)
result.stdout.fnmatch_lines([*expected_extra, "*1 passed*"])

monkeypatch.setenv("PYTHONTRACEMALLOC", "20")

result = pytester.run(sys.executable, "-Xdev", "-m", "pytest")
result = pytester.run(sys.executable, "-Xdev", "-Xtracemalloc=20", "-Im", "pytest")
expected_extra = (
[
"*ResourceWarning* unclosed file*",
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ setenv =
pip_pre=true
# use latest pip to get new dependency resolver (#7783)
download=true
install_command=python -m pip install {opts} {packages}
install_command=python -Im pip install {opts} {packages}
changedir = testing/plugins_integration
deps = -rtesting/plugins_integration/requirements.txt
setenv =
Expand Down

0 comments on commit d3322f5

Please sign in to comment.