65 Returns the service HTTP ping URL that is used by the testsuite to detect
66 that the service is ready to work. Returns None if there's no such URL.
68 By default, attempts to find server::handlers::Ping component by
69 "handler-ping" name in static config. Override this fixture to change the
72 @ingroup userver_testsuite_fixtures
74 components = service_config[
'components_manager'][
'components']
75 ping_handler = components.get(
'handler-ping')
77 return url_util.join(service_baseurl, ping_handler[
'path'])
81@pytest.fixture(scope='session')
133 service_http_ping_url,
134 service_non_http_health_checks,
135) -> Callable[..., Awaitable[bool]] | None:
137 Returns the health check function used by
138 @ref pytest_userver.plugins.service.service_daemon_scope "service_daemon_scope"
139 to detect that the service has started and is ready to accept requests.
141 Returns None when service_http_ping_url is set, in which case
142 create_daemon_scope uses the ping URL directly. Otherwise returns a checker
143 based on the service_non_http_health_checks info.
145 Override this fixture to change the way the service readiness is detected.
147 @ingroup userver_testsuite_fixtures
149 assert service_http_ping_url
or service_non_http_health_checks.tcp, (
150 '"service_http_ping_url" and "create_health_checker" fixtures '
151 'returned None. Testsuite is unable to detect if the service is ready '
152 'to accept requests.',
156 'userver fixture "service_health_check" would check for "%s"',
157 service_non_http_health_checks,
160 if service_http_ping_url:
167 async def _checker(*, session, process) -> bool:
168 LocalCounters.attempts += 1
169 new_log_time = time.monotonic()
170 if new_log_time - LocalCounters.last_log_time > 1.0:
171 LocalCounters.last_log_time = new_log_time
173 'userver fixture "service_health_check" checking "%s", attempt %s',
174 service_non_http_health_checks,
175 LocalCounters.attempts,
178 return await net.check_availability(service_non_http_health_checks)
183@pytest.fixture(scope='session')
188 service_http_ping_url,
189 service_config_path_temp,
191 service_binary_launcher,
192 service_health_check,
193 service_start_timeout,
196 Prepares the start of the service daemon.
197 Configures the health checking via the service_health_check fixture.
199 @see @ref pytest_userver.plugins.service.service_daemon_instance "service_daemon_instance"
200 @ingroup userver_testsuite_fixtures
203 poll_retries = int(service_start_timeout / 0.05)
205 async with create_daemon_scope(
206 args=service_binary_launcher + [str(service_binary),
'--config', str(service_config_path_temp)],
207 ping_url=service_http_ping_url,
208 health_check=service_health_check,
210 poll_retries=poll_retries,
342 Depend on this fixture directly or transitively to make your fixture a per-daemon fixture.
347 @pytest.fixture(scope='session')
348 def users_cache_state(daemon_scoped_mark, ...):
349 return UsersCacheState(users_list=[])
352 For tests marked with `@pytest.mark.uservice_oneshot(...)`, the service will be restarted,
353 and all the per-daemon fixtures will be recreated.
355 This fixture returns kwargs passed to the `uservice_oneshot` mark (which may be an empty dict).
356 For normal tests, this fixture returns `None`.
358 @ingroup userver_testsuite_fixtures
366 return getattr(request,
'param',
None)
372def pytest_configure(config):
373 config.addinivalue_line(
375 'uservice_oneshot: use a per-test service daemon instance',
379def _contains_oneshot_marker(parametrize: Iterable[pytest.Mark]) -> bool:
381 Check if at least one of 'parametrize' marks is of the form:
383 @pytest.mark.parametrize(
387 pytest.param("b", 20, marks=pytest.mark.uservice_oneshot), # <====
393 for parametrize_mark
in parametrize
394 if len(parametrize_mark.args) >= 2
395 for parameter_set
in parametrize_mark.args[1]
396 if hasattr(parameter_set,
'marks')
397 for mark
in parameter_set.marks
398 if mark.name ==
'uservice_oneshot'
402def pytest_generate_tests(metafunc: pytest.Metafunc) ->
None:
403 oneshot_marker = metafunc.definition.get_closest_marker(
'uservice_oneshot')
404 parametrize_markers = metafunc.definition.iter_markers(
'parametrize')
405 if oneshot_marker
is not None or _contains_oneshot_marker(parametrize_markers):
407 metafunc.parametrize(
408 (daemon_scoped_mark.__name__,),
413 ids=[
'uservice_oneshot'],
420def pytest_collection_modifyitems(items: list[pytest.Item]):
422 oneshot_marker = item.get_closest_marker(
'uservice_oneshot')
423 if oneshot_marker
and isinstance(item, pytest.Function):
424 func_item = typing.cast(pytest.Function, item)
425 func_item.callspec.params[daemon_scoped_mark.__name__] = dict(oneshot_marker.kwargs, function=func_item)