Asteroid.GodotUnitTest 0.7.0

dotnet add package Asteroid.GodotUnitTest --version 0.7.0
                    
NuGet\Install-Package Asteroid.GodotUnitTest -Version 0.7.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Asteroid.GodotUnitTest" Version="0.7.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Asteroid.GodotUnitTest" Version="0.7.0" />
                    
Directory.Packages.props
<PackageReference Include="Asteroid.GodotUnitTest" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Asteroid.GodotUnitTest --version 0.7.0
                    
#r "nuget: Asteroid.GodotUnitTest, 0.7.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Asteroid.GodotUnitTest@0.7.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Asteroid.GodotUnitTest&version=0.7.0
                    
Install as a Cake Addin
#tool nuget:?package=Asteroid.GodotUnitTest&version=0.7.0
                    
Install as a Cake Tool

Asteroid.GodotUnitTest

Asteroid.GodotUnitTest is a minimal Godot C# test API plus VSTest adapter. It lets a Godot C# project expose tests to dotnet test while executing the test bodies inside a Godot process.

The current scope is intentionally small: discover tests, run them through Godot, and report pass/fail/skip results back to VSTest. Version 0.6.0 is a 0.x release intended for internal projects and early users. Core workflows should be repeatable, but 1.0-level API compatibility is not promised yet.

Supported versions

Area Supported Notes
Godot Godot 4.7.2 Mono Other Godot 4.x Mono versions may work but are not part of the current guarantee.
OS Windows Linux and macOS are future validation targets.
.NET development and CI .NET SDK 10, .NET runtime 8 SDK policy follows the host AsteroidFrameworkDevelop repository.
Projects net8.0 Both API and adapter projects target net8.0 (consumer compatibility surface).

Distribution is NuGet: both packages (Asteroid.GodotUnitTest, Asteroid.GodotUnitTest.TestAdapter) are published to official nuget.org from the tooling/Utility/GodotUnitTest module of the AsteroidFrameworkDevelop repository. The module is a standalone development-time tool with no dependency on the framework libraries. The historical 0.5.0 packages remain on the Asteroid Gitea NuGet source as anchors.

Quick start

Install the API, adapter, VSTest SDK, and NUnit assertions in a Godot C# project:

dotnet add package Microsoft.NET.Test.Sdk
dotnet add package NUnit
dotnet add package Asteroid.GodotUnitTest --version 0.6.0
dotnet add package Asteroid.GodotUnitTest.TestAdapter --version 0.6.0

Mark the Godot project as a test project:

<PropertyGroup>
  <IsTestProject>true</IsTestProject>
</PropertyGroup>

Set GODOT_BIN to a Godot Mono executable:

$env:GODOT_BIN = 'C:\Dev\Godot\4.7.2.stable\Godot_v4.7.2-stable_mono_win64.exe'

Write a test:

namespace GodotProject.Tests;

using System.Threading.Tasks;
using Godot;
using Asteroid.GodotUnitTest;
using NUnit.Framework;

[GodotTestFixture]
public sealed class PlayerTests : GodotSceneTest
{
    [GodotTest]
    public async Task NodeEntersTree()
    {
        var node = AddChild(new Node2D());

        await WaitFrames();

        Assert.That(node.IsInsideTree(), Is.True);
    }
}

Run it through VSTest:

dotnet test

Do not reference NUnit3TestAdapter in the same Godot test project unless you intentionally want NUnit to discover a separate set of tests. Asteroid.GodotUnitTest discovers Godot* attributes and can use NUnit assertions without the NUnit adapter.

The adapter generates AsteroidGodotUnitTestRunner/AsteroidGodotUnitTestRunnerScene.cs inside the Godot project before execution. Add AsteroidGodotUnitTestRunner/ to the consumer project's .gitignore.

