From 938a167ff0f27c895b09f5739a4aacbc36b8d522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Weber?= Date: Wed, 7 Oct 2026 00:39:37 +0200 Subject: [PATCH] Use the plugin acceptance checks provided by PyMoDAQ 5.3.1 Replace the copy of the generic tests of the plugin template by the stub using pymodaq_utils.plugin_testing (see pymodaq_plugins_template PR 43). The module is skipped with older versions of PyMoDAQ. Co-Authored-By: Claude Sonnet 5.5 --- tests/test_plugin_package_structure.py | 105 +++++-------------------- 1 file changed, 21 insertions(+), 84 deletions(-) diff --git a/tests/test_plugin_package_structure.py b/tests/test_plugin_package_structure.py index be4e4ee..d050fb1 100644 --- a/tests/test_plugin_package_structure.py +++ b/tests/test_plugin_package_structure.py @@ -1,91 +1,28 @@ -# -*- coding: utf-8 -*- -""" -Created the 17/10/2023 - -@author: Sebastien Weber -""" -import pytest -from pathlib import Path -import importlib -import pkgutil - - -MANDATORY_MOVE_METHODS = ['ini_attributes', 'get_actuator_value', 'close', 'commit_settings', - 'ini_stage', 'move_abs', 'move_home', 'move_rel', 'stop_motion'] -MANDATORY_VIEWER_METHODS = ['ini_attributes', 'grab_data', 'close', 'commit_settings', - 'ini_detector', ] - - -def get_package_name(): - here = Path(__file__).parent - package_name = here.parent.stem - return package_name - - -def get_move_plugins(): - pkg_name = get_package_name() - move_mod = importlib.import_module(f'{pkg_name}.daq_move_plugins') +"""Acceptance tests of the plugin, provided by PyMoDAQ (from version 5.3.1). - plugin_list = [mod for mod in [mod[1] for mod in - pkgutil.iter_modules([str(move_mod.path.parent)])] - if 'daq_move_' in mod] - return plugin_list, move_mod - - -def get_viewer_plugins(dim='0D'): - pkg_name = get_package_name() - viewer_mod = importlib.import_module(f'{pkg_name}.daq_viewer_plugins.plugins_{dim}') - - plugin_list = [mod for mod in [mod[1] for mod in - pkgutil.iter_modules([str(viewer_mod.path.parent)])] - if f'daq_{dim}viewer_' in mod] - return plugin_list, viewer_mod - - -def test_package_name_ok(): - assert 'pymodaq_plugins_' in get_package_name()[0:16] - - -def test_imports(): - pkg_name = get_package_name() - mod = importlib.import_module(pkg_name) - assert hasattr(mod, 'config') - assert hasattr(mod, '__version__') - move_mod = importlib.import_module(f'{pkg_name}', 'daq_move_plugins') - importlib.import_module(f'{pkg_name}', 'daq_viewer_plugins') - importlib.import_module(f'{pkg_name}', 'extensions') - importlib.import_module(f'{pkg_name}', 'models') - importlib.import_module(f'{pkg_name}.daq_viewer_plugins', 'plugins_0D') - importlib.import_module(f'{pkg_name}.daq_viewer_plugins', 'plugins_1D') - importlib.import_module(f'{pkg_name}.daq_viewer_plugins', 'plugins_2D') - importlib.import_module(f'{pkg_name}.daq_viewer_plugins', 'plugins_ND') +They check the package structure, the entry points, the naming of the instrument modules and classes, the mandatory +attributes and methods of the plugin classes, and apply the static rules of PyMoDAQ on the sources +(see https://pymodaq.cnrs.fr/en/latest/developer_folder/instrument_plugins.html#testing-your-plugin). +The unfinished parts of the plugin (TODO comments, placeholders) are listed but do not fail the tests, set +``fail_on = 'todo'`` before a release. Add your own tests, specific to your instruments, in other files. +""" +import importlib.util -def test_move_inst_plugins_name(): - plugin_list, move_mod = get_move_plugins() - for plug in plugin_list: - name = plug.split('daq_move_')[1] - assert hasattr(getattr(move_mod, plug), f'DAQ_Move_{name}') +import pytest +try: + available = importlib.util.find_spec('pymodaq_utils.plugin_testing') is not None +except ModuleNotFoundError: # pymodaq_utils is not installed + available = False +if not available: + pytest.skip('The plugin acceptance checks need PyMoDAQ >= 5.3.1', allow_module_level=True) -def test_move_has_mandatory_methods(): - plugin_list, move_mod = get_move_plugins() - for plug in plugin_list: - name = plug.split('daq_move_')[1] - klass = getattr(getattr(move_mod, plug), f'DAQ_Move_{name}') - for meth in MANDATORY_MOVE_METHODS: - assert hasattr(klass, meth) +from pymodaq_utils.plugin_testing import PluginPackageChecks -@pytest.mark.parametrize('dim', ('0D', '1D', '2D', 'ND')) -def test_viewer_has_mandatory_methods(dim): - plugin_list, mod = get_viewer_plugins(dim) - for plug in plugin_list: - name = plug.split(f'daq_{dim}viewer_')[1] - try: - module = importlib.import_module(f'.{plug}', mod.__package__) - except Exception: - break - klass = getattr(module, f'DAQ_{dim}Viewer_{name}') - for meth in MANDATORY_VIEWER_METHODS: - assert hasattr(klass, meth) +class TestPlugin(PluginPackageChecks): + package_name = 'pymodaq_plugins_standing_wave' + fail_on = 'error' # 'error', 'warning' or 'todo' (also fail on the unfinished parts) + strict_imports = False # True: also fail when a module cannot be imported (missing dependency or driver); the + # modules of an instrument whose driver cannot be installed on the CI runner are then skipped, not failed