Skip to content
omar edited this page Nov 21, 2022 · 5 revisions

Overview of Dear ImGui Tests/Automation Engine

Foreword

This is a work-in-progress project. It is expected that some API will change over time. See Changelog.

It is expected that updates to imgui and imgui_test_engine are synchronized to similar dates (old versions of imgui_test_engine may not work with newer versions of Dear ImGui, and vice-versa).

Examples

  • app_minimal/ is a simple application showcasing how to integrate the test engine in your project.
  • imgui_test_suite/ is used to test the Dear ImGui library itself. It may be useful as a reference of how to write tests.

An example test

(This test emits its own UI code via the 'GuiFunc' function. When testing your app you may not need the 'GuiFunc' section.)

void RegisterTests(ImGuiTestEngine* e)
{
    ImGuiTest* t = IM_REGISTER_TEST(e, "demo_tests", "test1");
    t->GuiFunc = [](ImGuiTestContext* ctx)
    {
        ImGui::Begin("Test Window", NULL, ImGuiWindowFlags_NoSavedSettings);
        ImGui::Text("Hello, automation world");
        ImGui::Button("Click Me");
        if (ImGui::TreeNode("Node"))
        {
            static bool b = false;
            ImGui::Checkbox("Checkbox", &b);
            ImGui::TreePop();
        }
        ImGui::End();
    };
    t->TestFunc = [](ImGuiTestContext* ctx)
    {
        ctx->SetRef("Test Window");
        ctx->ItemClick("Click Me");
        ctx->ItemOpen("Node"); // Optional as ItemCheck("Node/Checkbox") will also do it automatically
        ctx->ItemCheck("Node/Checkbox");
        ctx->ItemUncheck("Node/Checkbox");
    };
}

See app_minimal_tests.cpp for more basic examples.

How it works

The Test Engine generally attempts to simulate end-user inputs.

It does so by writing to the ImGuiIO structure in ImGui::NewFrame(). Some functions do take the liberty to use internal api to alter state, but the intent is to try to reduce those to a minimum.

Tests may be comprised of a "GuiFunc" and/or "TestFunc". Either are optional.

  • When writing tests for Dear ImGui itself, the tests will often use both "GuiFunc" and "TestFunc".
  • When writing tests for your own application, your tests will generally only use "TestFunc".
  • GuiFunc = run every frame to submit Dear ImGui contents. When testing your own application, you may not need a GuiFunc at all, as you will test the GUI already exposed by your application. The GuiFunc is mainly useful if you need to test adhoc pieces of GUI. The test suite for Dear ImGui uses GuiFuncs a lot but you may never need one yourself.
  • TestFunc = this is the driver code to script interactions. Actions are currently exposed via a C++ API in the ImGuiTestContext class. The TestFunc runs on what is essentially a coroutine. Actions will frequently "yield" the coroutine, returning execution to your main thread. The coroutine will NEVER run in parallel with your main thread: they'll be always waiting each others using a mutex. The coroutine generally only runs a few lines of user code before returning execution to the main thread. Using a coroutine makes writing tests easier.

We can imagine in the future that the ImGuiTestContext API can be formalized as a language agnostic API with a dedicated file format able to store and express tests.

Setting Up

See Setting Up page.