Testing Plugins and Proxies
This page covers testing patterns for custom connection plugins, proxies, and capability interfaces.
Testing a Plugin Directly
Instantiate the plugin with a mock device and call capability methods:
import pytest
from neops_workflow_engine_client import DeviceTypeDto
from my_package.plugins.frr_plugin import FRRPlugin # see examples/device-connections/frr_plugin.py
@pytest.fixture
def frr_device() -> DeviceTypeDto:
return DeviceTypeDto(
id=1,
hostname="frr-rtr-01",
ip="10.0.1.1",
platform="frr",
username="admin",
password="admin",
)
def test_plugin_identity(frr_device):
plugin = FRRPlugin(device=frr_device)
assert plugin.platform == "frr"
assert plugin.connection_type == "ssh"
assert plugin.connection_library == "netmiko"
For integration tests that actually connect, use a remote lab fixture to provide a real device.
Registry Isolation
Plugin tests must not leak registrations into other tests. Use
clear_registry() and get_registry_snapshot() to isolate:
from neops_worker_sdk.connection.registry import (
clear_registry,
get_registry_snapshot,
register_connection_plugin,
)
@pytest.fixture(autouse=True)
def clean_registry():
clear_registry()
yield
clear_registry()
def test_plugin_registers():
@register_connection_plugin()
class TestPlugin(ConnectionPlugin):
platform = "test"
connection_type = "ssh"
connection_library = "mock"
...
snapshot = get_registry_snapshot()
assert "test" in snapshot["plugins"]
assert "ssh" in snapshot["plugins"]["test"]
Warning
Without clear_registry(), plugins registered in one test will be
visible in all subsequent tests. This causes flaky AmbiguousPluginError
failures that are hard to debug.
Testing Custom Capabilities
Verify that a proxy correctly raises NotImplementedForThisPlatform when
the resolved plugin does not implement a method:
from neops_worker_sdk.connection.exceptions import NotImplementedForThisPlatform
def test_unimplemented_capability_raises(frr_device):
# Assume MinimalPlugin only implements DeviceInfoCapability
proxy = FullProxy.get_connection(
frr_device, "ssh", "netmiko"
)
try:
with pytest.raises(NotImplementedForThisPlatform) as exc_info:
proxy.get_inventory() # not implemented
assert exc_info.value.context.method_name == "get_inventory"
assert exc_info.value.context.platform == "frr"
finally:
proxy.close()
Integration: Proxy + Plugin Together
Test the full stack — plugin resolution, connection, and capability calls — against a mock or real device:
@pytest.mark.asyncio
async def test_proxy_resolves_correct_plugin(frr_device):
with FRRProxy.connect(
frr_device, "ssh", "netmiko"
) as proxy:
version = proxy.get_version()
assert version["vendor"] is not None
For real-device tests, use @fb_test_case_with_lab with a topology that
includes the target platform.
Asserting Registration State
get_registry_snapshot() returns the full registry for inspection:
| Key | Type | Content |
|---|---|---|
plugins |
dict[platform, dict[type, dict[library, class]]] |
All registered plugins |
platform_defaults |
dict[platform, class] |
Platform-level defaults |
connection_type_defaults |
dict[(platform, type), class] |
Type-level defaults |
Use this to verify that your plugin package registers exactly the plugins you expect, and no more.