Check out our latest project ✨ OpenChapter.io: free ebooks the way its meant to be πŸ“–

GodotE2E

An asset by LIUXIN
The page banner background of a mountain and forest
GodotE2E hero image

Quick Information

0 ratings
GodotE2E icon image
LIUXIN
GodotE2E

Out-of-process E2E testing tool for Godot.Test your Godot games from Python using pytest. The addon runs a TCP automation server as an Autoload β€” completely dormant unless launched with the --e2e flag.Features:- Synchronous Python API (no async/await needed)- Input simulation: keyboard, mouse, named actions- Node operations: get/set properties, call methods, group lookup- Frame synchronization: wait for process/physics frames or game time- Scene management: change scene, reload scene- Screenshot capture with pytest failure integration- Works with standard Godot 4.x binaries, no engine modificationsInstall the Python package: pip install godot-e2eDocumentation: https://github.com/RandallLiuXin/godot-e2e/tree/main/docs

Supported Engine Version
4.0
Version String
1.0.0
License Version
Apache-2.0
Support Level
community
Modified Date
10 hours ago
Git URL
Issue URL

English | δΈ­ζ–‡

godot-e2e

README CI README PyPI README Python README Godot README License

Out-of-process E2E testing tool for Godot


Quick Start

1. Install the addon

Copy addons/godot_e2e/ into your Godot project's addons/ directory. Add AutomationServer as an Autoload in your project settings:

  • Path: *res://addons/godot_e2e/automation_server.gd
  • Name: AutomationServer

The * prefix means the script is used directly (not a scene). The server is completely dormant unless the game is launched with the --e2e flag, so it has no effect in production builds.

2. Install the Python package

pip install godot-e2e

Or install from source:

pip install -e .

3. Write a test

from godot_e2e import GodotE2E

def test_player_moves(game):
    initial_x = game.get_property("/root/Main/Player", "position:x")
    game.press_action("move_right")
    game.wait_physics_frames(10)
    new_x = game.get_property("/root/Main/Player", "position:x")
    assert new_x > initial_x

Run:

pytest tests/ -v

Features

  • Out-of-process β€” game runs in a separate process; crashes are isolated and timeouts are safe
  • No engine modifications β€” works with standard Godot 4.x binaries
  • Synchronous Python API β€” no async/await required in test code
  • Input simulation β€” keyboard, mouse clicks, named actions
  • Node operations β€” get/set properties, call methods, group lookup, node existence checks
  • Frame synchronization β€” wait for process frames, physics frames, or game time
  • Scene management β€” change scene, reload scene
  • Screenshot capture β€” manual or automatic on test failure (pytest integration)
  • pytest fixtures β€” built-in fixtures with configurable test isolation strategies

How It Works

Two processes communicate over a local TCP connection:

  1. Python (pytest) β€” sends JSON-encoded commands and waits for responses
  2. Godot (AutomationServer) β€” an Autoload that listens on a TCP port, executes commands on the main thread, and sends back results

The AutomationServer only opens its socket when the game is started with --e2e (and optionally --e2e-port <port>). In normal play or exported builds without that flag, the autoload does nothing.

pytest ──── TCP (localhost) ──── AutomationServer (Godot Autoload)
  sends: {"cmd": "get_property", "path": "/root/Main/Player", "prop": "position:x"}
  gets:  {"ok": true, "value": 400.0}

pytest Fixtures

Three isolation strategies are available depending on your needs.

Strategy 1: reload_scene (default, fast)

Reloads the current scene between each test. Cheap and usually sufficient.

# conftest.py
import pytest
from godot_e2e import GodotE2E

GODOT_PROJECT = "/path/to/your/project"

@pytest.fixture(scope="module")
def _game_process():
    with GodotE2E.launch(GODOT_PROJECT) as game:
        game.wait_for_node("/root/Main", timeout=10.0)
        yield game

@pytest.fixture(scope="function")
def game(_game_process):
    _game_process.reload_scene()
    _game_process.wait_for_node("/root/Main", timeout=5.0)
    yield _game_process

Strategy 2: game_fresh (strongest isolation)

Launches a brand new Godot process for each test. Slowest but fully isolated.

@pytest.fixture(scope="function")
def game_fresh():
    with GodotE2E.launch(GODOT_PROJECT) as game:
        game.wait_for_node("/root/Main", timeout=10.0)
        yield game

Strategy 3: Shared session (fastest)

One process for the entire test session. Use when tests are carefully ordered and do not share mutable state.

@pytest.fixture(scope="session")
def game_session():
    with GodotE2E.launch(GODOT_PROJECT) as game:
        game.wait_for_node("/root/Main", timeout=10.0)
        yield game

CI Configuration

Linux (GitHub Actions, headless via Xvfb)

- name: Install Godot
  run: |
    wget -q https://github.com/godotengine/godot-builds/releases/download/4.4-stable/Godot_v4.4-stable_linux.x86_64.zip
    unzip -q Godot_v4.4-stable_linux.x86_64.zip
    sudo mv Godot_v4.4-stable_linux.x86_64 /usr/local/bin/godot

