Testing experiments is critical to ensure reliable measurements. PLESTY provides mock devices and contract gates to validate experiment behavior without real hardware.

Using mock devices

Create mock device instances for testing:

from plesty.lib.device import BaseDeviceSyncModel


class MockLaser(BaseDeviceSyncModel):
    """Mock laser device for testing."""

    def __init__(self, main=None):
        super().__init__(main=main)
        self._connected = False
        self._power = 0.0

    def connect(self) -> bool:
        self._connected = True
        return True

    def disconnect(self) -> None:
        self._connected = False

    def _write_(self, key: str, value: object) -> None:
        if key == "power":
            self._power = float(value)

    def _query_(self, key: str) -> object:
        if key == "power":
            return self._power
        raise ValueError(f"Unknown key: {key}")

    def identity(self) -> str:
        return "MockLaser"

    def check_errors(self) -> list[str]:
        return []

    def check_operatability(self) -> bool:
        return self._connected

Testing with CompositeDevice

def test_power_sweep():
    # Arrange
    laser = MockLaser()
    laser.connect()
    composite = CompositeDevice(devices={"laser": laser})
    experiment = PowerSweep(composite)

    # Act
    result = experiment.run(current_range=[0.0, 1.0, 2.0])

    # Assert
    assert len(result["measurements"]) == 3
    assert result["measurements"][0]["current"] == 0.0

Gate e1: Experiment Contract

Gate e1 validates that your experiment implements the required contract:

Gate e2: Experiment Persistence

Gate e2 enforces that experiments use save_result() for data persistence, not ad-hoc file writing or database connections.

# Checks:
# - All data persistence goes through save_result
# - No direct file I/O for measurement data
# - No database connections in experiment code

Running experiment tests

# Run all tests including experiment tests
uv run pytest

# Run experiment-specific tests
uv run pytest -k "experiment"

# Run the full check suite (includes e1, e2)
uv run plesty check

Best practices

Next steps