Skip to content

Releases: godot-gdunit-labs/gdUnit4Net

v5.0.0

21 Jun 09:07
39f8365

Choose a tag to compare

🚀 GdUnit4 v5.0.0 - Major Architecture Overhaul

Breaking Changes ⚠️

Test Engine Redesign: GdUnit4 v5.0.0 introduces a completely reworked test engine that no longer requires the Godot runtime by default. This significantly improves test performance and enables testing in CI/CD environments without Godot installations.

Migration Required: Existing tests that depend on Godot runtime features (scenes, nodes, resources, etc.) must now be explicitly marked with the [RequireGodotRuntime] attribute.

New Features ✨

🎯 Selective Godot Runtime

  • [RequireGodotRuntime]: Annotate classes or methods that need Godot runtime context
  • Tests without this attribute run in fast, lightweight mode
  • Dramatically improves test execution speed for logic-only tests

📊 Enhanced Debugging & Output

  • <CaptureStdOut>true</CaptureStdOut>: Capture console output and Godot prints in test results
  • [GodotExceptionMonitor]: Monitor and report exceptions from Godot's main thread:
    • Catches exceptions in node callbacks (_Ready, _Process, etc.)
    • Monitors scene tree operations
    • Reports "silent" Godot exceptions as test failures
  • [ThrowsException]: Comprehensive exception testing with precise validation
  • Better error reporting and diagnostics

🔧 Advanced Test Configuration

  • [DataPoint(nameof(DataSource))]: Create data-driven tests with support for:
    • Static properties and methods as data sources
    • Parameterized data methods with arguments
    • Async data sources with IAsyncEnumerable<object[]>
    • External class data sources
  • [ThrowsException(typeof(ArgumentException), "message")]: Verify expected exceptions with:
    • Exception type validation
    • Message matching
    • Source file and line number verification
    • Support for multiple expected exception types
  • Full VSTest filter support: Use standard test filtering in Visual Studio and dotnet test
  • [TestCategory("CategoryA")]: Organize tests with categories
  • [Trait("Category", "A")]: Add custom traits for test organization

Migration Guide 📋

Before v5.0.0:

[Test]
public void MyTest() 
{
    // All tests ran in Godot runtime
    var node = new Node();
    AddChild(node);
}

v5.0.0:

[Test]
public void MyLogicTest() 
{
    // Runs fast without Godot runtime
    var result = Calculator.Add(1, 2);
    AssertThat(result).IsEqual(3);
}

[Test]
[RequireGodotRuntime]  // ← Add this for Godot-dependent tests
public void MyGodotTest() 
{
    var scene = new PackedScene();
    var node = scene.Instantiate();
    AddChild(node);
}

[Test]
[RequireGodotRuntime]
[GodotExceptionMonitor]  // ← Monitor Godot exceptions
public void TestNodeCallback()
{
    var node = new MyNode(); // Will catch exceptions in _Ready()
    AddChild(node);
}

[Test]
[DataPoint(nameof(TestData))]  // ← Data-driven tests
public void TestCalculations(int a, int b, int expected)
{
    AssertThat(Calculator.Add(a, b)).IsEqual(expected);
}

[Test]
[ThrowsException(typeof(ArgumentNullException), "Value cannot be null")]
public void TestValidation()
{
    Calculator.Add(null, 5); // Expects specific exception
}

// Data source for parameterized tests
public static IEnumerable<object[]> TestData => new[]
{
    new object[] { 1, 2, 3 },
    new object[] { 5, 7, 12 }
};

Performance Impact 🚀

  • Non-Godot tests: Up to 10x faster execution
  • CI/CD friendly: No Godot installation required for logic tests
  • Selective runtime: Only pay the Godot overhead when needed

Key Attribute Features 🏷️

Data-Driven Testing

[Test]
[DataPoint(nameof(CalculationData))]
public void TestCalculations(int a, int b, int expected)
{
    AssertThat(Calculator.Add(a, b)).IsEqual(expected);
}

// Multiple data source options
public static IEnumerable<object[]> CalculationData => new[]
{
    new object[] { 1, 2, 3 },
    new object[] { 5, 7, 12 }
};

// Parameterized data methods
[DataPoint(nameof(GetDynamicData), 10)]
public static IEnumerable<object[]> GetDynamicData(int multiplier) => 
    Enumerable.Range(1, 3).Select(i => new object[] { i * multiplier });

// External data sources
[DataPoint(nameof(SharedTestData), typeof(TestDataProvider))]
public void TestWithExternalData(string input, bool expected) { }

Exception Testing

// Basic exception type verification
[Test]
[ThrowsException(typeof(ArgumentNullException))]
public void TestNullArgument() { }

// Message validation
[Test]
[ThrowsException(typeof(InvalidOperationException), "Operation not allowed")]
public void TestSpecificError() { }

// File and line verification
[Test]
[ThrowsException(typeof(ArgumentException), "Invalid value", "Calculator.cs", 25)]
public void TestPreciseLocation() { }

// Multiple possible exceptions
[Test]
[ThrowsException(typeof(ArgumentNullException))]
[ThrowsException(typeof(ArgumentException))]
public void TestMultipleExceptions() { }

