Metadata-Version: 2.5
Name: qamule-pytest-dispcap
Version: 0.1.2
Summary: Case-level Android display recording for qamule-pytest.
License-Expression: MIT
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: adbutils>=2.12.0
Requires-Dist: pytest>=8.3
Requires-Dist: qamule-pytest>=0.1.0
Requires-Dist: uiautomator2>=3.7.0
Description-Content-Type: text/markdown

# qamule-pytest-dispcap

Case-level Android display recording for `qamule-pytest`.

## Usage

Register the devices through `qamule-pytest`, then select the devices to record with
`--dispcap-device`:

```bash
uv run pytest \
	-p qamule_pytest.plugin \
	-p qamule_pytest_dispcap.plugin \
	--device primary:emulator-5554 \
	--dispcap-device primary:display=0:size=1920x1080:bitrate=2.5M:fps=15
```

`--dispcap-device` may be repeated for multiple named devices. Its format is:

```text
--dispcap-device NAME[:display=ID[,ID...]][:size=WIDTHxHEIGHT][:bitrate=RATE][:fps=FPS]
```

`NAME` must be an existing `qamule-pytest` device name. The bundled `dispcap.jar`
is deployed once per selected device at session start. Use `--dispcap-jar PATH`
to override it.

The plugin reuses the uiautomator2 device and adbutils transport created by
`qamule-pytest`; it does not create a second device connection or set a device
port. Omit `--device-port` to use uiautomator2's default, or configure that
option on `qamule-pytest` when a non-default port is required.

Each selected device records from before fixture setup until after fixture
teardown. Outputs are written under the normal qamule-pytest case artifacts:

```text
pytest-artifacts/<session>/<case>/dispcap/<device>.mp4
pytest-artifacts/<session>/<case>/dispcap/manifest.json
```

The manifest records the effective capture settings, ADB command, timing, test
outcome, and per-device errors. Deploying or starting a capture is best effort:
a failure for one device does not fail the test or stop captures for other
selected devices.

## Retention and Circuit Breaker

Use `--dispcap-passed-remove` to remove each recorded device MP4 after a passed
case finishes. The case manifest remains and marks each successfully removed
file with `deleted_video: true`. Failed and skipped cases retain their videos.

The circuit breaker avoids recording repeated short cases that are unlikely to
produce useful video. It is enabled by default and can be tuned with:

```text
--dispcap-circuit-breaker-seconds SECONDS
--dispcap-circuit-breaker-consecutive COUNT
--dispcap-circuit-breaker-recover-consecutive COUNT
```

Defaults are `5.0` seconds, `1` short case to open, and `1` long case to
recover. When open, a case does not start dispcap and its manifest records
`recording.status = "skipped"` with reason `"circuit-breaker-open"`. A skipped
case that runs for at least the threshold contributes to recovery for later
cases.

The package uses the qamule-pytest uiautomator2 device for JAR deployment. Its
adbutils transport supplies the raw streaming shell connection and heartbeat
port forwarding.

## Real-device smoke test

The real-device test records a configured device for 60 seconds, then verifies
the generated MP4 and manifest. Set the device serial before running it:

```bash
QAMULE_PYTEST_DISPCAP_REAL_SERIAL=emulator-5554 \
	uv run pytest packages/qamule-pytest-dispcap/tests/test_real_device_recording.py -q
```

The test is marked `real_device` and skips when the environment variable is not
set.