- name: Run E2E tests
  run: |
    pip install -e .
    xvfb-run --auto-servernum pytest tests/e2e/ -v

Windows (GitHub Actions)

- name: Install Godot
  run: |
    Invoke-WebRequest -Uri "https://github.com/godotengine/godot-builds/releases/download/4.4-stable/Godot_v4.4-stable_win64.exe.zip" -OutFile godot.zip
    Expand-Archive godot.zip -DestinationPath C:\godot
  shell: pwsh

- name: Run E2E tests
  run: |
    pip install -e .
    pytest tests/e2e/ -v
  env:
    GODOT_BIN: C:\godot\Godot_v4.4-stable_win64.exe

macOS (GitHub Actions)

- name: Install Godot
  run: |
    wget -q https://github.com/godotengine/godot-builds/releases/download/4.4-stable/Godot_v4.4-stable_macos.universal.zip
    unzip -q Godot_v4.4-stable_macos.universal.zip
    sudo mv "Godot.app" /Applications/Godot.app

- name: Run E2E tests
  run: |
    pip install -e .
    pytest tests/e2e/ -v
  env:
    GODOT_BIN: /Applications/Godot.app/Contents/MacOS/Godot

Set GODOT_BIN to override the default Godot executable path. The default search order is: godot4, godot, then platform-specific standard locations.


API Reference

Launch / Lifecycle

Method Description
GodotE2E.launch(project_path, **kwargs) Context manager. Launches Godot and returns a connected GodotE2E instance.
game.close() Terminate the Godot process and close the connection.

Node Operations

Method Description
game.node_exists(path) Returns True if the node at path exists in the scene tree.
game.wait_for_node(path, timeout=5.0) Blocks until the node exists or timeout is reached.
game.get_property(path, prop) Get a property value. Supports dotted paths like "position:x".
game.set_property(path, prop, value) Set a property value on a node.
game.call_method(path, method, *args) Call a method on a node and return the result.
game.find_by_group(group) Return a list of node paths for all nodes in the given group.

Input Simulation

Method Description
game.press_action(action) Press and immediately release a named input action.
game.input_action(action, pressed) Set a named input action pressed state.
game.key_press(scancode) Press and release a key by scancode.
game.mouse_click(x, y, button=1) Click a mouse button at the given screen coordinates.

Frame Synchronization

Method Description
game.wait_frames(n) Wait for n process (_process) frames to complete.
game.wait_physics_frames(n) Wait for n physics (_physics_process) frames to complete.
game.wait_seconds(t) Wait for t in-game seconds (affected by Engine.time_scale).

Scene Management

Method Description
game.change_scene(scene_path) Change to a scene by res:// path.
game.reload_scene() Reload the current scene.

Diagnostics

Method Description
game.screenshot(path=None) Capture a screenshot. Returns PNG bytes; saves to path if given.

Examples

Example Description
minimal Simplest setup β€” node checks, property reading, method calls (3 tests)
platformer Player movement, scoring, groups, scene reload (5 tests)
ui_testing Button clicks, label verification, scene navigation (5 tests)

Run any example:

cd examples/minimal
pytest tests/e2e/ -v

License

Apache 2.0. See LICENSE.

Out-of-process E2E testing tool for Godot.

Test your Godot games from Python using pytest. The addon runs a TCP automation server as an Autoload β€” completely dormant unless launched with the --e2e flag.

Features:
- Synchronous Python API (no async/await needed)
- Input simulation: keyboard, mouse, named actions
- Node operations: get/set properties, call methods, group lookup
- Frame synchronization: wait for process/physics frames or game time
- Scene management: change scene, reload scene
- Screenshot capture with pytest failure integration
- Works with standard Godot 4.x binaries, no engine modifications

Install the Python package: pip install godot-e2e

Documentation: https://github.com/RandallLiuXin/godot-e2e/tree/main/docs

Reviews

0 ratings

Your Rating

Headline must be at least 3 characters but not more than 50
Review must be at least 5 characters but not more than 500
Please sign in to add a review

Quick Information

0 ratings
GodotE2E icon image
LIUXIN
GodotE2E

Out-of-process E2E testing tool for Godot.Test your Godot games from Python using pytest. The addon runs a TCP automation server as an Autoload β€” completely dormant unless launched with the --e2e flag.Features:- Synchronous Python API (no async/await needed)- Input simulation: keyboard, mouse, named actions- Node operations: get/set properties, call methods, group lookup- Frame synchronization: wait for process/physics frames or game time- Scene management: change scene, reload scene- Screenshot capture with pytest failure integration- Works with standard Godot 4.x binaries, no engine modificationsInstall the Python package: pip install godot-e2eDocumentation: https://github.com/RandallLiuXin/godot-e2e/tree/main/docs

Supported Engine Version
4.0
Version String
1.0.0
License Version
Apache-2.0
Support Level
community
Modified Date
10 hours ago
Git URL
Issue URL

Open Source

Released under the AGPLv3 license

Plug and Play

Browse assets directly from Godot

Community Driven

Created by developers for developers