Live demo — data resets daily at 03:00 UTC. Nothing you enter is saved. Server UI →

product: maestro audience: test-developer authority: normative

Design Principle: One YAML Step = One Method/Function

Writing one large method that performs connect, setup, all measurements, and teardown in a single call IS an anti-pattern. It defeats the step-based YAML model.

Why it matters

Aspect One method per step ✅ Everything in one method ❌
Retry granularity Retry only the failed step Must re-run the entire sequence
Skip/disable during dev Skip any step via enabled: false or precondition All or nothing
Traceability Each measurement has its own named step with verdict One opaque result
Abort safety Teardown steps run via run_on_abort: true If the method throws, cleanup may not run
Local MSTest coverage Each method tested independently Must run the whole sequence

Anti-pattern

// Don't — one method doing connect, scan, test, and disconnect
public static void RunFullTest(string host, string serialNumber)
{
    var client = new InstrumentClient(host);
    client.Reset();
    // ... scan I2C ...
    // ... test interconnect ...
    // ... program EEPROM ...
    client.Dispose();
}

Correct pattern

// Each method maps to exactly one YAML step
public static void Connect(string host) { ... }
public static void LoadModule() { ... }
public static List<MeasurementPointBase> ScanI2C() { ... }
public static List<MeasurementPointBase> TestInterconnect() { ... }
public static void ProgramDevice(string productId, string revision, string serialNumber) { ... }
public static void Disconnect() { ... }
# Same principle in Python
def connect(host: str) -> None: ...
def load_module() -> None: ...
def scan_i2c() -> dict: ...
def test_interconnect() -> dict: ...
def program_device(product_id: str, revision: str, serial_number: str) -> None: ...
def disconnect() -> None: ...

Rule of thumb for deciding where to split

  • If you would give an operation its own row in a test specification, it gets its own method and its own YAML step.
  • If an operation can fail independently from the others around it, it gets its own step so its verdict is recorded separately.
  • Setup operations (power on, connect, load firmware) ARE always individual steps with post_execution_action: terminate-on-fail.
  • Cleanup operations (power off, disconnect) ARE always individual steps with run_on_abort: true.
An unhandled error has occurred. Reload 🗙

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.