summaryrefslogtreecommitdiff
path: root/test/conftest.py
blob: 38f4dabc15fe896b17b9fd871da9a828d12c1607 (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
122
123
124
125
126
127
128
import sys
from contextlib import ExitStack

import pytest

pytest.register_assert_rewrite("test.utils")

from pathlib import Path  # noqa: E402
from test.utils.audit import AuditHookDispatcher  # noqa: E402
from test.utils.http import ctx_http_server  # noqa: E402
from test.utils.httpfileserver import HTTPFileServer  # noqa: E402
from typing import (  # noqa: E402
    Collection,
    Dict,
    Generator,
    Iterable,
    Optional,
    Tuple,
    Union,
)

from rdflib import Graph

from .data import TEST_DATA_DIR
from .utils.earl import EARLReporter  # noqa: E402
from .utils.httpservermock import ServedBaseHTTPServerMock  # noqa: E402

pytest_plugins = [EARLReporter.__module__]

# This is here so that asserts from these modules are formatted for human
# readibility.


@pytest.fixture(scope="session")
def http_file_server() -> Generator[HTTPFileServer, None, None]:
    host = "127.0.0.1"
    server = HTTPFileServer((host, 0))
    with ctx_http_server(server) as served:
        yield served


@pytest.fixture(scope="session")
def rdfs_graph() -> Graph:
    return Graph().parse(TEST_DATA_DIR / "defined_namespaces/rdfs.ttl", format="turtle")


_ServedBaseHTTPServerMocks = Tuple[ServedBaseHTTPServerMock, ServedBaseHTTPServerMock]


@pytest.fixture(scope="session")
def _session_function_httpmocks() -> Generator[_ServedBaseHTTPServerMocks, None, None]:
    """
    This fixture is session scoped, but it is reset for each function in
    :func:`function_httpmock`. This should not be used directly.
    """
    with ServedBaseHTTPServerMock() as httpmock_a, ServedBaseHTTPServerMock() as httpmock_b:
        yield httpmock_a, httpmock_b


@pytest.fixture(scope="function")
def function_httpmock(
    _session_function_httpmocks: _ServedBaseHTTPServerMocks,
) -> Generator[ServedBaseHTTPServerMock, None, None]:
    """
    HTTP server mock that is reset for each test function.
    """
    (mock, _) = _session_function_httpmocks
    mock.reset()
    yield mock


@pytest.fixture(scope="function")
def function_httpmocks(
    _session_function_httpmocks: _ServedBaseHTTPServerMocks,
) -> Generator[Tuple[ServedBaseHTTPServerMock, ServedBaseHTTPServerMock], None, None]:
    """
    Alternative HTTP server mock that is reset for each test function.

    This exists in case a tests needs to work with two different HTTP servers.
    """
    (mock_a, mock_b) = _session_function_httpmocks
    mock_a.reset()
    mock_b.reset()
    yield mock_a, mock_b


@pytest.fixture(scope="session", autouse=True)
def audit_hook_dispatcher() -> Generator[Optional[AuditHookDispatcher], None, None]:
    if sys.version_info >= (3, 8):
        dispatcher = AuditHookDispatcher()
        sys.addaudithook(dispatcher.audit)
        yield dispatcher
    else:
        yield None


@pytest.fixture(scope="function")
def exit_stack() -> Generator[ExitStack, None, None]:
    with ExitStack() as stack:
        yield stack


EXTRA_MARKERS: Dict[
    Tuple[Optional[str], str], Collection[Union[pytest.MarkDecorator, str]]
] = {
    ("rdflib/__init__.py", "rdflib"): [pytest.mark.webtest],
    ("rdflib/term.py", "rdflib.term.Literal.normalize"): [pytest.mark.webtest],
    ("rdflib/extras/infixowl.py", "rdflib.extras.infixowl"): [pytest.mark.webtest],
}


PROJECT_ROOT = Path(__file__).parent.parent


@pytest.hookimpl(tryfirst=True)
def pytest_collection_modifyitems(items: Iterable[pytest.Item]):
    for item in items:
        parent_name = (
            str(Path(item.parent.module.__file__).relative_to(PROJECT_ROOT))
            if item.parent is not None
            and isinstance(item.parent, pytest.Module)
            and item.parent.module is not None
            else None
        )
        if (parent_name, item.name) in EXTRA_MARKERS:
            extra_markers = EXTRA_MARKERS[(parent_name, item.name)]
            for extra_marker in extra_markers:
                item.add_marker(extra_marker)