Current capabilities

  • dotnet test --list-tests discovery through a VSTest adapter.
  • dotnet test execution through Godot headless by default, with opt-in windowed runs.
  • [GodotTestFixture] classes, [GodotTest] methods, and [GodotTestCase] parameterized cases.
  • Assertions through NUnit Assert or any assertion library that throws exceptions.
  • Failure artifacts: the scene tree dump at the failure moment is folded into the error message, and a PNG screenshot of the failure viewport is written when a frame buffer is available.
  • void and Task test methods.
  • Skip reporting with [GodotTest(Skip = "reason")] or [GodotTestCase(Skip = "reason")].
  • Display names with [GodotTest("Display name")], [GodotTestCase(..., DisplayName = "name")], or DisplayName.
  • GodotSetUp, GodotTearDown, GodotOneTimeSetUp, and GodotOneTimeTearDown lifecycle methods.
  • GodotSceneTest and GodotSceneTestContext helpers for per-test scene roots, node cleanup, frame waits, timers, signals, and scene loading.
  • Per-test Console.Out and Console.Error capture in VSTest/TRX output.
  • Godot file logging disabled by default for adapter-launched test processes, with a runsettings opt-out.
  • Categories with [GodotCategory("name")], surfaced as VSTest TestCategory traits.
  • Run mode selection with [GodotRunMode(GodotRunMode.Windowed)] or .runsettings.
  • Per-test timeout metadata through GodotTestAttribute.TimeoutMilliseconds.
  • Basic NUnit assertion exception interop (Assert.Ignore, Assert.Inconclusive, Assert.Pass).
  • Basic VSTest filtering for FullyQualifiedName, DisplayName, ManagedType, ManagedMethod, RunMode, SkipReason, TimeoutMilliseconds, and TestCategory.

Project layout

  • src/Asteroid.GodotUnitTest/ — lightweight API referenced by Godot test projects.
  • src/Asteroid.GodotUnitTest.TestAdapter/ — VSTest adapter and Godot process runner.
  • godot-project/ — sample Godot C# project used for end-to-end validation.
  • tests/Asteroid.GodotUnitTest.TestAdapter.Fixtures/ — fixture assembly for scanner tests.
  • tests/Asteroid.GodotUnitTest.TestAdapter.Tests/ — adapter unit tests.
  • tests/Asteroid.GodotUnitTest.ExpectedFailureProject/ — Godot project used by E2E tests to verify failure reporting.
  • tests/Asteroid.GodotUnitTest.EndToEnd.Tests/ — optional E2E tests that run dotnet test when GODOT_BIN is configured.

Writing tests

namespace GodotProject.Tests;

using System;
using System.Threading.Tasks;
using Godot;
using Asteroid.GodotUnitTest;
using NUnit.Framework;

[GodotTestFixture]
[GodotCategory("Sample")]
public sealed class PlayerTests
{
    private Node2D node = null!;

    [GodotSetUp]
    public void SetUp()
    {
        node = new Node2D();
    }

    [GodotTearDown]
    public void TearDown()
    {
        node.Free();
    }

    [GodotTest]
    [GodotCategory("Fast")]
    public void CanCreateNode()
    {
        Assert.That(node, Is.Not.Null);
        Assert.That(node, Is.TypeOf<Node2D>());
    }

    [GodotTest("Async example")]
    public async Task AsyncPasses()
    {
        await Task.Delay(1);
        Assert.That(2 + 2, Is.EqualTo(4));
    }

    [GodotTest("Console output example")]
    public void CapturesConsoleOutput()
    {
        Console.WriteLine("This is attached to the VSTest result.");
        Console.Error.WriteLine("stderr is attached under the same test result.");
        Assert.That(node, Is.Not.Null);
    }

    [GodotTest(TimeoutMilliseconds = 1000)]
    public async Task TimeoutSettingPasses()
    {
        await Task.Delay(1);
        Assert.That(true, Is.True);
    }

    [GodotTest("NUnit ignore example")]
    public void NUnitIgnoreIsReportedAsSkipped()
    {
        Assert.Ignore("NUnit Ignore is reported as a skipped Godot test.");
    }

    [GodotTest(Skip = "Waiting on a scene fixture.")]
    public void SkippedTest()
    {
        Assert.Fail("This should not run.");
    }
}

Plain [GodotTest] methods must be parameterless. Use [GodotTestCase] when a test method needs arguments; one VSTest case is discovered for each attribute instance.

[GodotTestCase(1, 2, 3)]
[GodotTestCase(2, 3, 5, DisplayName = "2 + 3 = 5")]
public void AddsNumbers(int left, int right, int expected)
{
    Assert.That(left + right, Is.EqualTo(expected));
}

