Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 21 additions & 106 deletions tests/test_plugin_package_structure.py
Original file line number Diff line number Diff line change
@@ -1,113 +1,28 @@
# -*- coding: utf-8 -*-
"""
Created the 17/10/2023

@author: Sebastien Weber
"""
import pytest
from pathlib import Path
import importlib
import pkgutil
from collections.abc import Iterable

from pymodaq_data import Q_, Unit


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()
try:
move_mod = importlib.import_module(f'{pkg_name}.daq_move_plugins')
plugin_list = [mod for mod in [mod[1] for mod in
pkgutil.iter_modules([str(move_mod.path.parent)])]
if 'daq_move_' in mod]
except ModuleNotFoundError:
plugin_list = []
move_mod = None
return plugin_list, move_mod
"""Acceptance tests of the plugin, provided by PyMoDAQ (from version 5.3.1).

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).

def get_viewer_plugins(dim='0D'):
pkg_name = get_package_name()
try:
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]
except ModuleNotFoundError:
plugin_list = []
viewer_mod = None
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')


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}')

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_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)
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_correct_units():
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}')
if not isinstance(klass._controller_units, list):
units = [klass._controller_units]
else:
units = klass._controller_units
for unit in units:
Unit(unit) # check if the unit is known from pint
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_piezoconcept'
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
Loading