Skip to content

Parse args from file #12085

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ coverage.xml
.settings
.vscode
__pycache__/
.python-version

# generated by pip
pip-wheel-metadata/
Expand Down
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ Kyle Altendorf
Lawrence Mitchell
Lee Kamentsky
Lev Maximov
Levon Saldamli
Lewis Cowles
Llandy Riveron Del Risco
Loic Esteve
Expand Down
1 change: 1 addition & 0 deletions changelog/11871.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added support for reading command line arguments from a file using the prefix character ``@``, like e.g.: ``pytest @tests.txt``. The file must have one argument per line.
25 changes: 24 additions & 1 deletion doc/en/how-to/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ in the current directory and its subdirectories. More generally, pytest follows
Specifying which tests to run
------------------------------

Pytest supports several ways to run and select tests from the command-line.
Pytest supports several ways to run and select tests from the command-line or from a file
(see below for :ref:`reading arguments from file <args-from-file>`).

**Run tests in a module**

Expand Down Expand Up @@ -91,6 +92,28 @@ For more information see :ref:`marks <mark>`.

This will import ``pkg.testing`` and use its filesystem location to find and run tests from.

.. _args-from-file:

**Read arguments from file**

.. versionadded:: 8.2

All of the above can be read from a file using the ``@`` prefix:

.. code-block:: bash

pytest @tests_to_run.txt

where ``tests_to_run.txt`` contains an entry per line, e.g.:

.. code-block:: text

tests/test_file.py
tests/test_mod.py::test_func[x1,y2]
tests/test_mod.py::TestClass
-m slow

This file can also be generated using ``pytest --collect-only -q`` and modified as needed.

Getting help on version, option names, environment variables
--------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions src/_pytest/config/argparsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ def __init__(
add_help=False,
formatter_class=DropShorterLongHelpFormatter,
allow_abbrev=False,
fromfile_prefix_chars="@",
)
# extra_info is a dict of (param -> value) to display if there's
# an usage error to provide more contextual information to the user.
Expand Down
27 changes: 27 additions & 0 deletions testing/acceptance_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import dataclasses
import importlib.metadata
import os
from pathlib import Path
import subprocess
import sys
import types
Expand Down Expand Up @@ -541,6 +542,32 @@ def test_foo(data):
res = pytester.runpytest(p)
res.assert_outcomes(passed=3)

# Warning ignore because of:
# https://github.com/python/cpython/issues/85308
# Can be removed once Python<3.12 support is dropped.
@pytest.mark.filterwarnings("ignore:'encoding' argument not specified")
def test_command_line_args_from_file(
self, pytester: Pytester, tmp_path: Path
) -> None:
pytester.makepyfile(
test_file="""
import pytest

class TestClass:
@pytest.mark.parametrize("a", ["x","y"])
def test_func(self, a):
pass
"""
)
tests = [
"test_file.py::TestClass::test_func[x]",
"test_file.py::TestClass::test_func[y]",
"-q",
]
args_file = pytester.maketxtfile(tests="\n".join(tests))
result = pytester.runpytest(f"@{args_file}")
result.assert_outcomes(failed=0, passed=2)


class TestInvocationVariants:
def test_earlyinit(self, pytester: Pytester) -> None:
Expand Down
11 changes: 11 additions & 0 deletions testing/test_parseopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,17 @@ def test_parse2(self, parser: parseopt.Parser) -> None:
args = parser.parse([Path(".")])
assert getattr(args, parseopt.FILE_OR_DIR)[0] == "."

# Warning ignore because of:
# https://github.com/python/cpython/issues/85308
# Can be removed once Python<3.12 support is dropped.
@pytest.mark.filterwarnings("ignore:'encoding' argument not specified")
def test_parse_from_file(self, parser: parseopt.Parser, tmp_path: Path) -> None:
tests = [".", "some.py::Test::test_method[param0]", "other/test_file.py"]
args_file = tmp_path / "tests.txt"
args_file.write_text("\n".join(tests), encoding="utf-8")
args = parser.parse([f"@{args_file.absolute()}"])
assert getattr(args, parseopt.FILE_OR_DIR) == tests

def test_parse_known_args(self, parser: parseopt.Parser) -> None:
parser.parse_known_args([Path(".")])
parser.addoption("--hello", action="store_true")
Expand Down