Methods may be static or instance methods and may return void or Task. [GodotTestFixture] is optional today; methods marked with [GodotTest] or [GodotTestCase] are discovered even without it. TimeoutMilliseconds applies to test methods, test cases, setup methods, and teardown methods; a synchronously blocked method still relies on the adapter/process-level timeout.

Godot scene helpers

Use GodotSceneTest when a fixture needs convenient access to the live Godot SceneTree:

[GodotTestFixture]
public sealed class PlayerSceneTests : GodotSceneTest
{
    [GodotTest]
    public async Task PlayerNodeEntersTree()
    {
        var player = AddChild(new Node2D());

        await WaitFrames();

        Assert.That(player.IsInsideTree(), Is.True);
        Assert.That(player.GetParent(), Is.SameAs(Root));
    }
}

GodotSceneTestContext is also available as a lower-level constructor injection API if you do not want to derive from GodotSceneTest.

Each test gets its own temporary Root node under the runner's SceneTree.Root. Nodes added through AddChild, scenes created through Instantiate/LoadScene, and objects registered with RegisterForCleanup are cleaned up after teardown. Static tests continue to run but cannot use fixture constructor context or instance base-class helpers.

Available helpers:

  • AddChild<T>(T node) adds a node under the per-test root and registers it for cleanup.
  • Instantiate<T>(PackedScene scene) instantiates, parents, and tracks a packed scene instance.
  • LoadScene<T>(string resourcePath) loads a PackedScene resource and instantiates it.
  • FindChild<T>(string name, bool recursive = true, bool owned = false) finds a child node under the per-test root.
  • WaitForChild<T>(string name, double timeoutSeconds = 5, ...) waits until a child node exists or the timeout expires.
  • WaitFrames(int frameCount = 1) waits for one or more process frames.
  • WaitFrames(int frameCount, CancellationToken cancellationToken) waits for frames with cancellation support.
  • WaitSeconds(double seconds) waits using a Godot timer.
  • WaitSeconds(double seconds, CancellationToken cancellationToken) waits using a Godot timer with cancellation support.
  • WaitUntil(Func<bool> condition, double timeoutSeconds = 5, CancellationToken cancellationToken = default) polls once per frame until a condition is true.
  • WaitSignal(GodotObject source, StringName signalName, double timeoutSeconds = 5) waits for a signal with an optional timeout.
  • WaitSignal(..., CancellationToken cancellationToken) overloads add cancellation support.

Lifecycle methods

Use [GodotOneTimeSetUp] and [GodotOneTimeTearDown] for fixture-level lifecycle work. One-time setup runs before the selected tests in that fixture; one-time teardown runs after those selected tests. If one-time setup fails, each selected test in the fixture is reported as failed and one-time teardown is still attempted.

Use [GodotSetUp] and [GodotTearDown] for per-test lifecycle work. Lifecycle methods may be public or non-public, instance or static, and may return void or Task.

Overall execution order is deterministic:

base GodotOneTimeSetUp methods, metadata order
derived GodotOneTimeSetUp methods, metadata order
  base GodotSetUp methods, metadata order
  derived GodotSetUp methods, metadata order
  test method
  derived GodotTearDown methods, reverse metadata order
  base GodotTearDown methods, reverse metadata order
derived GodotOneTimeTearDown methods, reverse metadata order
base GodotOneTimeTearDown methods, reverse metadata order

Lifecycle methods are collected per declared type in the inheritance chain, so private base class setup/teardown methods are supported. Static setup/teardown methods are also supported. Per-test setup/teardown methods run once per test; one-time setup/teardown methods run once per selected fixture group.

If instance creation succeeds and lifecycle execution starts, teardown methods are attempted even when setup or the test body fails. Teardown methods should tolerate partially initialized state. A teardown failure turns a passed or skipped test into a failed test; if the test already failed, the teardown failure is appended to the existing error message and stack trace.

Categories and filtering

Use [GodotCategory] on a class or method to add VSTest TestCategory traits. Class-level categories apply to tests declared in that class. Method-level categories are additive. Duplicate category names are emitted once per test.

[GodotCategory("Scene")]
public sealed class PlayerSceneTests
{
    [GodotTest]
    [GodotCategory("Fast")]
    public void CanCreatePlayer()
    {
    }
}

Filter with standard VSTest filter syntax:

