2Service main and monitor clients. 
    9import aiohttp.client_exceptions
 
   13from testsuite.daemons 
import service_client 
as base_service_client
 
   14from testsuite.daemons.pytest_plugin 
import DaemonInstance
 
   15from testsuite.utils 
import compat
 
   17from pytest_userver 
import client
 
   20logger = logging.getLogger(__name__)
 
   26    Service client dependencies hook. Feel free to override, e.g.: 
   30    def extra_client_deps(some_fixtures_to_wait_before_service_start): 
   33    @ingroup userver_testsuite_fixtures 
 
   40    Service client dependencies hook that knows about pgsql, mongodb, 
   41    clickhouse, rabbitmq, redis_store, ydb, and mysql dependencies. 
   42    To add some other dependencies prefer overriding the 
   43    extra_client_deps() fixture. 
   45    @ingroup userver_testsuite_fixtures 
   58        fixture_lookup_error = pytest.FixtureLookupError
 
   59    except AttributeError:
 
   61        import _pytest.fixtures
 
   62        fixture_lookup_error = _pytest.fixtures.FixtureLookupError
 
   65    for dep 
in known_deps:
 
   67            request.getfixturevalue(dep)
 
   68            resolved_deps.append(dep)
 
   69        except fixture_lookup_error:
 
   73        'userver fixture "auto_client_deps" resolved dependencies %s',
 
 
   79async def service_client(
 
   80        ensure_daemon_started,
 
   84        cleanup_userver_dumps,
 
   85        userver_client_cleanup,
 
   86        _config_service_defaults_updated,
 
   87        _testsuite_client_config: client.TestsuiteClientConfig,
 
   89        _service_client_testsuite,
 
   96    Main fixture that provides access to userver based service. 
   98    @snippet samples/testsuite-support/tests/test_ping.py service_client 
   99    @anchor service_client 
  100    @ingroup userver_testsuite_fixtures 
  104    daemon = await ensure_daemon_started(service_daemon)
 
  106    if not _testsuite_client_config.testsuite_action_path:
 
  107        yield _service_client_base
 
  109        service_client = _service_client_testsuite(daemon)
 
  110        await _config_service_defaults_updated.update(
 
  111            service_client, dynamic_config,
 
  114        async with userver_client_cleanup(service_client):
 
 
  119def userver_client_cleanup(request, userver_flush_logs):
 
  120    marker = request.node.get_closest_marker(
'suspend_periodic_tasks')
 
  122        tasks_to_suspend = marker.args
 
  124        tasks_to_suspend = ()
 
  126    @compat.asynccontextmanager 
  127    async def cleanup_manager(client: client.AiohttpClient):
 
  129            await client.suspend_periodic_tasks(tasks_to_suspend)
 
  133                await client.resume_all_periodic_tasks()
 
  135    return cleanup_manager
 
  140    """Flush logs in case of failure.""" 
  142    @compat.asynccontextmanager 
  143    async def flush_logs(service_client: client.AiohttpClient):
 
  144        async def do_flush():
 
  146                await service_client.log_flush()
 
  147            except aiohttp.client_exceptions.ClientResponseError:
 
  158            if failed 
or item.utestsuite_report.failed:
 
 
  167    Fixture that provides access to userver based websocket service. 
  169    @anchor websocket_client 
  170    @ingroup userver_testsuite_fixtures 
  174        @compat.asynccontextmanager 
  175        async def get(self, path):
 
  176            update_server_state = getattr(
 
  177                service_client, 
'update_server_state', 
None,
 
  179            if update_server_state:
 
  180                await update_server_state()
 
  181            ws_context = websockets.connect(
 
  182                f
'ws://localhost:{service_port}/{path}',
 
  184            async with ws_context 
as socket:
 
 
  193        service_client_options,
 
  195        monitor_baseurl: str,
 
  199    Main fixture that provides access to userver monitor listener. 
  201    @snippet samples/testsuite-support/tests/test_metrics.py metrics labels 
  202    @ingroup userver_testsuite_fixtures 
  204    aiohttp_client = client.AiohttpClientMonitor(
 
  206        config=_testsuite_client_config,
 
  207        headers={
'x-yatraceid': mockserver.trace_id},
 
  208        **service_client_options,
 
 
  214async def _service_client_base(service_baseurl, service_client_options):
 
  215    class _ClientDiagnose(base_service_client.Client):
 
  216        def __getattr__(self, name: str) -> 
None:
 
  217            raise AttributeError(
 
  218                f
'"Client" object has no attribute "{name}". ' 
  219                'Note that "service_client" fixture returned the basic ' 
  220                '"testsuite.daemons.service_client.Client" client rather than ' 
  221                'a "pytest_userver.client.Client" client with userver ' 
  222                'extensions. That happened because the service ' 
  223                'static configuration file contains no "tests-control" ' 
  224                'component with "action" field.',
 
  227    return _ClientDiagnose(service_baseurl, **service_client_options)
 
  231def _service_client_testsuite(
 
  233        service_client_options,
 
  235        userver_cache_control,
 
  239        cache_invalidation_state,
 
  240        service_periodic_tasks_state,
 
  241        _testsuite_client_config: client.TestsuiteClientConfig,
 
  243    def create_client(daemon):
 
  244        aiohttp_client = client.AiohttpClient(
 
  246            config=_testsuite_client_config,
 
  248            testpoint_control=testpoint_control,
 
  249            periodic_tasks_state=service_periodic_tasks_state,
 
  250            log_capture_fixture=userver_log_capture,
 
  251            mocked_time=mocked_time,
 
  252            cache_invalidation_state=cache_invalidation_state,
 
  253            cache_control=userver_cache_control(daemon),
 
  254            **service_client_options,
 
  261@pytest.fixture(scope='session') 
  264    Returns the main listener URL of the service. 
  266    Override this fixture to change the main listener URL that the testsuite 
  269    @ingroup userver_testsuite_fixtures 
  271    return f
'http://localhost:{service_port}/' 
  274@pytest.fixture(scope='session') 
 
  277    Returns the main monitor URL of the service. 
  279    Override this fixture to change the main monitor URL that the testsuite 
  282    @ingroup userver_testsuite_fixtures 
  284    return f
'http://localhost:{monitor_port}/' 
  287@pytest.fixture(scope='session') 
 
  288def service_periodic_tasks_state() -> client.PeriodicTasksState:
 
  292@pytest.fixture(scope='session') 
  293def _testsuite_client_config(
 
  294        pytestconfig, service_config,
 
  295) -> client.TestsuiteClientConfig:
 
  296    components = service_config[
'components_manager'][
'components']
 
  298    def get_component_path(name, argname=None):
 
  299        if name 
in components:
 
  300            path = components[name][
'path']
 
  301            path = path.rstrip(
'*')
 
  303            if argname 
and f
'{{{argname}}}' not in path:
 
  305                    f
'Component {name} must provide path argument {argname}',
 
  311        server_monitor_path=get_component_path(
'handler-server-monitor'),
 
  312        testsuite_action_path=get_component_path(
'tests-control', 
'action'),