Skip to content

Commit

Permalink
Parse args from file (pytest-dev#12085)
Browse files Browse the repository at this point in the history
Co-authored-by: Ran Benita <ran@unusedvar.com>
Co-authored-by: Bruno Oliveira <bruno@soliv.dev>
  • Loading branch information
3 people committed Mar 9, 2024
1 parent 2ccc73b commit 9033d4d
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 1 deletion.
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

0 comments on commit 9033d4d

Please sign in to comment.