module Lapis::Docs::H_TESTING_AND_BENCHMARKS::A_TESTING_FRAMEWORK

Overview

Unified Testing Framework & Leak Verification

Comprehensive guide to the Lapis::Test apparatus, authoring automated test suites, running headless in-editor tool tests, and quantitatively proving zero memory leaks.

Executive Summary & Key Topics

Topic Method / Anchor Description
Testing Apparatus Features .topic_00_test_capabilities Declarative test_suite DSL, lifecycle fixtures, and engine performance monitors.
Authoring a Test Suite .topic_01_writing_suites Creating test suites in spec/suites/ with custom assertions.
Proving Zero Leaks with assert_no_leak .topic_02_zero_leak_verification Using Godot's Performance monitors and Boehm GC to mathematically prove zero memory leaks.
Multi-Frame Physics Simulation & Stability Testing .topic_03_multiframe_physics_stability_testing Simulating physical settling over dozens of frames and quantitatively asserting numeric and structural stability.

Related Guides & Source References

Defined in:

libgodot/docs/h_testing_and_benchmarks/a_testing_framework.cr

Class Method Summary

Class Method Detail

def self.topic_00_test_capabilities : Nil #

Testing Apparatus Features: Declarative test_suite DSL, lifecycle fixtures, and engine performance monitors.

Key Topics & Information

  • Declarative syntax: test_suite "Name" do ... test "Case" do ... end end
  • Lifecycle fixtures: before_each and after_each setup hooks
  • Quantitative zero memory leak verification via assert_no_leak
  • Multi-frame physics simulation and numerical stability testing
  • Dual execution: Run headlessly in CI or interactively in Godot Editor Test Runner Dock

def self.topic_01_writing_suites : Nil #

Authoring a Test Suite: Creating test suites in spec/suites/ with custom assertions.

require "../spec_helper"

test_suite "Combat Mechanics" do
  before_each do
    @player = Godot.create(Godot::CharacterBody2D)
  end

  after_each do
    @player.destroy if @player.alive?
  end

  test "player takes damage correctly" do
    combat = CombatSystem.new(@player)
    combat.apply_damage(20)
    combat.health.should eq(80)
  end
end

def self.topic_02_zero_leak_verification : Nil #

Proving Zero Leaks with assert_no_leak: Using Godot's Performance monitors and Boehm GC to mathematically prove zero memory leaks.

Memory leaks are fatal in game development. Lapis provides assert_no_leak:

test "1,000 bullet spawns do not leak engine memory" do
  Lapis::Test.assert_no_leak(warmup: 5, iterations: 100) do
    bullet = Godot.create(Godot::Sprite2D)
    get_tree.root.add_child(bullet)
    bullet.queue_free
  end
end

How It Works:

  1. Runs warmup iterations to stabilize caches.
  2. Records initial OBJECT_COUNT, OBJECT_NODE_COUNT, and MEMORY_STATIC.
  3. Executes the test block across batch iterations.
  4. Forces GC.collect and pumps Godot frames to flush deferred deletions.
  5. Mathematically asserts that final object count exactly equals initial object count!

def self.topic_03_multiframe_physics_stability_testing : Nil #

Multi-Frame Physics Simulation & Stability Testing: Simulating physical settling over dozens of frames and quantitatively asserting numeric and structural stability.

Unit tests that inspect nodes at a single instant cannot catch physics jitter, tunneling, divergent numerical explosions (NaN / Inf coordinates), or memory leaks across continuous engine ticks.

Lapis provides multi-frame simulation testing using skip_frames(N) and skip_physics_frames(N) to run authentic physics over real virtual time:

1. 2D Pit Settling (200 Rigid Bodies):

In spec/suites/test_physics_multiframe_pit_settling.cr, an enclosed containment pit (static floor and walls) is spawned alongside 200 RigidBody2D circle balls. The test yields 180 frames (skip_frames(180)) for balls to fall, bounce, and pack into a stable resting pile:

test "200 RigidBody2D balls drop into an enclosed pit and settle" do
  assert_no_leak(name: "200 Ball Pit Settling") do
    # 1. Spawn static floor and containment walls
    # 2. Spawn 200 RigidBody2D balls in falling grid
    # 3. Simulate multi-frame physics
    skip_frames(180)

    # 4. Assert boundary containment and numerical sanity
    balls.each do |ball|
      pos = ball.get_position
      assert_false pos.x.nan?, "Ball coordinate must not be NaN"
      assert_gt pos.x, 70.0_f32, "Ball escaped left pit wall"
      assert_lt pos.x, 930.0_f32, "Ball escaped right pit wall"
      assert_lt pos.y, 650.0_f32, "Ball fell through floor"
    end

    # 5. Destroy all bodies and verify zero ObjectDB leaks
  end
end

2. 3D Cube Stack Stability:

In spec/suites/test_physics_cube_stack_stability.cr, a vertical tower of 10 RigidBody3D boxes is spawned on a static ground plane. After stepping physics frames:

  • Validates that the tower compresses and settles without violent explosion or toppling into outer space.
  • Asserts that all coordinates remain finite and within reasonable horizontal drift bounds (pos.x.abs < 15.0).
  • Confirms that destroying the bodies returns Godot's ObjectDB count to baseline with zero orphan nodes.