Skip to content

Repository files navigation

Noktra Sequencer

Write a test sequence in YAML. Run it against real hardware. Get a report you can hand to someone.

A small, offline-first alternative to the big test-executive suites. You describe a sequence of steps in a text file — talk to a serial instrument, read a Modbus register, send a UDP frame, ask the operator — and each step is judged against a rule you state. The result is a self-contained HTML report and a CSV, produced deterministically: the same measurements always produce the same verdicts.

Built for closed networks. No cloud, no telemetry, no account, no network access of any kind beyond the instruments you point it at.

The sequencer after a passing run


Contents


Why

Bench testing usually falls into one of two holes. Either it lives in a spreadsheet and a pair of hands — which does not survive the person leaving — or it needs a commercial test executive that costs more than the project. This sits between them: a sequence is a text file you keep in version control, and running it produces a document you can put in a report pack.

Three things it takes seriously:

  • Judgement is deterministic. Pass and fail come from a pure function of (rule, measurement). No clock, no I/O, no state. Two runs over the same readings cannot disagree.
  • A skipped step is not a pass. If a step never ran, the run failed. Reporting an unknown as a pass is the exact failure this kind of tool exists to prevent.
  • Protocol details are cited, not guessed. Modbus constants and frame layouts come from spec/modbus.md, which names the published documents they were taken from. Anything not on that page is unimplemented and says so, rather than being improvised.

Install

Windows — download NoktraSequencer.exe from the latest release. It is self-contained: no .NET runtime to install, nothing to unpack. Double-click it.

macOS and Linuxbuild from source. One command.


Five-minute tour

  1. Start the application and press Open sequence…, or pass a file on the command line:

    NoktraSequencer.exe examples\psu-acceptance.yaml
    

    Add --run to start it immediately — useful for a desktop shortcut to a routine check.

  2. The left panel shows what was loaded; the middle lists every step before anything has run, so you can see what is coming as well as what has happened.

  3. Press Run. Steps light up as they execute, with the measurement, the rule it was judged against, and the verdict.

  4. Press Save report… to write an HTML and a CSV report side by side.

Two sequences in examples/ run anywhere with no hardware attached:

File What it shows
psu-acceptance.yaml A passing run: limits, tolerance, a regex that pulls a serial number out of an instrument reply
failure-handling.yaml A failing run: abort, skip, and teardown still running
hardware-instrument.yaml A real bench sequence — SCPI over serial plus Modbus RTU. Needs hardware

A failing run: the aborting step, the skipped step, and teardown running anyway


Writing a sequence

A sequence is a YAML file. There is no editor built in, on purpose — you already have one you like, and the file is small enough to read in full.

name: Power supply acceptance
description: 5 V rail, ripple and load regulation on a bench supply

variables:
  serial: PSU-0042
  nominal: "5.0"

settings:
  defaultTimeoutMs: 2000

setup:
  - name: warmUp
    action: wait
    params: { ms: 300 }

steps:
  - name: railVoltage
    action: const
    description: No-load output on the 5 V rail
    params:
      value: "5.02"
    verdict:
      type: limits
      min: 4.75
      max: 5.25

  - name: loadRegulation
    action: const
    params:
      value: "4.98"
    verdict:
      type: tolerance
      expected: ${nominal}
      tolerance: 0.1

teardown:
  - name: outputOff
    action: const
    params:
      value: "off"
    verdict:
      type: equals
      expected: "off"

setup runs first, then steps, then teardown. Teardown runs whatever happened before it — leaving a supply at 30 V because the measurement before it failed is worse than the failed measurement.

The full schema, including every default, is in spec/sequence-schema.md.

Every mistake that can be caught before the run is caught at load time — an unknown action, a rule missing its bounds, a ${...} pointing at a step that runs later — and all of them are reported at once, with line numbers, instead of one per attempt.


Actions

Action What it does Key parameters
const Yields a fixed value — how you exercise a sequence without hardware value
wait Waits ms
prompt Asks the operator to confirm, or to type in a reading message, expectText
serial-write Writes text or hex to a serial port port, baud, data, terminator, encoding
serial-read Reads until a terminator or a byte count port, until, maxBytes, encoding
udp-send Sends one datagram host, port, data, localPort
udp-recv Waits for one datagram port, from
modbus-read Reads coils, discrete inputs, holding or input registers transport, port/host, unit, type, address, count
modbus-write Writes coils or holding registers as above, plus value or values
shell Runs a command and captures its output command, args, expectExitCode