Godot Integration

// Class-level runtime requirement
[RequireGodotRuntime]
public class NodeTests
{
    [Before]
    public void Setup() => Engine.PhysicsTicksPerSecond = 60;
}

// Method-level monitoring
[Test]
[RequireGodotRuntime]
[GodotExceptionMonitor]
public void TestNodeBehavior()
{
    var node = new MyCustomNode();
    AddChild(node); // Will catch exceptions in _Ready(), _Process(), etc.
}

.runsettings Configuration

<RunSettings>
  <GdUnit4>
    <CaptureStdOut>true</CaptureStdOut>
    <Parameters>--verbose --headless</Parameters>
    <DisplayName>FullyQualifiedName</DisplayName>
    <CompileProcessTimeout>30000</CompileProcessTimeout>
  </GdUnit4>
</RunSettings>

Summary

This release represents a major step forward in making GdUnit4 more efficient, flexible, and suitable for modern development workflows. The selective runtime approach allows developers to get the best of both worlds: lightning-fast tests for business logic and full Godot integration when needed.

Key Benefits:

  • Performance: Up to 10x faster for non-Godot tests
  • 🧪 Data-Driven: Comprehensive parameterized testing with multiple data source options
  • 🔍 Exception Testing: Precise exception validation with message and location verification
  • 🎮 Godot Integration: Smart runtime detection and exception monitoring
  • 🛠️ VSTest Compatible: Full integration with Visual Studio and dotnet test

For technical support and questions, please visit our GitHub repository or documentation.

What's Changed

✨ New Features

  • GD-138: Add capture test case execution stdout to the test report by @MikeSchulze in #139
  • GD-144: Add AwaitInputProcessed to SceneRunner by @MikeSchulze in #145
  • GD-46: Added support of DataPoint attributes, which make it possible to define parameterized tests with dynamic test data by @MikeSchulze in #147
  • GD-153: Add Roslyn Analyzer to validate TestCase and DataPoint attribute combinations by @MikeSchulze in #154
  • GD-156: Add an exception hook to report exceptions as test failures that are caught by Godot by @MikeSchulze in #157
  • GD-160: Apply runsettings environment variables to the test execution context by @MikeSchulze in #161
  • GD-163: Collect the Godot log file into test report by @MikeSchulze in #164
  • GD-156: Install Godot exception handler and forward uncaught exceptions as test failure. by @MikeSchulze in #162
  • GD-682: Rework on GdUnit4Net API Godot bridge by @MikeSchulze in #197
  • GD-27: Add VSTest filter support with test categories and traits by @MikeSchulze in #201
  • GD-240: Add GDUNIT4NET_API_V5 Conditional Compilation Constant by @MikeSchulze in #241
  • Upgrade to .NET 8/9 with C# 12 support by @MikeSchulze in #267
  • GD-211: Implement missing AwaitSignalOn by @MikeSchulze in #282

🪲 Bug Fixes

  • GD-149: Add error to the execution log when the test session timeout occurs by @MikeSchulze in #150
  • GD-152: Fix test case display name for dynamic test data driven tests by @MikeSchulze in #176
  • Fixes Godot exception monitoring issues by @MikeSchulze in #187
  • Make WithTimeout public by @MikeSchulze in #189
  • GD-199: TestRunner install ends with abnormal exit on large projects by @MikeSchulze in #200
  • GD-203: Handle failure reporting for test stages [Before] and [After] by @MikeSchulze in #204
  • GD-212: Fix vector assertion IsEqualApprox by @MikeSchulze in #214
  • GD-284: Fix test failure causes the entire test execution if it is executed in the Godot Editor by @MikeSchulze in #285

🧹 Maintenance

Read more

gdUnit4Net v4.3.1

30 Jul 15:03
a42fa57

Choose a tag to compare

Hot Fix

What's Changed

  • GD-135: Allow to use AssertSignal on RefCounted Objects by @MikeSchulze in #136

Full Changelog: v4.3.0...v4.3.1

gdUnit4Net v4.3.0

09 Jul 16:08
22007d7

Choose a tag to compare

Major Changes

The way test events are sent has been changed from std:out to IPC and had to be updated in the API and test adapter.

With this version, we achieve the test adapter in Rider to debugging without need of hacks.
It is important to update Rider to 2024.2 or later to enable the test adapter to run debug.

gdUnit4.api v4.3.0

gdUnit4.test.adapter v2.0.0

What's Changed

  • GD-127: Replace stdout based TestEventProcessor by IPC implementation by @MikeSchulze in #129
  • GD-124: Use LaunchProcessWithDebuggerAttached instead of AttachDebuggerIfNeed for Rider 2024.2 by @MikeSchulze in #130

Full Changelog: v4.2.5...v4.3.0

gdUnit4Net v4.2.5

24 Jun 07:58
cb66317

Choose a tag to compare

What's Changed

gdUnit4.api v4.2.5

  • GD-110: Allow a Node to be passed in to SceneRunner.Load as the root of the scene. by @taylor-nightingale in #111
  • GD-121: Improve AssertSignal by adding a StartMonitoring method by @MikeSchulze in #122

