File: conftest.py

package info (click to toggle)
nc-py-api 0.19.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,320 kB
  • sloc: python: 12,415; makefile: 238; xml: 100; javascript: 56; sh: 14
file content (147 lines) | stat: -rw-r--r-- 5,387 bytes parent folder | download
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
141
142
143
144
145
146
147
from os import environ
from typing import Optional, Union

import pytest

from nc_py_api import (  # noqa
    AsyncNextcloud,
    AsyncNextcloudApp,
    Nextcloud,
    NextcloudApp,
    _session,
)

from . import gfixture_set_env  # noqa

_TEST_FAILED_INCREMENTAL: dict[str, dict[tuple[int, ...], str]] = {}

NC_CLIENT = None if environ.get("SKIP_NC_CLIENT_TESTS", False) else Nextcloud()
NC_CLIENT_ASYNC = None if environ.get("SKIP_NC_CLIENT_TESTS", False) else AsyncNextcloud()
if environ.get("SKIP_AA_TESTS", False):
    NC_APP = None
    NC_APP_ASYNC = None
else:
    NC_APP = NextcloudApp(user="admin")
    NC_APP_ASYNC = AsyncNextcloudApp(user="admin")
    if "app_api" not in NC_APP.capabilities:
        NC_APP = None
        NC_APP_ASYNC = None
if NC_CLIENT is None and NC_APP is None:
    raise EnvironmentError("Tests require at least Nextcloud or NextcloudApp.")


@pytest.fixture(scope="session")
def nc_version() -> _session.ServerVersion:
    return NC_APP.srv_version if NC_APP else NC_CLIENT.srv_version


@pytest.fixture(scope="session")
def nc_client() -> Optional[Nextcloud]:
    if NC_CLIENT is None:
        pytest.skip("Need Client mode")
    return NC_CLIENT


@pytest.fixture(scope="session")
def anc_client() -> Optional[AsyncNextcloud]:
    if NC_CLIENT_ASYNC is None:
        pytest.skip("Need Async Client mode")
    return NC_CLIENT_ASYNC


@pytest.fixture(scope="session")
def nc_app() -> Optional[NextcloudApp]:
    if NC_APP is None:
        pytest.skip("Need App mode")
    return NC_APP


@pytest.fixture(scope="session")
def anc_app() -> Optional[AsyncNextcloudApp]:
    if NC_APP_ASYNC is None:
        pytest.skip("Need Async App mode")
    return NC_APP_ASYNC


@pytest.fixture(scope="session")
def nc_any() -> Union[Nextcloud, NextcloudApp]:
    """Marks a test to run once for any of the modes."""
    return NC_APP if NC_APP else NC_CLIENT


@pytest.fixture(scope="session")
def anc_any() -> Union[AsyncNextcloud, AsyncNextcloudApp]:
    """Marks a test to run once for any of the modes."""
    return NC_APP_ASYNC if NC_APP_ASYNC else NC_CLIENT_ASYNC


@pytest.fixture(scope="session")
def nc(request) -> Union[Nextcloud, NextcloudApp]:
    """Marks a test to run for both modes if possible."""
    return request.param


@pytest.fixture(scope="session")
def anc(request) -> Union[AsyncNextcloud, AsyncNextcloudApp]:
    """Marks a test to run for both modes if possible."""
    return request.param


def pytest_generate_tests(metafunc):
    if "nc" in metafunc.fixturenames:
        values_ids = []
        values = []
        if NC_CLIENT is not None:
            values.append(NC_CLIENT)
            values_ids.append("client")
        if NC_APP is not None:
            values.append(NC_APP)
            values_ids.append("app")
        metafunc.parametrize("nc", values, ids=values_ids)
    if "anc" in metafunc.fixturenames:
        values_ids = []
        values = []
        if NC_CLIENT_ASYNC is not None:
            values.append(NC_CLIENT_ASYNC)
            values_ids.append("client_async")
        if NC_APP_ASYNC is not None:
            values.append(NC_APP_ASYNC)
            values_ids.append("app_async")
        metafunc.parametrize("anc", values, ids=values_ids)


def pytest_collection_modifyitems(items):
    for item in items:
        require_nc = [i for i in item.own_markers if i.name == "require_nc"]
        if require_nc:
            min_major = require_nc[0].kwargs["major"]
            min_minor = require_nc[0].kwargs.get("minor", 0)
            srv_ver = NC_APP.srv_version if NC_APP else NC_CLIENT.srv_version
            if srv_ver["major"] < min_major:
                item.add_marker(pytest.mark.skip(reason=f"Need NC>={min_major}"))
            elif srv_ver["major"] == min_major and srv_ver["minor"] < min_minor:
                item.add_marker(pytest.mark.skip(reason=f"Need NC>={min_major}.{min_minor}"))


def pytest_runtest_makereport(item, call):
    if "incremental" in item.keywords and call.excinfo is not None:
        # the test has failed
        cls_name = str(item.cls)  # retrieve the class name of the test
        # Retrieve the index of the test (if parametrize is used in combination with incremental)
        parametrize_index = tuple(item.callspec.indices.values()) if hasattr(item, "callspec") else ()
        test_name = item.originalname or item.name  # retrieve the name of the test function
        # store in _test_failed_incremental the original name of the failed test
        _TEST_FAILED_INCREMENTAL.setdefault(cls_name, {}).setdefault(parametrize_index, test_name)


def pytest_runtest_setup(item):
    if "incremental" in item.keywords:
        cls_name = str(item.cls)
        if cls_name in _TEST_FAILED_INCREMENTAL:  # check if a previous test has failed for this class
            # retrieve the index of the test (if parametrize is used in combination with incremental)
            parametrize_index = tuple(item.callspec.indices.values()) if hasattr(item, "callspec") else ()
            # retrieve the name of the first test function to fail for this class name and index
            test_name = _TEST_FAILED_INCREMENTAL[cls_name].get(parametrize_index, None)
            # if name found, test has failed for the combination of class name & test name
            if test_name is not None:
                pytest.xfail("previous test failed ({})".format(test_name))