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')
116 service_http_ping_url,
117 service_config_path_temp,
119 service_non_http_health_checks,
120 service_start_timeout,
123 Prepares the start of the service daemon.
124 Configures the health checking to use service_http_ping_url fixture value
125 if it is not None; otherwise uses the service_non_http_health_checks info.
127 @see @ref pytest_userver.plugins.service.service_daemon_instance "service_daemon_instance"
128 @ingroup userver_testsuite_fixtures
130 assert service_http_ping_url
or service_non_http_health_checks.tcp, (
131 '"service_http_ping_url" and "create_health_checker" fixtures '
132 'returned None. Testsuite is unable to detect if the service is ready '
133 'to accept requests.',
137 'userver fixture "service_daemon_scope" would check for "%s"',
138 service_non_http_health_checks,
145 async def _checker(*, session, process) -> bool:
146 LocalCounters.attempts += 1
147 new_log_time = time.monotonic()
148 if new_log_time - LocalCounters.last_log_time > 1.0:
149 LocalCounters.last_log_time = new_log_time
151 'userver fixture "service_daemon_scope" checking "%s", attempt %s',
152 service_non_http_health_checks,
153 LocalCounters.attempts,
156 return await net.check_availability(service_non_http_health_checks)
158 health_check = _checker
159 if service_http_ping_url:
163 poll_retries = int(service_start_timeout / 0.05)
165 async with create_daemon_scope(
166 args=[str(service_binary),
'--config', str(service_config_path_temp)],
167 ping_url=service_http_ping_url,
168 health_check=health_check,
170 poll_retries=poll_retries,
300 Depend on this fixture directly or transitively to make your fixture a per-daemon fixture.
305 @pytest.fixture(scope='session')
306 def users_cache_state(daemon_scoped_mark, ...):
307 return UsersCacheState(users_list=[])
310 For tests marked with `@pytest.mark.uservice_oneshot(...)`, the service will be restarted,
311 and all the per-daemon fixtures will be recreated.
313 This fixture returns kwargs passed to the `uservice_oneshot` mark (which may be an empty dict).
314 For normal tests, this fixture returns `None`.
316 @ingroup userver_testsuite_fixtures
324 return getattr(request,
'param',
None)
330def pytest_configure(config):
331 config.addinivalue_line(
333 'uservice_oneshot: use a per-test service daemon instance',
337def _contains_oneshot_marker(parametrize: Iterable[pytest.Mark]) -> bool:
339 Check if at least one of 'parametrize' marks is of the form:
341 @pytest.mark.parametrize(
345 pytest.param("b", 20, marks=pytest.mark.uservice_oneshot), # <====
351 for parametrize_mark
in parametrize
352 if len(parametrize_mark.args) >= 2
353 for parameter_set
in parametrize_mark.args[1]
354 if hasattr(parameter_set,
'marks')
355 for mark
in parameter_set.marks
356 if mark.name ==
'uservice_oneshot'
360def pytest_generate_tests(metafunc: pytest.Metafunc) ->
None:
361 oneshot_marker = metafunc.definition.get_closest_marker(
'uservice_oneshot')
362 parametrize_markers = metafunc.definition.iter_markers(
'parametrize')
363 if oneshot_marker
is not None or _contains_oneshot_marker(parametrize_markers):
365 metafunc.parametrize(
366 (daemon_scoped_mark.__name__,),
371 ids=[
'uservice_oneshot'],
380def pytest_collection_modifyitems(items: list[pytest.Item]):
382 oneshot_marker = item.get_closest_marker(
'uservice_oneshot')
383 if oneshot_marker
and isinstance(item, pytest.Function):
384 func_item = typing.cast(pytest.Function, item)
385 func_item.callspec.params[daemon_scoped_mark.__name__] = dict(oneshot_marker.kwargs, function=func_item)