gdUnit4.test.adapter v1.1.2

  • GD-114: Fix test adapter gdUnit4.api version resolving by @MikeSchulze in #118
  • GD-115: Fix Debug tests gets stuck when using --verbose by @MikeSchulze in #119

Other changes

  • GD-116: Add publish WF to publish test reports in a separate way by @MikeSchulze in #120
  • GD-87: Remove temporary solution of Godot.SourceGenerators.MustBeVariantAnalyzer warnings by @MikeSchulze in #123

New Contributors

Full Changelog: v4.2.4...v4.2.5

gdUnit4Net v4.2.4

04 Jun 05:55
1b1a33f

Choose a tag to compare

  • gdUnit4.api v4.2.4
  • gdUnit4.test.adapter v1.1.1

Improvements

  • GD-89: Add input action support to the SceneRunner by @MikeSchulze in #92
  • GD-94: Improve assertions error message when comparing objects by @MikeSchulze in

Bug fixes

  • GD-90: Cleanup old runner configuration before run new tests by @MikeSchulze in #93
    #95
  • GD-96: Fix methods with a single parameterized test case are not executed by @MikeSchulze in #97
  • Use example project for unit test using gdunit4-action by @MikeSchulze in #98
  • GD-99: Add support to load a scene by uid:// path to the Scene Runner by @MikeSchulze in #100
  • GD-101: Respect the GdUnit4 settings to notify about orphan nodes by @MikeSchulze in #102
  • GD-103: Trim MSTest assert stack trace by @MikeSchulze in #105
  • GD-104: Fix exception failure message propagation by @MikeSchulze in #108

Full Changelog: v4.2.3...v4.2.4

gdUnit4Net v4.2.3

17 Apr 11:47
89e051a

Choose a tag to compare

  • gdUnit4.api v4.2.3
  • gdUnit4.test.adapter v1.1.1

What's Changed

gdUnit4.api

  • GD-84: Fix AssertThat for dynamic assert type resolving by @MikeSchulze in #85

gdUnit4.test.adapter

  • GD-86: Fixes space in folder name prevents tests from running by @MikeSchulze in #88

New Contributors

Full Changelog: v2.2.2...v4.2.3

gdUnit4Net v4.2.2

12 Apr 10:31
f0ba1f1

Choose a tag to compare

GdUnit4Net Release Notes

  • gdUnit4.api v4.2.2
  • gdUnit4.test.adapter v1.1.0

What's Changed

  • GD-6: Update project to GodotSharp v4.1.0 by @MikeSchulze in #7
  • GD-9: Fix SceneRunnerTest by @MikeSchulze in #13
  • GD-5: SceneRunner: Fix InputEvent handling by @MikeSchulze in #14
  • GD-12: Reorganize the project by @MikeSchulze in #15
  • GD-11: Add continue integration tests for pull request by @MikeSchulze in #23
  • GD-11: Fix CI workflow by @MikeSchulze in #24
  • GD-16: Add GdUnit4 Test Adapter to CI Workflow by @MikeSchulze in #25
  • GD-40: Fix GdUnit4MonoAPI IsTestSuite cannot run TestSuite by @MikeSchulze in #41
  • GD-42: Fix test run stops at some point by @MikeSchulze in #43
  • GD_35: Add example to show usage of gdUnit4.test.adapter by @MikeSchulze in #37
  • G-8: Provide generic vector assert to support all Godot vector types by @MikeSchulze in #45
  • GD-51: Format and fix warnings according to C# standards by @MikeSchulze in #53
  • GD-54: Format the tests according to the C# Formatting rules by @MikeSchulze in #55
  • GD-52: Format the code to C# standard by @MikeSchulze in #56
  • GD-357: Parameterized test cases are not run from Godot Editor GdUnit4 inspector by @MikeSchulze in #59
  • Support both net7 and net8 at once by @van800 in #61
  • GD-62: Add full .NET8 support by @MikeSchulze in #63
  • GD-22: Calling Invoke on SceneRunner must propagate exceptions by @MikeSchulze in #65
  • GD-49: Revision of the stack trace collection for failed tests by @MikeSchulze in #66
  • GD-10: Complete missing features for IDictionaryAssert by @MikeSchulze in #67
  • GD-10: Complete missing features for IEnumerableAssert by @MikeSchulze in #69
  • GD-10: Complete missing features for INumberAssert by @MikeSchulze in #70
  • GD-32: Add missing SimulateMouseMoveRelative and SimulateMouseMoveAbsolute to ISceneRunner by @MikeSchulze in #71
  • GD-26: Fix parameterized tests are incorrect grouped by @MikeSchulze in #73
  • GD-74: Improve the CI workflow for job unit-test-example by validate the test report by @MikeSchulze in #75
  • GD-76: Fix DisplayName resolving on test adapter by @MikeSchulze in #79
  • GD-80: Rename repository from gdUnit4Mono to gdUnit4Net by @MikeSchulze in #81

New Contributors

Full Changelog: v2.3.1...v2.2.2