Merge branch 'main' into dev1
This commit is contained in:
commit
36d82f0254
|
@ -208,6 +208,7 @@ option names are:
|
|||
If you need to record the whole test suite logging calls to a file, you can pass
|
||||
``--log-file=/path/to/log/file``. This log file is opened in write mode by default which
|
||||
means that it will be overwritten at each run tests session.
|
||||
You can specify the level of verbosity of the log file by passing ```--log-file-verbose=1``
|
||||
If you'd like the file opened in append mode instead, then you can pass ``--log-file-mode=a``.
|
||||
Note that relative paths for the log-file location, whether passed on the CLI or declared in a
|
||||
config file, are always resolved relative to the current working directory.
|
||||
|
|
|
@ -2107,6 +2107,7 @@ All the command-line flags can be obtained by running ``pytest --help``::
|
|||
--log-cli-date-format=LOG_CLI_DATE_FORMAT
|
||||
Log date format used by the logging module
|
||||
--log-file=LOG_FILE Path to a file when logging will be written to
|
||||
--log-file-verbose={0,1} Log file verbose
|
||||
--log-file-mode={w,a}
|
||||
Log file open mode
|
||||
--log-file-level=LOG_FILE_LEVEL
|
||||
|
@ -2207,6 +2208,8 @@ All the command-line flags can be obtained by running ``pytest --help``::
|
|||
log_cli_date_format (string):
|
||||
Default value for --log-cli-date-format
|
||||
log_file (string): Default value for --log-file
|
||||
log_file_verbose (int):
|
||||
Default value for --log-file-verbose
|
||||
log_file_mode (string):
|
||||
Default value for --log-file-mode
|
||||
log_file_level (string):
|
||||
|
|
|
@ -1576,6 +1576,7 @@ class Config:
|
|||
``paths``, ``pathlist``, ``args`` and ``linelist`` : empty list ``[]``
|
||||
``bool`` : ``False``
|
||||
``string`` : empty string ``""``
|
||||
``int`` : ``0``
|
||||
|
||||
If neither the ``default`` nor the ``type`` parameter is passed
|
||||
while registering the configuration through
|
||||
|
@ -1643,6 +1644,8 @@ class Config:
|
|||
return value
|
||||
elif type == "bool":
|
||||
return _strtobool(str(value).strip())
|
||||
elif type == "int":
|
||||
return int(str(value).strip())
|
||||
elif type == "string":
|
||||
return value
|
||||
elif type is None:
|
||||
|
|
|
@ -180,7 +180,7 @@ class Parser:
|
|||
name: str,
|
||||
help: str,
|
||||
type: Optional[
|
||||
Literal["string", "paths", "pathlist", "args", "linelist", "bool"]
|
||||
Literal["string", "paths", "pathlist", "args", "linelist", "bool", "int"]
|
||||
] = None,
|
||||
default: Any = NOT_SET,
|
||||
) -> None:
|
||||
|
@ -190,7 +190,7 @@ class Parser:
|
|||
Name of the ini-variable.
|
||||
:param type:
|
||||
Type of the variable. Can be:
|
||||
|
||||
* ``int``: an integer
|
||||
* ``string``: a string
|
||||
* ``bool``: a boolean
|
||||
* ``args``: a list of strings, separated as in a shell
|
||||
|
@ -215,7 +215,16 @@ class Parser:
|
|||
The value of ini-variables can be retrieved via a call to
|
||||
:py:func:`config.getini(name) <pytest.Config.getini>`.
|
||||
"""
|
||||
assert type in (None, "string", "paths", "pathlist", "args", "linelist", "bool")
|
||||
assert type in (
|
||||
None,
|
||||
"string",
|
||||
"paths",
|
||||
"pathlist",
|
||||
"args",
|
||||
"linelist",
|
||||
"bool",
|
||||
"int",
|
||||
)
|
||||
if default is NOT_SET:
|
||||
default = get_ini_default_for_type(type)
|
||||
|
||||
|
@ -224,7 +233,9 @@ class Parser:
|
|||
|
||||
|
||||
def get_ini_default_for_type(
|
||||
type: Optional[Literal["string", "paths", "pathlist", "args", "linelist", "bool"]],
|
||||
type: Optional[
|
||||
Literal["string", "paths", "pathlist", "args", "linelist", "bool", "int"]
|
||||
],
|
||||
) -> Any:
|
||||
"""
|
||||
Used by addini to get the default value for a given ini-option type, when
|
||||
|
@ -236,6 +247,8 @@ def get_ini_default_for_type(
|
|||
return []
|
||||
elif type == "bool":
|
||||
return False
|
||||
elif type == "int":
|
||||
return 0
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
|
|
@ -299,6 +299,13 @@ def pytest_addoption(parser: Parser) -> None:
|
|||
default=None,
|
||||
help="Path to a file when logging will be written to",
|
||||
)
|
||||
add_option_ini(
|
||||
"--log-file-verbose",
|
||||
dest="log_file_verbose",
|
||||
default=0,
|
||||
type="int",
|
||||
help="Log file verbose",
|
||||
)
|
||||
add_option_ini(
|
||||
"--log-file-mode",
|
||||
dest="log_file_mode",
|
||||
|
@ -677,6 +684,8 @@ class LoggingPlugin:
|
|||
if not os.path.isdir(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
self.log_file_verbose = get_option_ini(config, "log_file_verbose")
|
||||
|
||||
self.log_file_mode = get_option_ini(config, "log_file_mode") or "w"
|
||||
self.log_file_handler = _FileHandler(
|
||||
log_file, mode=self.log_file_mode, encoding="UTF-8"
|
||||
|
@ -837,6 +846,22 @@ class LoggingPlugin:
|
|||
|
||||
@hookimpl(wrapper=True)
|
||||
def pytest_runtest_setup(self, item: nodes.Item) -> Generator[None, None, None]:
|
||||
if self.log_file_verbose and int(self.log_file_verbose) >= 1:
|
||||
old_log_file_formatter = self.log_file_handler.formatter
|
||||
self.log_file_handler.setFormatter(logging.Formatter())
|
||||
self.log_file_handler.emit(
|
||||
logging.LogRecord(
|
||||
"N/A",
|
||||
logging.INFO,
|
||||
"N/A",
|
||||
0,
|
||||
f"Running at {item.nodeid}",
|
||||
None,
|
||||
None,
|
||||
)
|
||||
)
|
||||
self.log_file_handler.setFormatter(old_log_file_formatter)
|
||||
|
||||
self.log_cli_handler.set_when("setup")
|
||||
|
||||
empty: Dict[str, List[logging.LogRecord]] = {}
|
||||
|
|
|
@ -8,6 +8,6 @@ import pytest
|
|||
result_index = [(1, 2, 3), (-1, 1, 0), (0, 0, 0), (5, -3, 2), (1, 1, 2)]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("a, b,expected_result", result_index)
|
||||
@pytest.mark.parametrize("a, b, expected_result", result_index)
|
||||
def test_add(a: int, b: int, expected_result: int) -> None:
|
||||
assert add_function.add(a, b) == expected_result
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import os
|
||||
|
||||
from _pytest.pytester import Pytester
|
||||
|
||||
|
||||
def test_log_file_verbose(pytester: Pytester) -> None:
|
||||
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
import logging
|
||||
def test_verbose1():
|
||||
logging.info("test 1")
|
||||
|
||||
def test_verbose2():
|
||||
logging.warning("test 2")
|
||||
"""
|
||||
)
|
||||
|
||||
result = pytester.runpytest(
|
||||
"-s", f"--log-file={log_file}", "--log-file-verbose=1", "--log-file-level=INFO"
|
||||
)
|
||||
|
||||
rec = pytester.inline_run()
|
||||
rec.assertoutcome(passed=2)
|
||||
|
||||
# make sure that we get a '0' exit code for the testsuite
|
||||
assert result.ret == 0
|
||||
assert os.path.isfile(log_file)
|
||||
with open(log_file, encoding="utf-8") as rfh:
|
||||
contents = rfh.read()
|
||||
|
||||
for s in [
|
||||
"Running at test_log_file_verbose.py::test_verbose1",
|
||||
"test 1",
|
||||
"Running at test_log_file_verbose.py::test_verbose2",
|
||||
"test 2",
|
||||
]:
|
||||
assert s in contents
|
||||
|
||||
|
||||
def test_log_file_verbose0(pytester: Pytester) -> None:
|
||||
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
import logging
|
||||
def test_verbose1():
|
||||
logging.info("test 1")
|
||||
|
||||
def test_verbose2():
|
||||
logging.warning("test 2")
|
||||
"""
|
||||
)
|
||||
|
||||
result = pytester.runpytest(
|
||||
"-s", f"--log-file={log_file}", "--log-file-verbose=0", "--log-file-level=INFO"
|
||||
)
|
||||
|
||||
rec = pytester.inline_run()
|
||||
rec.assertoutcome(passed=2)
|
||||
|
||||
# make sure that we get a '0' exit code for the testsuite
|
||||
assert result.ret == 0
|
||||
assert os.path.isfile(log_file)
|
||||
with open(log_file, encoding="utf-8") as rfh:
|
||||
contents = rfh.read()
|
||||
|
||||
for s in ["test 1", "test 2"]:
|
||||
assert s in contents
|
||||
|
||||
for s in [
|
||||
"Running at test_log_file_verbose0.py::test_verbose1",
|
||||
"Running at test_log_file_verbose.py::test_verbose2",
|
||||
]:
|
||||
assert s not in contents
|
Loading…
Reference in New Issue