# pytest plugin

The fixtures and options the plugin registers. Guide: [Python + pytest](../../sdk/python.md).

## <kbd>class</kbd> `TapConfig`
The plugin's settings, read from ``pytest.ini`` (``tap_*`` keys) or ``TAP_*`` environment variables; the environment wins. 

**Attributes:**
 
 - <b>`serials`</b>:  Devices to use, in order (``tap_serials`` / ``TAP_SERIALS``, comma-separated).  Empty means every device the server lists. 
 - <b>`artifacts`</b>:  Where failure artifacts are written (``tap_artifacts`` / ``TAP_ARTIFACTS``,  default ``tap-artifacts``). 
 - <b>`server`</b>:  ``host:port`` of the server (``tap_server`` / ``TAP_SERVER``). ``None`` finds  the one ``tap start`` recorded. 
 - <b>`acquire_timeout`</b>:  Seconds to wait for a device another session holds  (``tap_acquire_timeout`` / ``TAP_ACQUIRE_TIMEOUT``). 
 - <b>`manage_daemon`</b>:  Start the server before the session and stop it afterwards if this run  started it (``tap_manage_daemon`` / ``TAP_MANAGE_DAEMON``). 
 - <b>`capture_on_failure`</b>:  Save screenshot, hierarchy, device info and driver log when a test 
 - <b>`fails (``tap_capture`` / ``TAP_CAPTURE```</b>:  ``onFailure`` or ``off``). 
 - <b>`device_scope`</b>:  How long attached devices are kept: ``function`` (default), ``class``,  ``module`` or ``session`` (``tap_device_scope`` / ``TAP_DEVICE_SCOPE``). 

### <kbd>method</kbd> `TapConfig.__init__`

```python
__init__(
    serials: 'list[str]',
    artifacts: 'pathlib.Path',
    server: 'str | None',
    acquire_timeout: 'float',
    manage_daemon: 'bool',
    capture_on_failure: 'bool' = True,
    device_scope: 'str' = 'function'
) → None
```

---

### <kbd>classmethod</kbd> `TapConfig.from_pytest`

```python
from_pytest(config: 'pytest.Config') → TapConfig
```

Read the settings from the pytest configuration and the environment. 

## <kbd>function</kbd> `tap_config`

```python
tap_config(pytestconfig: 'pytest.Config') → TapConfig
```

The plugin's [TapConfig][tap_e2e.pytest_plugin.TapConfig] for the session. 

## <kbd>function</kbd> `tap_client`

```python
tap_client(tap_config: 'TapConfig') → Generator[TapClient, None, None]
```

The server channel. With ``tap_manage_daemon`` the daemon is started here and, if that start created it, stopped after the session; one already running is left alone. 

## <kbd>function</kbd> `tap_connection`

```python
tap_connection(
    tap_client: 'TapClient',
    request: 'pytest.FixtureRequest'
) → Generator[TapConnection, None, None]
```

One ``TapConnection`` per pytest session (observing from the start); the server tears everything down if this process dies. 

## <kbd>function</kbd> `tap_devices`

```python
tap_devices(
    request: 'pytest.FixtureRequest',
    tap_connection: 'TapConnection',
    tap_config: 'TapConfig'
) → Generator[dict[str, Device], None, None]
```

The test's devices by role, attached before the test and detached after it. 

Roles come from ``@pytest.mark.tap_devices("sender", "receiver")``; without the marker there is one role, ``"device"``. Each role gets a different serial, and the test is skipped when there are fewer devices than roles. If the test fails, failure artifacts are saved for every device under ``tap_artifacts/<test id>/``. 

## <kbd>function</kbd> `tap_device`

```python
tap_device(tap_devices: 'dict[str, Device]') → Device
```

The test's single device: ``tap_devices["device"]``. 