dotnet test --filter "TestCategory=Fast"
dotnet test --filter "TestCategory!=Slow"
dotnet test --filter "TestCategory=Scene&FullyQualifiedName~Player"
dotnet test --filter "RunMode=Windowed&TestCategory=Visual"

Asteroid.GodotUnitTest category filtering does not require NUnit3TestAdapter; the categories are discovered from Godot-prefixed attributes by Asteroid.GodotUnitTest.TestAdapter.

Godot run mode

Tests run in Godot headless mode by default. Use GodotRunMode when a fixture or individual test needs a real Godot window, display driver, or non-headless rendering path.

[GodotRunMode(GodotRunMode.Windowed)]
public sealed class VisualRenderingTests
{
    [GodotTest]
    public void OpensAWindow()
    {
    }

    [GodotTest]
    [GodotRunMode(GodotRunMode.Headless)]
    public void OverridesTheFixtureDefault()
    {
    }
}

GodotRunMode can be applied to a class or method. Method-level run mode overrides class-level run mode. Because headless/windowed mode is a Godot process startup choice, mixed runs are split into separate Godot process invocations.

Filter by effective run mode with standard VSTest syntax:

dotnet test --filter "RunMode=Windowed"

Configuring a Godot project

For local development in this repository, the sample project references the API and adapter projects directly:

<ItemGroup>
  <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
  <PackageReference Include="NUnit" Version="4.4.0" />
  <ProjectReference Include="..\src\Asteroid.GodotUnitTest\Asteroid.GodotUnitTest.csproj" />
  <ProjectReference Include="..\src\Asteroid.GodotUnitTest.TestAdapter\Asteroid.GodotUnitTest.TestAdapter.csproj" />
</ItemGroup>

It also marks the Godot project as a test project:

<PropertyGroup>
  <IsTestProject>true</IsTestProject>
</PropertyGroup>

When consuming packed NuGet packages from a Godot project, reference the packages instead:

<ItemGroup>
  <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
  <PackageReference Include="NUnit" Version="4.4.0" />
  <PackageReference Include="Asteroid.GodotUnitTest" Version="0.6.0" />
  <PackageReference Include="Asteroid.GodotUnitTest.TestAdapter" Version="0.6.0" />
</ItemGroup>

Minimal consumer project shape:

<Project Sdk="Godot.NET.Sdk/4.7.2">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
    <PackageReference Include="NUnit" Version="4.4.0" />
    <PackageReference Include="Asteroid.GodotUnitTest" Version="0.6.0" />
    <PackageReference Include="Asteroid.GodotUnitTest.TestAdapter" Version="0.6.0" />
  </ItemGroup>
</Project>

Add the generated runner directory to the consumer project's .gitignore:

AsteroidGodotUnitTestRunner/

The adapter package includes a buildTransitive props file that copies the runner template to the consumer output, so package consumers should not need ProjectReference or TestAdaptersPaths. Do not reference NUnit3TestAdapter in the same Godot test project unless you intentionally want NUnit to discover a separate set of tests; Asteroid.GodotUnitTest discovers Godot* attributes and can use NUnit assertions without the NUnit adapter.

During local project-reference development, godot-project/Directory.Build.props points VSTest at the adapter output directory:

<Project>
  <PropertyGroup>
    <TestAdaptersPaths>$(MSBuildProjectDirectory)\..\src\Asteroid.GodotUnitTest.TestAdapter\bin\$(Configuration)\net8.0</TestAdaptersPaths>
  </PropertyGroup>
</Project>

When this project is consumed as a NuGet package, this local TestAdaptersPaths workaround should no longer be necessary if the adapter package is laid out correctly.

Run settings

Set GODOT_BIN to the Godot Mono executable, either in the environment or in .runsettings.

Example environment variable on Windows:

$env:GODOT_BIN = 'C:\Dev\Godot\4.7.2.stable\Godot_v4.7.2-stable_mono_win64.exe'

Minimal .runsettings:

<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <RunConfiguration>
    <ResultsDirectory>./TestResults</ResultsDirectory>
    <TestSessionTimeout>600000</TestSessionTimeout>
  </RunConfiguration>
  <AsteroidGodotUnitTest>
    <ResultTimeoutMilliseconds>600000</ResultTimeoutMilliseconds>
    <RebuildBeforeRun>true</RebuildBeforeRun>
    <DisableGodotFileLogging>true</DisableGodotFileLogging>
  </AsteroidGodotUnitTest>
