{"id":5033,"library":"pytest-qt","title":"pytest-qt","description":"pytest-qt is a pytest plugin that provides utilities and fixtures for testing PyQt and PySide applications. It simplifies GUI testing by offering tools to interact with widgets, handle signals, and manage the Qt event loop, ensuring reliable and robust tests for Qt-based UIs. The current version is 4.5.0, with minor releases arriving semi-regularly.","status":"active","version":"4.5.0","language":"en","source_language":"en","source_url":"https://github.com/pytest-dev/pytest-qt","tags":["pytest","qt","pyqt","pyside","testing","gui","plugin"],"install":[{"cmd":"pip install pytest-qt","lang":"bash","label":"Install core plugin"},{"cmd":"pip install pytest-qt 'PyQt5'","lang":"bash","label":"Install with PyQt5 bindings"},{"cmd":"pip install pytest-qt 'PySide6'","lang":"bash","label":"Install with PySide6 bindings"}],"dependencies":[{"reason":"pytest-qt is a plugin for the pytest testing framework.","package":"pytest","optional":false},{"reason":"One of the Qt bindings is required to run tests against a Qt application. pytest-qt supports PyQt5, PyQt6, PySide2, and PySide6.","package":"PyQt5","optional":true},{"reason":"One of the Qt bindings is required to run tests against a Qt application. pytest-qt supports PyQt5, PyQt6, PySide2, and PySide6.","package":"PyQt6","optional":true},{"reason":"One of the Qt bindings is required to run tests against a Qt application. pytest-qt supports PyQt5, PyQt6, PySide2, and PySide6.","package":"PySide2","optional":true},{"reason":"One of the Qt bindings is required to run tests against a Qt application. pytest-qt supports PyQt5, PyQt6, PySide2, and PySide6.","package":"PySide6","optional":true}],"imports":[{"note":"pytest-qt's primary features are exposed via fixtures, which are automatically discovered by pytest and injected into test functions. They should not be imported directly.","wrong":"from pytest_qt.plugin import qtbot # or similar","symbol":"qtbot (fixture)","correct":"def test_something(qtbot):\n    # use qtbot here"}],"quickstart":{"code":"from PyQt5.QtWidgets import QLabel\nimport pytest\n\ndef test_label_text_using_qtbot(qtbot):\n    # The QApplication instance is managed by pytest-qt (via the 'qapp' fixture if needed).\n    # We typically don't create/quit QApplication explicitly in tests using pytest-qt.\n    label = QLabel('Hello QtBot')\n    qtbot.addWidget(label)\n    # qtbot.addWidget ensures the widget is shown and its lifecycle is managed for the test.\n    # No explicit label.show(), qtbot.waitExposed(), or label.close() needed for basic interaction.\n    assert label.text() == 'Hello QtBot'\n","lang":"python","description":"This quickstart demonstrates a basic test using the `qtbot` fixture. `qtbot` provides methods to interact with Qt widgets. `qtbot.addWidget` is used to manage the widget's lifecycle for the duration of the test, handling showing and cleanup. The specific `QtWidgets` import (e.g., PyQt5, PySide6) depends on your chosen Qt binding."},"warnings":[{"fix":"Use the `PYTEST_QT_API` environment variable (e.g., `export PYTEST_QT_API=pyqt5`) or the `qt_api` config option in `pytest.ini` to explicitly select the Qt binding (e.g., `qt_api = pyside6`).","message":"The environment variable `PYTEST_QT_FORCE_PYQT` for forcing PyQt API selection was deprecated in favor of `PYTEST_QT_API` in version 1.3.0. While `PYTEST_QT_FORCE_PYQT` was initially kept for backward compatibility, new projects and updated configurations should use `PYTEST_QT_API`.","severity":"breaking","affected_versions":"All versions, especially projects migrating from <1.3.0"},{"fix":"Upgrade to `pytest-qt` version 1.5.0 or later to ensure that actual exceptions are correctly propagated when using signal waiting utilities.","message":"Prior to `pytest-qt` version 1.5.0, exceptions raised within a `qtbot.waitSignals` or `qtbot.waitSignal` with-statement block could be swallowed and result in a `SignalTimeoutError` instead of the actual exception, masking the root cause of the failure.","severity":"gotcha","affected_versions":"<1.5.0"},{"fix":"Upgrade to `pytest-qt` version 1.5.1 or later. It's also good practice to ensure your Qt application handles exceptions gracefully in virtual methods to prevent such issues at the Qt level.","message":"When using `PyQt5.5` or newer, Qt changed its default behavior to call `abort` on unhandled exceptions in virtual methods during tear down, which could crash the interpreter. `pytest-qt` version 1.5.1 introduced a fix to capture these exceptions during tear down, preventing crashes.","severity":"breaking","affected_versions":"<1.5.1 when used with PyQt >= 5.5"},{"fix":"Always explicitly configure the desired Qt binding using the `PYTEST_QT_API` environment variable (e.g., `PYTEST_QT_API=pyside6`) or by adding `qt_api = pyside6` to your `pytest.ini` file. This ensures consistent test execution.","message":"While `pytest-qt` attempts to auto-detect the available Qt binding (PyQt5, PyQt6, PySide2, PySide6), explicit configuration is highly recommended to avoid unexpected behavior or conflicts if multiple bindings are installed. The order of `sys.path` and other factors can influence auto-detection.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-12T00:00:00.000Z","next_check":"2026-07-11T00:00:00.000Z"}