from unittest import mock import pytest from pytestqt.exceptions import TimeoutError as QtBotTimeoutError from qtpy.QtWidgets import QApplication from bec_widgets.cli.rpc.rpc_register import RPCRegister from bec_widgets.utils import bec_dispatcher as bec_dispatcher_module from bec_widgets.utils import error_popups @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): # execute all other hooks to obtain the report object outcome = yield rep = outcome.get_result() item.stash["failed"] = rep.failed @pytest.fixture(autouse=True) def qapplication(qtbot, request, testable_qtimer_class): # pylint: disable=unused-argument yield # if the test failed, we don't want to check for open widgets as # it simply pollutes the output if request.node.stash._storage.get("failed"): print("Test failed, skipping cleanup checks") return bec_dispatcher = bec_dispatcher_module.BECDispatcher() bec_dispatcher.stop_cli_server() testable_qtimer_class.check_all_stopped(qtbot) qapp = QApplication.instance() qapp.processEvents() if hasattr(qapp, "os_listener") and qapp.os_listener: qapp.removeEventFilter(qapp.os_listener) try: qtbot.waitUntil(lambda: qapp.topLevelWidgets() == []) except QtBotTimeoutError as exc: raise TimeoutError(f"Failed to close all widgets: {qapp.topLevelWidgets()}") from exc @pytest.fixture(autouse=True) def rpc_register(): yield RPCRegister() RPCRegister.reset_singleton() @pytest.fixture(autouse=True) def bec_dispatcher(threads_check): # pylint: disable=unused-argument bec_dispatcher = bec_dispatcher_module.BECDispatcher() yield bec_dispatcher bec_dispatcher.disconnect_all() # clean BEC client bec_dispatcher.client.shutdown() # stop the cli server bec_dispatcher.stop_cli_server() # reinitialize singleton for next test bec_dispatcher_module.BECDispatcher.reset_singleton() @pytest.fixture(autouse=True) def clean_singleton(): error_popups._popup_utility_instance = None def create_widget(qtbot, widget, *args, **kwargs): """ Create a widget and add it to the qtbot for testing. This is a helper function that should be used in all tests that require a widget to be created. Args: qtbot (fixture): pytest-qt fixture widget (QWidget): widget class to be created *args: positional arguments for the widget **kwargs: keyword arguments for the widget Returns: QWidget: the created widget """ widget = widget(*args, **kwargs) qtbot.addWidget(widget) qtbot.waitExposed(widget) return widget