</RunSettings>

Optional settings:

<AsteroidGodotUnitTest>
  <GodotBin>C:\path\to\Godot_v4.7.2-stable_mono_win64.exe</GodotBin>
  <GodotProjectPath>C:\path\to\project-containing-project.godot</GodotProjectPath>
  <RunMode>Headless</RunMode>
  <Headless>true</Headless>
  <ResultTimeoutMilliseconds>600000</ResultTimeoutMilliseconds>
  <RebuildBeforeRun>true</RebuildBeforeRun>
  <DisableGodotFileLogging>true</DisableGodotFileLogging>
</AsteroidGodotUnitTest>

Runsettings reference:

Setting Default Purpose Notes
GodotBin GODOT_BIN environment variable Path to the Godot Mono executable. May also be supplied as <RunConfiguration><EnvironmentVariables><GODOT_BIN>.
GodotProjectPath unset Explicit path to the directory containing project.godot. When omitted, the adapter walks upward from the test assembly path.
RunMode Headless Default run mode for tests without [GodotRunMode]. Use Windowed for tests that need a real window/display path.
Headless unset Compatibility shortcut for older configuration. false maps to RunMode=Windowed; prefer RunMode.
ResultTimeoutMilliseconds 600000 Process-level timeout for dotnet build and Godot execution. Per-test TimeoutMilliseconds is separate and cannot interrupt synchronously blocked code.
RebuildBeforeRun true Builds the Godot project before launching Godot. Set false only when the project is already built.
DisableGodotFileLogging true Prevents adapter-launched Godot processes from writing normal project log files. Set false to opt out and keep Godot file logs.

If GodotProjectPath is omitted, the adapter walks upward from the discovered test assembly until it finds project.godot.

Set <RunMode>Windowed</RunMode> to make unannotated tests run without --headless. [GodotRunMode(...)] on a class or method overrides the .runsettings default for matching tests. <Headless>false</Headless> is also accepted as a compatibility shortcut for windowed mode.

Godot file logging is disabled by default during test runs. The adapter passes debug/file_logging/enable_file_logging=false, redirects any early Godot log file to a temporary adapter path, and deletes that temporary log after the process exits. The adapter still captures Godot standard output and standard error for VSTest/TRX diagnostics. Set <DisableGodotFileLogging>false</DisableGodotFileLogging> if you need Godot to write its normal project log files.

Running tests

Build and test entry points live in the host repository (AsteroidFrameworkDevelop). Adapter unit tests (no Godot required):

dotnet test tests/Managed/Asteroid.GodotUnitTest.TestAdapter.Tests

The sample Godot project and the end-to-end validation live under tests/Godot/Asteroid.GodotUnitTest.E2E.Tests/ (sample-project TRX reconciliation, an expected-failure project, and a package layout smoke test). They require GODOT_BIN to point at a Godot Mono executable and skip cleanly (Assert.Inconclusive) when it is absent; they are minute-scale and invoked explicitly:

dotnet test tests/Godot/Asteroid.GodotUnitTest.E2E.Tests

Generated runner files

Before execution, the adapter injects a small Godot C# runner into the target project under:

AsteroidGodotUnitTestRunner/AsteroidGodotUnitTestRunnerScene.cs

This file is generated from the adapter package and should not be edited by hand. It is ignored by the sample project's .gitignore. The older .haze_godot_unit/ directory name is also ignored as a legacy generated location.

Package layout smoke test

The E2E suite (PackagesContainExpectedLayout) packs both projects in Release and asserts the package layout: the API dll, the adapter dll, the packaged runner template under lib/net8.0/Runner/, and the buildTransitive props file.

Compatibility policy

The 0.x compatibility promise covers the user-facing API and configuration surface: GodotTestAttribute, GodotTestCaseAttribute, GodotTestFixtureAttribute, lifecycle attributes, GodotCategoryAttribute, GodotRunModeAttribute, GodotRunModeEnum, GodotSceneTest, GodotSceneTestContext, and the documented runsettings schema.

The generated runner protocol DTOs and adapter internals are public only where the runner needs to share assembly contracts with the adapter. They are not intended for direct user code and may change between 0.x releases.

Before 1.0.0, the project should have successful feedback from at least two real Godot C# consumers, complete runsettings documentation, final public API review, and confirmed package-source policy (currently: official nuget.org).

