summaryrefslogtreecommitdiffstats
path: root/test/conftest.py
blob: f31967d6fdf6b9e97db28b90d897f553a6551c1c (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
"""PyTest fixtures for testing the project."""
from __future__ import annotations

import os
import shutil
import subprocess
from contextlib import contextmanager
from pathlib import Path
from typing import TYPE_CHECKING, Iterator

import pytest

# pylint: disable=wildcard-import,unused-wildcard-import
from ansiblelint.testing.fixtures import *  # noqa: F403
from ansiblelint.yaml_utils import FormattedYAML

if TYPE_CHECKING:
    from typing import List  # pylint: disable=ungrouped-imports

    from _pytest import nodes
    from _pytest.config import Config
    from _pytest.config.argparsing import Parser


@contextmanager
def cwd(path: str) -> Iterator[None]:
    """Context manager for chdir."""
    old_pwd = os.getcwd()
    os.chdir(path)
    try:
        yield
    finally:
        os.chdir(old_pwd)


def pytest_addoption(parser: Parser) -> None:
    """Add --regenerate-formatting-fixtures option to pytest."""
    parser.addoption(
        "--regenerate-formatting-fixtures",
        action="store_true",
        default=False,
        help="Regenerate formatting fixtures with prettier and internal formatter",
    )


def pytest_collection_modifyitems(items: list[nodes.Item], config: Config) -> None:
    """Skip tests based on --regenerate-formatting-fixtures option."""
    do_regenerate = config.getoption("--regenerate-formatting-fixtures")
    skip_other = pytest.mark.skip(
        reason="not a formatting_fixture test and "
        "--regenerate-formatting-fixtures was specified"
    )
    skip_formatting_fixture = pytest.mark.skip(
        reason="specify --regenerate-formatting-fixtures to "
        "only run formatting_fixtures test"
    )
    for item in items:
        if do_regenerate and "formatting_fixtures" not in item.keywords:
            item.add_marker(skip_other)
        elif not do_regenerate and "formatting_fixtures" in item.keywords:
            item.add_marker(skip_formatting_fixture)


def pytest_configure(config: Config) -> None:
    """Register custom markers."""
    if config.getoption("--regenerate-formatting-fixtures"):
        regenerate_formatting_fixtures()


def regenerate_formatting_fixtures() -> None:
    """Re-generate formatting fixtures with prettier and internal formatter.

    Pass ``--regenerate-formatting-fixtures`` to run this and skip all other tests.
    This is a "test" because once fixtures are regenerated,
    we run prettier again to make sure it does not change files formatted
    with our internal formatting code.
    """
    subprocess.check_call(["which", "prettier"])

    yaml = FormattedYAML()

    fixtures_dir = Path("test/fixtures/")
    fixtures_dir_before = fixtures_dir / "formatting-before"
    fixtures_dir_prettier = fixtures_dir / "formatting-prettier"
    fixtures_dir_after = fixtures_dir / "formatting-after"

    fixtures_dir_prettier.mkdir(exist_ok=True)
    fixtures_dir_after.mkdir(exist_ok=True)

    # Copying before fixtures...
    for fixture in fixtures_dir_before.glob("fmt-[0-9].yml"):
        shutil.copy(str(fixture), str(fixtures_dir_prettier / fixture.name))
        shutil.copy(str(fixture), str(fixtures_dir_after / fixture.name))

    # Writing fixtures with prettier...
    subprocess.check_call(["prettier", "-w", str(fixtures_dir_prettier)])
    # NB: pre-commit end-of-file-fixer can also modify files.

    # Writing fixtures with ansiblelint.yaml_utils.FormattedYAML()
    for fixture in fixtures_dir_after.glob("fmt-[0-9].yml"):
        data = yaml.loads(fixture.read_text())
        output = yaml.dumps(data)
        fixture.write_text(output)

    # Make sure prettier won't make changes in {fixtures_dir_after}
    subprocess.check_call(["prettier", "-c", str(fixtures_dir_after)])