64 Returns the service HTTP ping URL that is used by the testsuite to detect
65 that the service is ready to work. Returns None if there's no such URL.
67 By default, attempts to find server::handlers::Ping component by
68 "handler-ping" name in static config. Override this fixture to change the
71 @ingroup userver_testsuite_fixtures
73 components = service_config[
'components_manager'][
'components']
74 ping_handler = components.get(
'handler-ping')
76 return url_util.join(service_baseurl, ping_handler[
'path'])
80@pytest.fixture(scope='session')
103 service_http_ping_url,
104 service_config_path_temp,
106 service_non_http_health_checks,
109 Prepares the start of the service daemon.
110 Configures the health checking to use service_http_ping_url fixture value
111 if it is not None; otherwise uses the service_non_http_health_checks info.
113 @see @ref pytest_userver.plugins.service.service_daemon_instance "service_daemon_instance"
114 @ingroup userver_testsuite_fixtures
116 assert service_http_ping_url
or service_non_http_health_checks.tcp, (
117 '"service_http_ping_url" and "create_health_checker" fixtures '
118 'returned None. Testsuite is unable to detect if the service is ready '
119 'to accept requests.',
123 'userver fixture "service_daemon_scope" would check for "%s"',
124 service_non_http_health_checks,
131 async def _checker(*, session, process) -> bool:
132 LocalCounters.attempts += 1
133 new_log_time = time.monotonic()
134 if new_log_time - LocalCounters.last_log_time > 1.0:
135 LocalCounters.last_log_time = new_log_time
137 'userver fixture "service_daemon_scope" checking "%s", attempt %s',
138 service_non_http_health_checks,
139 LocalCounters.attempts,
142 return await net.check_availability(service_non_http_health_checks)
144 health_check = _checker
145 if service_http_ping_url:
148 async with create_daemon_scope(
149 args=[str(service_binary),
'--config', str(service_config_path_temp)],
150 ping_url=service_http_ping_url,
151 health_check=health_check,
282 Depend on this fixture directly or transitively to make your fixture a per-daemon fixture.
287 @pytest.fixture(scope='session')
288 def users_cache_state(daemon_scoped_mark, ...):
289 return UsersCacheState(users_list=[])
292 For tests marked with `@pytest.mark.uservice_oneshot(...)`, the service will be restarted,
293 and all the per-daemon fixtures will be recreated.
295 This fixture returns kwargs passed to the `uservice_oneshot` mark (which may be an empty dict).
296 For normal tests, this fixture returns `None`.
298 @ingroup userver_testsuite_fixtures
306 return getattr(request,
'param',
None)
312def pytest_configure(config):
313 config.addinivalue_line(
315 'uservice_oneshot: use a per-test service daemon instance',
319def _contains_oneshot_marker(parametrize: Iterable[pytest.Mark]) -> bool:
321 Check if at least one of 'parametrize' marks is of the form:
323 @pytest.mark.parametrize(
327 pytest.param("b", 20, marks=pytest.mark.uservice_oneshot), # <====
333 for parametrize_mark
in parametrize
334 if len(parametrize_mark.args) >= 2
335 for parameter_set
in parametrize_mark.args[1]
336 if hasattr(parameter_set,
'marks')
337 for mark
in parameter_set.marks
338 if mark.name ==
'uservice_oneshot'
342def pytest_generate_tests(metafunc: pytest.Metafunc) ->
None:
343 oneshot_marker = metafunc.definition.get_closest_marker(
'uservice_oneshot')
344 parametrize_markers = metafunc.definition.iter_markers(
'parametrize')
345 if oneshot_marker
is not None or _contains_oneshot_marker(parametrize_markers):
347 metafunc.parametrize(
348 (daemon_scoped_mark.__name__,),
353 ids=[
'uservice_oneshot'],
362def pytest_collection_modifyitems(items: list[pytest.Item]):
364 oneshot_marker = item.get_closest_marker(
'uservice_oneshot')
365 if oneshot_marker
and isinstance(item, pytest.Function):
366 func_item = typing.cast(pytest.Function, item)
367 func_item.callspec.params[daemon_scoped_mark.__name__] = dict(oneshot_marker.kwargs, function=func_item)