Packing and release

Both projects carry self-contained package metadata (version, license, repository) and pack independently:

dotnet pack Asteroid.GodotUnitTest/Asteroid.GodotUnitTest.csproj -c Release -o artifacts/packages
dotnet pack Asteroid.GodotUnitTest.TestAdapter/Asteroid.GodotUnitTest.TestAdapter.csproj -c Release -o artifacts/packages

Packages are written to artifacts/packages/ and include symbol packages (.snupkg). Releases go to official nuget.org (dotnet nuget push ... --source https://api.nuget.org/v3/index.json --api-key $NUGET_API_KEY --skip-duplicate); note the Chinese NuGet mirror may lag the official feed by several minutes after a push.

Before pushing a 0.x package:

  1. Ensure package descriptions, README, and CHANGELOG.md describe the release accurately.
  2. Run the host repository test suites: adapter unit tests plus the E2E suite with GODOT_BIN set.
  3. Verify package consumption from a separate Godot C# project and confirm the adapter package exposes its runner template correctly.

Troubleshooting

Failure phase diagnostics

Failed test results may include a Failure phase: ... prefix in the TRX error message. This identifies where the runner was when the failure was recorded:

  • TestDiscovery, TestMetadata, or TestCaseArguments means the runner could not resolve the selected method or parameterized case metadata.
  • OneTimeSetUp, SetUp, Test, TearDown, OneTimeTearDown, Cleanup, or OneTimeCleanup points to the matching lifecycle or cleanup step.
  • SceneContext or FixtureConstruction means the temporary scene root or fixture instance could not be created.
  • Runner means the Godot runner failed before it could produce normal per-test results.

When the Godot process exits unexpectedly, the adapter includes a summarized copy of Godot standard output and standard error in the failure message so the root cause is visible from dotnet test or TRX output.

At normal verbosity and above, execution also reports the effective runsettings summary, selected test count, project root, run mode, and mixed run mode process grouping.

Godot executable not found

Set GODOT_BIN to the Godot Mono executable, or add <GodotBin> under <AsteroidGodotUnitTest> in .runsettings. The adapter reports both the configured and expanded path when the file is missing.

project.godot not found

If GodotProjectPath is omitted, the adapter walks upward from the discovered test assembly until it finds project.godot. If your test assembly is outside the Godot project directory, configure an absolute GodotProjectPath in .runsettings.

Adapter not discovered

Ensure the Godot test project references Microsoft.NET.Test.Sdk and either references Asteroid.GodotUnitTest.TestAdapter as a package or points TestAdaptersPaths at the local adapter output during project-reference development. Package consumers should not need TestAdaptersPaths.

Runner template not found

The adapter first looks for the runner template as an embedded resource, then near the adapter assembly and test output. Package consumers rely on the adapter package's buildTransitive props file to copy AsteroidGodotUnitTestRunnerScene.cs.template into the output directory. Rebuild/restore the consumer project if the copied template is stale or missing.

Stale generated runner

AsteroidGodotUnitTestRunner/AsteroidGodotUnitTestRunnerScene.cs is generated. If template changes are not reflected, delete the generated AsteroidGodotUnitTestRunner/ directory and rebuild before running tests again.

Duplicate NUnit discovery

Do not reference NUnit3TestAdapter in the same Godot test project unless you intentionally want NUnit to discover a separate set of tests. Asteroid.GodotUnitTest discovers Godot* attributes and can use NUnit assertions without the NUnit adapter.

Timeout expectations

TimeoutMilliseconds can fail awaited Task tests and methods that complete after their timeout. It cannot interrupt a synchronously blocked method before control returns to the runner; use ResultTimeoutMilliseconds or VSTest session timeout for process-level protection.

Deliberately out of scope for the current 0.x line

  • Advanced scene/input simulation helpers.
  • Named-pipe or streaming result protocol.
  • Reusing a long-lived Godot process.
  • Running pure .NET tests outside Godot.
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Asteroid.GodotUnitTest:

Package Downloads
Asteroid.GodotUnitTest.TestAdapter

VSTest adapter that discovers Asteroid.GodotUnitTest tests, runs them inside a Godot process, and reports results to dotnet test.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.7.0 187 9/16/2026
0.6.0 112 9/12/2026