shell refuses to run unless the file sets settings.allowShell: true. A sequence is a document that gets e-mailed around, and one arriving from outside should not be able to run commands because somebody pressed Run.

Modbus speaks both RTU (transport: rtu, over a serial port) and TCP (transport: tcp). Ports and sockets are opened once and shared for the whole run, so a write and the read that answers it are the same connection.


Verdicts

Type Passes when Keys
limits the measurement is inside the window, both bounds inclusive min, max (at least one)
tolerance |measured − expected| ≤ tolerance expected, tolerance
equals the text matches expected, trim (default true)
regex the pattern matches — and capture group 1 becomes the step's value pattern

The regex capture is what makes chatty instruments usable. Ask a meter for a reading, get back NOKTRA,PSU,PSU-0042,1.4\r\n, pull the field you want out of it, and judge that in the next step:

  - name: identity
    action: serial-read
    params: { port: COM3, until: "\n" }
    verdict:
      type: regex
      pattern: "NOKTRA,PSU,([A-Z0-9-]+)"

  - name: checkSerial
    action: const
    params:
      value: ${identity.value}     # -> "PSU-0042"
    verdict:
      type: equals
      expected: ${serial}

Numbers are parsed the same way on every machine, so a sequence reaches the same verdict in Seoul and in Seattle. 4,9 is text, not a number.


Variables

  • ${name} — a value declared in variables:. Usable in step parameters and in verdicts.
  • ${step.field} — a result of a step that ran earlier, where field is one of value, raw, elapsedMs, status.

value is what the verdict produced (the regex capture, if there was one); raw is exactly what the equipment sent, before anything touched it.

A ${step.field} cannot be used inside a verdict — a rule that changes shape mid-run is not a rule. Compare the result in a following step instead, as above.


Failure handling

Each step chooses what its failure means:

  • onFailure: continue (default) — record it and carry on.
  • onFailure: abort — stop; every remaining step in the body is reported as skipped, and teardown still runs.

retry: n gives a step n further attempts before it is called failed.

A run passes only when nothing failed and nothing was skipped.


Reports

HTML — one self-contained file. Inline CSS, a logo embedded as a data URI if you set settings.reportLogo, and no external requests of any kind. A report opened in five years on a machine with no network renders exactly as it did on the bench.

CSV — RFC 4180, written with a UTF-8 byte order mark so Excel reads it correctly.

Both are deterministic: same run, byte-identical output. That is what makes two archived reports comparable.

The HTML report


Building from source

Requires the .NET 8 SDK.

git clone https://github.com/Kim-Hakseong/NOKTRA-test-sequencer.git
cd NOKTRA-test-sequencer

dotnet test                                   # 226 tests
dotnet run --project src/Sq.App -- examples/psu-acceptance.yaml

To produce the Windows executable:

dotnet publish src/Sq.App -c Release -r win-x64 --self-contained true \
  -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true \
  -p:EnableCompressionInSingleFile=true

Swap win-x64 for osx-arm64 or linux-x64 to build for those instead.


Design notes

src/Sq.Core/     schema and loader, verdicts, runner, actions, transports, Modbus, reports (no UI)
src/Sq.App/      Avalonia desktop application
tests/           226 tests, none of which sleep
spec/            the sequence schema, and the Modbus constants with their sources
examples/        sequences that run

A few decisions worth knowing about if you read the code:

  • The verdict engine is a pure function. It has no clock and no I/O, so replaying measurements cannot produce a different answer.
  • All time flows through one interface. Tests drive a virtual clock, so a step that overruns a 200 ms timeout is proved to fail at exactly 200 ms without a real millisecond passing.
  • YAML is parsed by a small purpose-built parser. It accepts the subset a sequence file needs and makes everything else a hard error with a line number. A file that parses differently than its author expected is a wrong test result.
  • Transports are polled, not blocking. A blocking socket read would take the timeout decision away from the runner and put it somewhere a test cannot reach.
  • The Modbus test slave answers real frames, so protocol tests check the bytes on the wire rather than an agreement between two halves of one assumption.

Licence

MIT — see LICENSE.

Noktra — verification tools that work in the dark (offline-first).

About

Write a test sequence in YAML, run it against real hardware, get a report you can hand to someone. Offline-first desktop test executive — deterministic verdicts, self-contained HTML/CSV reports, serial · UDP · Modbus.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages