1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
# mypy: allow-untyped-defs
from __future__ import annotations
from pathlib import Path
import re
import warnings
from _pytest import nodes
from _pytest.compat import legacy_path
from _pytest.outcomes import OutcomeException
from _pytest.pytester import Pytester
from _pytest.warning_types import PytestWarning
import pytest
def test_node_from_parent_disallowed_arguments() -> None:
with pytest.raises(TypeError, match="session is"):
nodes.Node.from_parent(None, session=None) # type: ignore[arg-type]
with pytest.raises(TypeError, match="config is"):
nodes.Node.from_parent(None, config=None) # type: ignore[arg-type]
def test_node_direct_construction_deprecated() -> None:
with pytest.raises(
OutcomeException,
match=(
r"Direct construction of _pytest\.nodes\.Node has been deprecated, please "
r"use _pytest\.nodes\.Node\.from_parent.\nSee "
r"https://docs\.pytest\.org/en/stable/deprecations\.html#node-construction-changed-to-node-from-parent"
r" for more details\."
),
):
nodes.Node(None, session=None) # type: ignore[arg-type]
def test_subclassing_both_item_and_collector_deprecated(
request, tmp_path: Path
) -> None:
"""
Verifies we warn on diamond inheritance as well as correctly managing legacy
inheritance constructors with missing args as found in plugins.
"""
# We do not expect any warnings messages to issued during class definition.
with warnings.catch_warnings():
warnings.simplefilter("error")
class SoWrong(nodes.Item, nodes.File):
def __init__(self, fspath, parent):
"""Legacy ctor with legacy call # don't wana see"""
super().__init__(fspath, parent)
def collect(self):
raise NotImplementedError()
def runtest(self):
raise NotImplementedError()
with pytest.warns(PytestWarning) as rec:
SoWrong.from_parent(
request.session, fspath=legacy_path(tmp_path / "broken.txt")
)
messages = [str(x.message) for x in rec]
assert any(
re.search(".*SoWrong.* not using a cooperative constructor.*", x)
for x in messages
)
assert any(
re.search("(?m)SoWrong .* should not be a collector", x) for x in messages
)
@pytest.mark.parametrize(
"warn_type, msg", [(DeprecationWarning, "deprecated"), (PytestWarning, "pytest")]
)
def test_node_warn_is_no_longer_only_pytest_warnings(
pytester: Pytester, warn_type: type[Warning], msg: str
) -> None:
items = pytester.getitems(
"""
def test():
pass
"""
)
with pytest.warns(warn_type, match=msg):
items[0].warn(warn_type(msg))
def test_node_warning_enforces_warning_types(pytester: Pytester) -> None:
items = pytester.getitems(
"""
def test():
pass
"""
)
with pytest.raises(
ValueError, match="warning must be an instance of Warning or subclass"
):
items[0].warn(Exception("ok")) # type: ignore[arg-type]
def test__check_initialpaths_for_relpath() -> None:
"""Ensure that it handles dirs, and does not always use dirname."""
cwd = Path.cwd()
initial_paths = frozenset({cwd})
assert nodes._check_initialpaths_for_relpath(initial_paths, cwd) == ""
sub = cwd / "file"
assert nodes._check_initialpaths_for_relpath(initial_paths, sub) == "file"
outside = Path("/outside-this-does-not-exist")
assert nodes._check_initialpaths_for_relpath(initial_paths, outside) is None
def test_failure_with_changed_cwd(pytester: Pytester) -> None:
"""
Test failure lines should use absolute paths if cwd has changed since
invocation, so the path is correct (#6428).
"""
p = pytester.makepyfile(
"""
import os
import pytest
@pytest.fixture
def private_dir():
out_dir = 'ddd'
os.mkdir(out_dir)
old_dir = os.getcwd()
os.chdir(out_dir)
yield out_dir
os.chdir(old_dir)
def test_show_wrong_path(private_dir):
assert False
"""
)
result = pytester.runpytest()
result.stdout.fnmatch_lines([str(p) + ":*: AssertionError", "*1 failed in *"])
|