summaryrefslogtreecommitdiff
path: root/tests/pytest_/test_init.py
blob: 1bb4eed497d33c60f913eda79cd77cb2c2db682f (plain)
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)