ImGui Test Engine is the official testing and automation framework for Dear ImGui. It enables automated UI testing, screenshot capture, and regression testing.
Quick Start¶
from imgui_bundle import imgui, hello_imgui
my_test: imgui.test_engine.Test
def my_register_tests():
global my_test
engine = hello_imgui.get_imgui_test_engine()
my_test = imgui.test_engine.register_test(engine, "My Tests", "Click Button")
def test_func(ctx: imgui.test_engine.TestContext):
ctx.item_click("**/My Button")
my_test.test_func = test_func
def gui():
test_engine = hello_imgui.get_imgui_test_engine()
if imgui.button("My Button"):
print("Clicked!")
if imgui.button("Run Tests"):
imgui.test_engine.queue_test(test_engine, my_test)
params = hello_imgui.RunnerParams()
params.use_imgui_test_engine = True
params.callbacks.register_tests = my_register_tests
params.callbacks.show_gui = gui
hello_imgui.run(params)#include "hello_imgui/hello_imgui.h"
#include "imgui_test_engine/imgui_te_engine.h"
#include "imgui_test_engine/imgui_te_context.h"
ImGuiTest * myTest = nullptr;
void RegisterTests() {
ImGuiTestEngine* engine = HelloImGui::GetImGuiTestEngine();
myTest = ImGuiTestEngine_RegisterTest(engine, "My Tests", "Click Button");
myTest->TestFunc = [](ImGuiTestContext* ctx) {
ctx->ItemClick("**/My Button");
};
}
void Gui() {
auto testEngine = HelloImGui::GetImGuiTestEngine();
if (ImGui::Button("My Button"))
printf("Clicked!\n");
if (ImGui::Button("Run Tests"))
ImGuiTestEngine_QueueTest(testEngine, myTest);
}
int main() {
HelloImGui::RunnerParams params;
params.useImGuiTestEngine = true;
params.callbacks.RegisterTests = RegisterTests;
params.callbacks.ShowGui = Gui;
HelloImGui::Run(params);
return 0;
}Full demo¶
For more complete examples, see the test engine demo from the interactive explorer:
Named References¶
Test Engine uses “named references” to find widgets. The syntax uses path separators:
| Pattern | Meaning |
|---|---|
"Button" | Widget named “Button” in current reference |
"**/Button" | Search for “Button” anywhere in children |
"//Window/Button" | Absolute path from root |
"$FOCUSED" | Currently focused window |
ctx.set_ref("My Window") # Set current reference
ctx.item_click("**/Save") # Find "Save" anywhere in window
ctx.item_click("//Dialog/OK") # Absolute path to OK buttonCommon Actions¶
# Click items
ctx.item_click("**/Button")
ctx.item_double_click("**/Item")
# Input text
ctx.item_input("**/Name", "John Doe")
# Check/uncheck
ctx.item_check("**/Enable")
ctx.item_uncheck("**/Disable")
# Open/close tree nodes
ctx.item_open("**/Settings")
ctx.item_close("**/Settings")
ctx.item_open_all("**/Tree")
# Screenshots
ctx.capture_screenshot_window("Window Name")
# Keyboard input
ctx.key_press(imgui.Key.enter)
ctx.key_chars("Hello")Assertions¶
Use the CHECK function to verify conditions:
from imgui_bundle.imgui.test_engine_checks import CHECK
def test_func(ctx: imgui.test_engine.TestContext):
ctx.item_click("**/Increment")
CHECK(counter == 1) # Verify counter was incrementedCustom Test GUI¶
Tests can display their own GUI:
my_test = imgui.test_engine.register_test(engine, "Category", "Test Name")
def test_gui_func(ctx: imgui.test_engine.TestContext):
imgui.text("Custom test controls here")
if imgui.button("Do Something"):
# Custom action
pass
my_test.gui_func = test_gui_funcDriving a GUI and capturing screenshots — immapp.testing¶
ImGui Bundle ships a small testing module that combines the test engine
with screenshot capture. Use it when you want to script an interaction
(click, type, expand a header) and grab a PNG at chosen moments: automated tests,
documentation pictures. It is also how an AI agent sees and drives the app it writes, with
nobody at the mouse: the bundle’s screenshot skills (.claude/skills/) are built on it.
immapp.testing.run(gui, test_fn, ...)— Python: runs the GUI and drives it withtest_fn(ctx); exits once the test finishes (override withexit_after_test=False). An app with its own params:run(test_function=test_fn, runner_params=params, add_ons_params=add_ons).immapp.testing.capture(ctx, path, window=None, flags=0)— Python: write a PNG from inside a test. Captures the full framebuffer, or a single window ifwindow="My Window".immapp.testing.capture_final_frame(gui, path, ...)— Python one-shot: run the GUI for a few frames, save the final frame. No test engine.ImmApp::Testing::Capture(ctx, path, {window, flags})— C++ equivalent ofcapture, fromimmapp/testing.h.ImmApp::Testing::CaptureFinalFrame(guiFn, path, opts)— C++ one-shot.
Example:
from imgui_bundle import imgui
from imgui_bundle.immapp import testing
def gui():
imgui.button("Click me")
def my_test(ctx: imgui.test_engine.TestContext):
testing.capture(ctx, "/tmp/00_initial.png")
ctx.item_click("//**/Click me")
testing.capture(ctx, "/tmp/01_after_click.png")
testing.run(gui, my_test, window_size=(600, 400))See the full demo in
demo_immapp_testing.py
and
demo_immapp_testing.cpp.
Running Tests¶
When test engine is enabled:
A “Test Engine” window appears
Click tests to run them
Watch as actions are automated
Check results (green = pass, red = fail)
In the browser (Pyodide)¶
The test engine works in the browser since v1.93, with the same API. Its coroutine, a thread on the desktop, is a WebAssembly stack switch there (JSPI), which needs Chrome 137, Firefox 153 or Safari 27. In an older browser, the app runs without the engine: use_imgui_test_engine is turned off, get_imgui_test_engine() returns None, and a message says so on stderr.
immapp.testing.run() cannot block in the browser: it returns at once, the test runs in the frames that follow, the app stays open after it, and the result is printed when the test ends (stderr on failure). The screenshots go to Pyodide’s virtual file system, and a “Captures” window shows them when the test ends: click one to enlarge it, or download it.
While the engine runs, Python’s automatic garbage collection is replaced by explicit collections at each frame (a workaround for a Pyodide bug with suspended stacks, pyodide#6464): a test that calls gc.enable() reopens it.
Documentation & Resources¶
Test Engine Wiki - Official documentation
Named References - Path syntax reference