Quality

rbterm tests itself

A terminal emulator is only as good as the thousand escape sequences it renders correctly. rbterm proves it: an extensive, self-hosted test framework drives a real rbterm through its own scripting API, reads the screen back, and pixel-verifies screenshots — fully automated, headless, and ruthless.

40+
assertions
15
categories
px
verified shots
0
windows shown

There are no mocks and no stubs. Every check spins up the actual terminal binary, feeds bytes into a pane exactly as a shell would, and asserts on what the VT parser, grid, and renderer actually produced. If a colour is off by a shade or the cursor lands one column wrong, the suite fails — loudly.

Self-hosted by designThe terminal is both the thing under test and the test harness.

rbterm ships a scripting API that can drive a running instance and read it back. The test framework is built directly on it: send-text to feed escape sequences into a pane, get-text / get-text --ansi to read the rendered screen (with full colour and attributes), ls and get-colors to inspect structure and palette, and screenshot to capture pixels. One real pipeline, asserted end to end.

def test_truecolor(rc):
    rc.run_cmd("clear")
    rc.emit(r"\033[38;2;10;200;30mTRUE\033[0m\n")   # 24-bit green
    ansi = rc.get_text(ansi=True)                  # read the screen, with SGR
    i = ansi.rfind("TRUE")
    assert "38;2;10;200;30" in ansi[i-28:i]    # confirm the colour rendered
    # ok test_truecolor

What it exercisesThe hard parts of a terminal — not just "hello world".

VT parser

Cursor addressing (CUP/HVP, relative moves, save&restore), erase (ED/EL/ECH), delete/insert, scroll regions & reverse index, auto-wrap on/off, carriage-return overwrite.

Colour & attributes

Bold, italic, underline, reverse, strike; 16-colour, 256-colour, and 24-bit truecolour; default reset — verified by reading back the actual SGR stream.

Unicode

Accented text, Greek, symbols, and double-width CJK round-tripped byte-for-byte through input and output.

Palette

OSC 4 palette updates and live recolouring, confirmed against a colour query.

Modes & graphics

Alternate screen buffer isolation, DEC special-graphics box drawing, window-title sequences.

Layout

Opening and closing tabs, nested splits, stable pane identity, font size and spacing.

Targeting

The boolean match engine — and/or/not over id, title, cwd, pid, and user variables.

Input & process

Synthesised key chords, signal delivery to pane processes, and captured command output.

Pixel-verified screenshots"It looks right" isn't good enough — we read the pixels.

The framework captures PNGs of rendered panes and decodes them with a dependency-free PNG reader, then asserts on actual pixel values: a background fill matches the colour that was set, white text produces bright pixels where glyphs land, colour bars contain the expected distinct hues. The screenshots below were produced by the framework itself — captured headless, with no window ever shown.

rbterm rendering: bold/italic/underline/reverse/strike, 16-colour dots, a 24-bit truecolour gradient, box drawing, and Unicode (café, 世界, Ω≠∞)
Attributes, truecolour, box drawing and Unicode — one rendered frame, captured by the test framework
rbterm rendering the full 256-colour cube as background blocks
The full 256-colour cube, rendered and screenshotted headlessly

Headless by defaultTests never steal your screen, focus, or keystrokes.

rbterm can run with a hidden window. The GPU context and offscreen render targets still work, so remote control and screenshot render in full — but nothing appears on your desktop, nothing takes focus, and a stray keypress can never land in a test session. That makes the suite safe to run any time, including in continuous integration (under a virtual display on Linux).

It catches real bugsAlready earning its keep.

This isn't a checkbox suite. On its very first full run it surfaced — and drove fixes for — two genuine rendering bugs: non-ASCII text being double-encoded across the control channel, and an X11 rgb: colour specification being scaled wrong so every channel came out a quarter of its intended brightness. Both are fixed, both now have regression coverage.

# run it
make test      # fast sanity subset
make stress    # the full suite + pixel-verified screenshots

40 passed, 0 failed, of 40