userver: en/testsuite/databases/clickhouse/pytest_plugin.py Source File
Loading...
Searching...
No Matches
pytest_plugin.py
1import collections
2
3import clickhouse_driver
4import pytest
5
6from . import classes, control, service, utils
7
8
9def pytest_addoption(parser):
10 group = parser.getgroup('clickhouse')
11 group.addoption('--clickhouse')
12 group.addoption(
13 '--no-clickhouse',
14 help='Disable use of ClickHouse',
15 action='store_true',
16 )
17
18
19def pytest_configure(config):
20 config.addinivalue_line(
21 'markers',
22 'clickhouse: per-test ClickHouse initialization',
23 )
24
25
26def pytest_service_register(register_service):
27 register_service('clickhouse', service.create_clickhouse_service)
28
29
30@pytest.fixture
31def clickhouse(
32 _clickhouse,
33 _clickhouse_apply,
34) -> dict[str, clickhouse_driver.Client]:
35 return _clickhouse.get_connections()
36
37
38@pytest.fixture
39def _clickhouse(clickhouse_local, _clickhouse_service, _clickhouse_state):
40 if not _clickhouse_service:
41 clickhouse_local = {}
42 dbcontrol = control.Control(clickhouse_local, _clickhouse_state)
43 dbcontrol.run_migrations()
44 return dbcontrol
45
46
47@pytest.fixture
48def _clickhouse_apply(
49 clickhouse_local,
50 _clickhouse_state,
51 _clickhouse_query_loader,
52 request,
53):
54 def load_default_queries(dbname):
55 return [
56 *_clickhouse_query_loader.load(
57 f'ch_{dbname}.sql',
58 'clickhouse.default_queries',
59 missing_ok=True,
60 ),
61 *_clickhouse_query_loader.loaddir(
62 f'ch_{dbname}',
63 'clickhouse.default_queries',
64 missing_ok=True,
65 ),
66 ]
67
68 def clickhouse_mark(dbname, *, files=(), directories=(), queries=()):
69 result_queries = []
70 for path in files:
71 result_queries += _clickhouse_query_loader.load(
72 path, 'mark.clickhouse.files'
73 )
74 for path in directories:
75 result_queries += _clickhouse_query_loader.loaddir(
76 path, 'mark.clickhouse.directories'
77 )
78 for query in queries:
79 result_queries.append(
80 control.ClickhouseQuery(
81 body=query,
82 source='mark.clickhouse.queries',
83 path=None,
84 ),
85 )
86
87 return dbname, result_queries
88
89 overrides = collections.defaultdict(list)
90 for mark in request.node.iter_markers('clickhouse'):
91 dbname, queries = clickhouse_mark(*mark.args, **mark.kwargs)
92 if dbname not in clickhouse_local:
93 raise RuntimeError(f'Unknown clickhouse database {dbname}')
94 overrides[dbname].extend(queries)
95
96 for alias, dbconfig in clickhouse_local.items():
97 if alias in overrides:
98 queries = overrides[alias]
99 else:
100 queries = load_default_queries(alias)
101 control.apply_queries(
102 _clickhouse_state.get_connection(dbconfig.dbname),
103 queries,
104 )
105
106
107@pytest.fixture
108def _clickhouse_query_loader(get_file_path, get_directory_path):
109 def load_query(path, source):
110 return control.ClickhouseQuery(
111 body=path.read_text(),
112 source=source,
113 path=str(path),
114 )
115
116 class Loader:
117 @staticmethod
118 def load(path, source, missing_ok=False):
119 data = get_file_path(path, missing_ok=missing_ok)
120 if not data:
121 return []
122 return [load_query(data, source)]
123
124 @staticmethod
125 def loaddir(directory, source, missing_ok=False):
126 result = []
127 directory = get_directory_path(directory, missing_ok=missing_ok)
128 if not directory:
129 return []
130 for path in utils.scan_sql_directory(directory):
131 result.append(load_query(path, source))
132 return result
133
134 return Loader()
135
136
137@pytest.fixture(scope='session')
138def clickhouse_disabled(pytestconfig) -> bool:
139 return pytestconfig.option.no_clickhouse
140
141
142@pytest.fixture(scope='session')
143def clickhouse_local() -> classes.DatabasesDict:
144 """Use to override databases configuration.
145
146 @ingroup userver_testsuite_fixtures
147 Part of the [yandex-taxi-testsuite](https://github.com/yandex/yandex-taxi-testsuite/blob/develop/testsuite/databases/clickhouse/pytest_plugin.py#L143)
148 """
149 return {}
150
151
152@pytest.fixture(scope='session')
153def _clickhouse_service_settings() -> service.ServiceSettings:
154 return service.get_service_settings()
155
156
157@pytest.fixture(scope='session')
158def clickhouse_conn_info(_clickhouse_service_settings):
159 return _clickhouse_service_settings.get_connection_info()
160
161
162@pytest.fixture
163def _clickhouse_service(
164 ensure_service_started,
165 clickhouse_local,
166 clickhouse_disabled,
167 pytestconfig,
168 _clickhouse_service_settings,
169):
170 if not clickhouse_local or clickhouse_disabled:
171 return False
172 if not pytestconfig.option.clickhouse:
173 ensure_service_started(
174 'clickhouse',
175 settings=_clickhouse_service_settings,
176 )
177 return True
178
179
180@pytest.fixture(scope='session')
181def _clickhouse_state(pytestconfig, clickhouse_conn_info):
182 return control.DatabasesState(
183 connections=control.ConnectionCache(clickhouse_conn_info),
184 verbose=pytestconfig.option.verbose,
185 )