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
|
from __future__ import annotations
import os
import sys
from itertools import chain, combinations
from pathlib import Path
from textwrap import dedent
from typing import Sequence
import pytest
from pytest_mock import MockerFixture
from tox.pytest import MonkeyPatch, ToxProjectCreator, check_os_environ
from tox.report import HandledError
def test_tox_project_no_base(tox_project: ToxProjectCreator) -> None:
project = tox_project(
{
"tox.ini": "[tox]",
"src": {"__init__.py": "pass", "a": "out", "b": {"c": "out"}, "e": {"f": ""}},
},
)
assert str(project.path) in repr(project)
assert project.path.exists()
assert project.structure == {
"tox.ini": "[tox]",
"src": {"__init__.py": "pass", "a": "out", "e": {"f": ""}, "b": {"c": "out"}},
}
def test_tox_project_base(tmp_path: Path, tox_project: ToxProjectCreator) -> None:
base = tmp_path / "base"
base.mkdir()
(base / "out").write_text("a")
project = tox_project({"tox.ini": "[tox]"}, base=base)
assert project.structure
COMB = list(chain.from_iterable(combinations(["DIFF", "MISS", "EXTRA"], i) for i in range(4)))
@pytest.mark.parametrize("ops", COMB, ids=["-".join(i) for i in COMB])
def test_env_var(monkeypatch: MonkeyPatch, ops: list[str]) -> None:
with monkeypatch.context() as m:
if "DIFF" in ops:
m.setenv("DIFF", "B")
if "MISS" in ops:
m.setenv("MISS", "1")
m.setenv("NO_CHANGE", "yes")
m.setenv("PYTHONPATH", "yes") # values to clean before run
with check_os_environ():
assert "PYTHONPATH" not in os.environ
if "EXTRA" in ops:
m.setenv("EXTRA", "A")
if "DIFF" in ops:
m.setenv("DIFF", "D")
if "MISS" in ops:
m.delenv("MISS")
from tox.pytest import pytest as tox_pytest # type: ignore[attr-defined]
exp = "test changed environ"
if "EXTRA" in ops:
exp += " extra {'EXTRA': 'A'}"
if "MISS" in ops:
exp += " miss {'MISS': '1'}"
if "DIFF" in ops:
exp += " diff {'DIFF = B vs D'}"
def fail(msg: str) -> None:
assert msg == exp
m.setattr(tox_pytest, "fail", fail)
assert "PYTHONPATH" in os.environ
def test_tox_run_does_not_return_exit_code(tox_project: ToxProjectCreator, mocker: MockerFixture) -> None:
project = tox_project({"tox.ini": ""})
mocker.patch("tox.run.main", return_value=None)
with pytest.raises(RuntimeError, match="exit code not set"):
project.run("c")
def test_tox_run_fails_before_state_setup(tox_project: ToxProjectCreator, mocker: MockerFixture) -> None:
project = tox_project({"tox.ini": ""})
mocker.patch("tox.run.main", side_effect=HandledError("something went bad"))
outcome = project.run("c")
with pytest.raises(RuntimeError, match="no state"):
assert outcome.state
def test_tox_run_outcome_repr(tox_project: ToxProjectCreator) -> None:
project = tox_project({"tox.ini": ""})
outcome = project.run("l")
msg = dedent(
f"""
code: 0
cmd: {sys.executable} -m tox l
cwd: {project.path}
standard output
default environments:
py -> [no description]
""",
).lstrip()
assert repr(outcome) == msg
assert outcome.shell_cmd == f"{sys.executable} -m tox l"
def test_tox_run_assert_out_err_no_dedent(tox_project: ToxProjectCreator, mocker: MockerFixture) -> None:
project = tox_project({"tox.ini": ""})
def _main(args: Sequence[str]) -> int: # noqa: U100
print(" goes on out", file=sys.stdout)
print(" goes on err", file=sys.stderr)
return 0
mocker.patch("tox.run.main", side_effect=_main)
outcome = project.run("c")
outcome.assert_out_err(" goes on out\n", " goes on err\n", dedent=False)
|