Run the full Pharo SUnit test suite headless, with a fake GUI that lets you click menus, press buttons, and take screenshots — all without a real display.
Works on any Spur VM: official Pharo VM (Cog JIT), interpreter VMs, Mac Catalyst, etc. Tested on Pharo 13 and Pharo 14.
setup_fake_gui.st — Creates a virtual Morphic display (1024x768
Form, WorldMorph, MorphicUIManager, UI process). Installs the FakeGUI
helper class for programmatic interaction:
FakeGUI clickMenuItemNamed: 'Save'.
FakeGUI clickButtonNamed: 'OK' in: aPresenter.
FakeGUI allMorphsNamed: 'Tools'.
FakeGUI findWidgetOfType: SpButtonMorph in: aPresenter.
FakeGUI openPresenter: aPresenter.
FakeGUI screenshot. "returns Display Form"
FakeGUI screenshotToFile: '/tmp/screenshot.png'. "saves PNG"
FakeGUI screenshotOf: aMorph toFile: '/tmp/m.png'. "captures one morph"
Also patches Morph>>activate/passivate to skip nil submorphs, which
fixes ~350 "receiver of activate is nil" errors that occur headless.
run_sunit_tests.st — Batch SUnit runner that discovers and runs every TestCase subclass in the image. Features:
- Per-test watchdog timeouts (Delay-based, configurable scale factor)
- Bail-out after consecutive timeouts per class
- Skip list for known hangers (Epicea file watchers, Athens/Cairo, etc.)
- Delay scheduler health checks between classes
- Auto-runs on image startup via SessionManager hook
- Tab-delimited detail log with pass/fail/error/skip/timeout per test
- Runs inside TestExecutionEnvironment for proper test isolation
- Trait-modifying tests sorted last to avoid corrupting shared state
# Download a fresh Pharo image
curl -sL https://get.pharo.org/64/140 | bash
# Inject the scripts (--save bakes them into the image)
./pharo --headless Pharo.image eval --save \
"'setup_fake_gui.st' asFileReference fileIn. \
'run_sunit_tests.st' asFileReference fileIn"
# Run — tests auto-execute on startup, results to /tmp
./pharo --headless Pharo.image
# Check results
cat /tmp/sunit_test_results.txt # summary
cat /tmp/sunit_test_detail.txt # per-test detail
If you just want the fake GUI for your own scripts (interactive testing,
CI screenshots, etc.), only inject setup_fake_gui.st:
./pharo --headless Pharo.image eval --save \
"'setup_fake_gui.st' asFileReference fileIn"
Then in your own scripts:
./pharo --headless Pharo.image eval "
FakeGUI openPresenter: SpSystemBrowser new.
FakeGUI screenshotToFile: '/tmp/browser.png'.
Smalltalk exitSuccess"
Write class names to /tmp/sunit_class_names.txt (one per line):
echo 'SmallIntegerTest
FloatTest
ArrayTest' > /tmp/sunit_class_names.txt
./pharo --headless Pharo.image
Or use batch ranges in /tmp/sunit_batch.txt:
echo '1 50' > /tmp/sunit_batch.txt
The default timeout scale is 5x (50 seconds per test). Interpreter VMs without JIT compilation are slower, so increase the scale:
echo '10' > /tmp/sunit_timeout_scale.txt
Without setup_fake_gui.st, ~350 Spec presenter tests fail with
"receiver of activate is nil".
With it: 1054/1113 pass (94.6%) across 64 Spec GUI test classes. The remaining failures are font metrics (FreeType not initialized headless) and timing-sensitive tests.
The fake GUI creates a real Morphic world that thinks it has a display:
- A 1024x768 depth-32
Formis installed asDisplay - A
WorldMorphis created and set asWorld/ActiveWorld MorphicUIManagerreplacesNonInteractiveUIManager- The UI process starts the
MorphicRenderLoop
From there, all standard Morphic operations work: opening windows,
building Spec presenters, rendering morphs, handling events. The
FakeGUI class sends synthetic MouseButtonEvents to simulate clicks
and steps the world loop to process deferred actions.
Screenshots work because morphs render to the in-memory Display Form.
writePNGFileNamed: saves it as a standard PNG.
These scripts have no VM-specific dependencies. They were developed for iospharo (a Pharo VM for iPad) but work identically on the official Pharo VM. Any VM that runs a standard Pharo 13+ Spur image will work.
For VMs without a pharo command-line launcher, inject the scripts
using whatever mechanism your VM provides, then launch the image. The
test runner registers a SessionManager startup hook at priority 90 and
runs automatically on image resume.
/tmp/sunit_test_results.txt Summary with pass/fail/error/skip counts
/tmp/sunit_test_detail.txt Tab-delimited: run# class selector result
/tmp/sunit_run_number.txt Auto-incrementing run counter
/tmp/sunit_run_completed.txt Marker to prevent re-run on image resume
Other repos in this collection:
- smalltalk80-2026 — C++17 virtual machine for Smalltalk-80 on macOS, Mac Catalyst, Linux, and Windows. It boots the 1983 Xerox virtual image to the desktop.
- iospharo — Virtual machine for Pharo Smalltalk on iOS and macOS. The C++ interpreter runs Pharo 13 and Pharo 14 images without a just-in-time compiler, and it uses low-bit oop encoding to work with ASLR.
- validate_smalltalk_image — Standalone validator and export tool for Spur-format Smalltalk images. It checks the heap, and it writes SHA-256 manifests and reference graphs.
- soogle — Search engine for Smalltalk source code. It indexes packages and labels each one with its dialect, such as Pharo, Squeak, or GemStone.
- claude-skills — Collection of open source skills for Claude Code. Each skill is a Markdown file in
.claude/skills/that holds reusable knowledge and algorithms.
MIT. See LICENSE file.