pytest-xvfb
pytest-xvfb is an active pytest plugin, currently at version 3.1.1, that automatically runs tests within a virtual X server like Xvfb, Xephyr, or Xvnc. This enables running graphical user interface (GUI) tests in headless environments, such as continuous integration (CI) servers, without the need for a physical display, preventing windows from unexpectedly popping up during testing.
Common errors
-
pytest-qt needs a DISPLAY to run, otherwise Qt calls abort() and the process crashes immediately.
cause GUI tests (e.g., using PyQt/PySide with pytest-qt) are being run in an environment without an active X display server, causing the Qt application to crash.fixInstall `pytest-xvfb` and ensure `xvfb` (the system package) is installed. `pytest-xvfb` will automatically provide a virtual display for your tests. Command: `pip install pytest-xvfb` then `sudo apt-get install xvfb` (or equivalent for your OS). -
ERROR: InvocationError: '/path/to/project/.tox/py36/bin/python setup.py test --addopts --doctest-modules' ___ summary _____ ERROR: py36: commands failed
cause Similar to the 'DISPLAY' issue, `tox` runs often occur in headless environments. If the tests involve GUI components, the lack of a display server causes an unhandled error, leading to a generic `InvocationError`.fixIntegrate `pytest-xvfb` into your `tox` environment. Ensure `pytest-xvfb` is installed in the testenv and that `xvfb` is available on the system. You might need to add `passenv = DISPLAY XAUTHORITY` to your `tox.ini` if not automatically handled. -
AssertionError: assert False + where False = hasattr('hello', 'check') (or similar for UI events). / TimeoutError when using waitUntil, waitExposed and UI events.cause When running GUI tests with Xvfb, UI events (like button clicks, window exposures) may not propagate correctly if a window manager is not active within the virtual display.fixStart a lightweight window manager (e.g., `herbstluftwm`) within your CI environment before starting tests. For example, in a `.travis.yml` or similar CI config: `sudo apt-get install -y xvfb herbstluftwm` and then launch `herbstluftwm &` after Xvfb starts. -
Xvfb IO Error: client killed
cause The application being tested crashed the Xvfb server itself, often due to an unhandled X error or resource issue, rather than the test framework failing. This can be masked if using an `xvfb-run` wrapper.fixInvestigate the logs of the GUI application itself for errors that might be causing the X server to terminate. Ensure system resources (memory, CPU) are sufficient for Xvfb and the application. If using `xvfb-run`, add `--error-file=` to capture Xvfb's stderr for more diagnostic information. Consider updating `pytest-xvfb` and `pyvirtualdisplay` as they manage Xvfb more robustly.
Warnings
- gotcha The `xvnc` backend is currently experimental and may not be fully stable or tested on all CI environments, especially with newer Ubuntu versions and `PyVirtualDisplay` incompatibilities.
- gotcha When using `xvfb` or `xephyr`, ensure a window manager is running for UI events to function properly within your GUI applications being tested. Without a window manager, certain UI interactions (like clicks or keyboard inputs) might not be registered correctly.
- gotcha If the underlying `xvfb` system package is not installed on the testing environment, `pytest-xvfb` will issue an informational message. However, if you explicitly use the `--xvfb-backend xvfb` option without the `xvfb` system package, it will result in a hard error.
- gotcha Using Python's Qt modules (PySide or PyQt) with other packages that also link against Qt (e.g., some `cv2` builds) can lead to conflicts in CI environments due to differing Qt versions or environment variables, which may cause tests to fail.
Install
-
pip install pytest-xvfb
Imports
- pytest.mark.no_xvfb
import pytest; @pytest.mark.no_xvfb
- xvfb fixture
def test_something(xvfb): ...
Quickstart
import pytest
import os
def test_gui_app_runs_headless(xvfb):
# The test automatically runs with Xvfb started by pytest-xvfb
# The 'xvfb' fixture provides details about the virtual display.
print(f"\nRunning on virtual display: {xvfb.display}")
print(f"Screen resolution: {xvfb.width}x{xvfb.height}x{xvfb.colordepth}")
# Example: Run a simple command that needs a display
# In a real scenario, you'd launch your GUI application here
# and perform assertions.
# For demonstration, we'll just check DISPLAY environment variable
assert os.environ.get('DISPLAY') == f':{xvfb.display}', 'DISPLAY environment variable not set correctly.'
@pytest.mark.no_xvfb
def test_this_runs_without_xvfb():
# This test will explicitly not use Xvfb, even if enabled.
assert 'DISPLAY' not in os.environ