Chickensoft.GoDotTest
0.0.2
See the version list below for details.
dotnet add package Chickensoft.GoDotTest --version 0.0.2
NuGet\Install-Package Chickensoft.GoDotTest -Version 0.0.2
<PackageReference Include="Chickensoft.GoDotTest" Version="0.0.2" />
paket add Chickensoft.GoDotTest --version 0.0.2
#r "nuget: Chickensoft.GoDotTest, 0.0.2"
// Install Chickensoft.GoDotTest as a Cake Addin #addin nuget:?package=Chickensoft.GoDotTest&version=0.0.2 // Install Chickensoft.GoDotTest as a Cake Tool #tool nuget:?package=Chickensoft.GoDotTest&version=0.0.2
GoDotTest
An opinionated test runner system to make running C# tests easier in Godot. Supports code coverage and debugging in-editor.
Installation
Find the latest version of GoDotTest on nuget.
Add the latest version of GoDotTest to your *.csproj
file. Make sure to replace *VERSION*
with the latest version.
<ItemGroup>
<PackageReference Include="Chickensoft.GoDotTest" Version="*VERSION*" />
</ItemGroup>
You can use GoDotTest with C# 10 and Godot to run, debug, and collect code coverage for your project inside Godot.
For C# 10 to work, you need the dotnet 6 SDK installed. See what you have installed with dotnet --info
. On mac, Godot 3 can have trouble finding .NET 6 if you have older SDK's installed, due to the dotnet path search order. There are also a few work-arounds available.
This project uses git submodules to bring in the code for the Godot addons, since some of the addons are still in development. Be sure to run git submodule update --init --recursive
once you've cloned the repo to pull in all the addon code.
Example Test
Here's a simple test which does absolutely nothing. It can use the TestScene
node available to it from its base class to manipulate the scene tree, if needed.
using Godot;
using GoDotNet;
using GoDotTest;
public class ExampleTest : TestClass {
private readonly ILog _log = new GDLog(nameof(ExampleTest));
public ExampleTest(Node testScene) : base(testScene) { }
[SetupAll]
public void SetupAll() => _log.Print("Setup everything");
[Setup]
public void Setup() => _log.Print("Setup");
[Test]
public void Test() => _log.Print("Test");
[Cleanup]
public void Cleanup() => _log.Print("Cleanup");
[CleanupAll]
public void CleanupAll() => _log.Print("Cleanup everything");
}
Here's the output of the test above:
Setup
You can debug tests in Godot from Visual Studio Code. To do this, you will need to specify the GODOT
environment variable for the following launch configurations and scripts to work correctly. The GODOT
variable should point to the path of the Godot executable.
You will need to include something like this in your .zshrc
or .bash_profile
file.
# Dotnet
export DOTNET_CLI_TELEMETRY_OPTOUT=1 # Disable analytics
DOTNET_ROOT="/usr/local/share/dotnet"
# Mono
export PATH="/Library/Frameworks/Mono.framework/Versions/Current/Commands/mono:$PATH"
export PATH="$HOME/.dotnet/tools:$PATH"
# For dotnet 6 SDK:
export PATH="/usr/local/share/dotnet:/usr/local/share/dotnet/sdk:$PATH"
# Godot
# Path go Godot executable, on mac it might look like this:
export GODOT="/Applications/Godot.app/Contents/MacOS/Godot"
Debugging
The following launch.json
file provides launch configurations to debug the game, debug all the tests, or debug the currently open test in Visual Studio Code. To debug the currently open test, make sure the class name of the test matches the file name, as is typical in C#.
You can also just copy and paste
.vscode/launch.json
and.vscode/tasks.json
from this repository into your own project that uses GoDotTest.
{
"version": "0.2.0",
"configurations": [
{
"name": "Play in Editor",
"type": "godot-mono",
"mode": "playInEditor",
"request": "launch"
},
// We tell the game to run tests by using command line arguments.
// This means we can't use the "play in editor" option — we have to launch
// our own instance of Godot.
//
// Since passing scene files to Godot doesn't seem to work easily with the
// C# Tools for Godot VSCode plugin, we use the path to Godot from the
// environment. Make sure you set the GODOT variable to your Godot
// executable.
//
// On mac, you can add the following to your zsh rc file:
// alias godot="/Applications/Godot.app/Contents/MacOS/Godot"
{
"name": "Debug Tests",
"type": "godot-mono",
"mode": "executable",
"request": "launch",
"executable": "${env:GODOT}",
"executableArguments": [
"--run-tests",
"--quit-on-finish"
],
"preLaunchTask": "build"
},
// Debug the current test!
//
// The test runner will look for the class with the same name as the test
// file that's currently open (disregarding its folder and file extension).
// The search is case-insensitive.
{
"name": "Debug Current Test",
"type": "godot-mono",
"mode": "executable",
"request": "launch",
"executable": "${env:GODOT}",
"executableArguments": [
"--run-tests=${fileBasenameNoExtension}",
"--quit-on-finish"
],
"preLaunchTask": "build"
},
{
"name": "Launch",
"type": "godot-mono",
"request": "launch",
"mode": "executable",
"preLaunchTask": "build",
"executable": "/Applications/Godot.app/Contents/MacOS/Godot",
"executableArguments": [
"--path",
"${workspaceRoot}"
]
},
{
"name": "Launch (Select Scene)",
"type": "godot-mono",
"request": "launch",
"mode": "executable",
"preLaunchTask": "build",
"executable": "/Applications/Godot.app/Contents/MacOS/Godot",
"executableArguments": [
"--path",
"${workspaceRoot}",
"${command:SelectLaunchScene}"
]
},
{
"name": "Attach",
"type": "godot-mono",
"request": "attach",
"address": "localhost",
"port": 23685
}
]
}
Note: You will also need the accompanying tasks.json
(below) to be able to build the game before running the debug configurations for testing.
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build"
],
"problemMatcher": "$msCompile",
"presentation": {
"echo": true,
"reveal": "silent",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": false
}
}
]
}
Test Scene
Create a test
folder in your project and create a test scene in it. Add a C# script to the root of the test scene with the following contents:
using Godot;
using GoDotNet;
using GoDotTest;
public class Tests : Node2D {
public override async void _Ready() => await GoTest.RunTests(
Assembly.GetExecutingAssembly(),
this, TestEnvironment.From(OS.GetCmdlineArgs()), new GDLog(nameof(Tests))
);
}
Main Scene
In your main scene, you need to determine if tests should be run. GoDotTest relies on the presence of certain command line arguments to determine if tests should be run.
In your main scene, you should construct a test environment from the command line arguments and determine if tests should be run. If they are, you can switch to the test scene. Otherwise, you can switch to the game scene. If you've written your own scene switching system, you can adapt this file to use that accordingly.
using Godot;
using GoDotTest;
public class Main : Node2D {
public override void _Ready() {
var testEnv = TestEnvironment.From(OS.GetCmdlineArgs());
if (testEnv.ShouldRunTests) {
GetTree().ChangeScene("res://test/Tests.tscn");
}
else {
GetTree().ChangeScene("res://scenes/Game.tscn");
}
}
}
Logging
Make sure you add this to your project.godot
file so you can see test logs when they're running.
[network]
; Required to see all the logs when tests are running!
limits/debugger_stdout/max_chars_per_second=200000
limits/debugger_stdout/max_messages_per_frame=500
limits/debugger_stdout/max_errors_per_second=500
limits/debugger_stdout/max_warnings_per_second=500
Assertions and Mocking
GoDotTest doesn't provide any assertions or mocking. It's simply a test provider and test running system. Eventually, GoDotTest will include a few asynchronous utilities to make integration testing scenes easier, allowing you to simulate frames, input, etc, but there are no plans to ever provide an assertion or mocking system — you can use whatever you like!
Coverage
If your code is configured correctly to switch to the test scene when --run-tests
is passed in (see above), you can run all of your tests and generate code coverage while Godot is running.
First, install coverlet and reportgenerator.
dotnet tool install --global dotnet-reportgenerator-globaltool
dotnet tool install --global coverlet.console
# Do this too if you're on an M1 mac / ARMx64 system:
# Works around https://github.com/dotnet/efcore/issues/27787#issuecomment-1110061226
dotnet tool update --global coverlet.console
To run Godot with code coverage enabled, use a script like the following (or reference the local coverage.sh
.
coverlet .mono/temp/bin/Debug/ --target $GODOT --targetargs \
"--run-tests --quit-on-finish" --format "lcov" \
--output ./coverage/coverage.info \
--exclude-by-file "**/test/**/*.cs" # Don't collect coverage for the tests
reportgenerator \
-reports:"./coverage/coverage.info" \
-targetdir:"./coverage/report" \
-reporttypes:Html
# Open the coverage report in your browser.
open coverage/report/index.html
Note: On macOS, you may need to run chmod +x ./coverage.sh
to add execution permissions before you are able to run the coverage.sh
script.
How It Works
GoDotTest uses C# Reflection to find all classes in the current assembly that extend the TestClass
it provides. It uses a TestProvider
to find and load test suites (classes that extend TestClass
) that can be run. It references a TestEnvironment
that is created from the command line arguments given to the game/Godot and filters the test suites based on the presence of a test suite name, if given.
GoDotTest uses a TestExecutor
to run methods in the order they are declared in a TestClass
. Test methods are denoted with the [Test]
attribute.
Test output is displayed by a TestReporter
which responds to test events.
Auxiliary methods, such as Setup
and Cleanup
are run before and after each test, respectively. They can be specified with the [Setup]
and [Cleanup]
attributes on methods in a TestClass
.
Additionally, any methods tagged with the [SetupAll]
or [CleanupAll]
attributes will be run once at the start of the test suite and once at the end, respectively.
GoDotTest will await
any async Task
test methods it encounters. Tests do not run in parallel, nor are there any plans to add that functionality. The focus of GoDotTest is to provide a simple, C#-first approach to testing in Godot that runs tests in a very simple and deterministic manner.
If you need to customize how tests are loaded and run, you can use the code in addons/go_dot_test/GoTest.cs
as a starting point.
Command Line Arguments
--run-tests
: The presence of this flag informs your game that tests should be run. If you've setup your main scene to redirect to the test scene when it finds this flag (as described above), you can use pass this flag in when running Godot from the command line (for debugging or CI/CD purposes) to run your test(s).--quit-on-finish
: The presence of this flag indicates that the test runner should exit the application as soon as it is finished running tests.--stop-on-error
: The presence of this flag indicates that the test runner should stop running tests when it encounters the first error in any test suite. Without this flag, it will attempt to run all of the test suites.--sequential
: The presence of this flag indicates that subsequent test methods in a test suite should be skipped if an error occurs in a test suite method. Use this if your test methods rely on the previous test method completing successfully. This flag is ignored when using--stop-on-error
.
For more information about command line flags, see addons/go_dot_test/TestEnvironment.cs
.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. |
.NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Chickensoft.GoDotCollections (>= 0.0.2)
- Chickensoft.GoDotLog (>= 0.0.4)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Chickensoft.GoDotTest:
Package | Downloads |
---|---|
RBG_GodotTools_AutoTest
RBG_GodotTools_AutoTest description. |
GitHub repositories (3)
Showing the top 3 popular GitHub repositories that depend on Chickensoft.GoDotTest:
Repository | Stars |
---|---|
chickensoft-games/GameDemo
The Chickensoft Game Demo — a fully tested, third-person 3D game built with Godot and C#. Now with saving and loading!
|
|
chickensoft-games/GodotEnv
Manage Godot versions and addons from the command line on Windows, macOS, and Linux.
|
|
chickensoft-games/AutoInject
Node-based dependency injection for C# Godot scripts at build-time, including utilities for automatic node-binding, additional lifecycle hooks, and .net-inspired notification callbacks.
|
Version | Downloads | Last updated |
---|---|---|
1.5.10 | 4,541 | 8/15/2024 |
1.5.9-godot4.3.0-rc.3 | 171 | 8/8/2024 |
1.5.8-godot4.3.0-rc.2 | 75 | 8/1/2024 |
1.5.7-godot4.3.0-rc.1 | 134 | 7/25/2024 |
1.5.6-godot4.3.0-beta.3 | 165 | 7/9/2024 |
1.5.5-godot4.3.0-beta.2 | 124 | 6/20/2024 |
1.5.4-godot4.3.0-beta.1 | 192 | 5/31/2024 |
1.5.3 | 1,487 | 5/15/2024 |
1.5.2 | 8,641 | 4/17/2024 |
1.5.1-godot4.2.2-rc.2 | 166 | 3/13/2024 |
1.5.0-godot4.2.2-rc.1 | 207 | 2/1/2024 |
1.4.1-godot4.2.2-rc.1 | 80 | 1/26/2024 |
1.4.0 | 3,883 | 12/18/2023 |
1.3.6 | 626 | 12/12/2023 |
1.3.5-godot4.2.1-rc.1 | 137 | 12/7/2023 |
1.3.4 | 1,112 | 11/30/2023 |
1.3.3-godot4.2.0-rc.2 | 112 | 11/25/2023 |
1.3.2-godot4.2.0-beta.5 | 600 | 11/7/2023 |
1.3.1-godot4.2.0-beta.3 | 100 | 10/27/2023 |
1.3.0-godot4.2.0-beta.2 | 97 | 10/20/2023 |
1.2.4-godot4.2.0-beta.2 | 81 | 10/19/2023 |
1.2.3 | 3,256 | 10/4/2023 |
1.2.2-godot4.1.2-rc.1 | 137 | 9/22/2023 |
1.2.1 | 506 | 9/4/2023 |
1.2.0 | 169 | 8/29/2023 |
1.1.19 | 235 | 8/21/2023 |
1.1.18 | 9,396 | 7/21/2023 |
1.1.17 | 1,296 | 7/7/2023 |
1.1.16-godot4.1.0-rc.3 | 145 | 7/4/2023 |
1.1.15-godot4.1.0-rc.2 | 145 | 6/30/2023 |
1.1.14-godot4.1.0-rc.1 | 130 | 6/27/2023 |
1.1.13-godot4.1.0-beta.3 | 121 | 6/22/2023 |
1.1.12-godot4.1.0-beta.2 | 119 | 6/14/2023 |
1.1.11-godot4.1.0-beta.1 | 116 | 6/7/2023 |
1.1.10 | 317 | 5/19/2023 |
1.1.9-godot4.0.3-rc.2 | 112 | 5/17/2023 |
1.1.8-godot4.0.3-rc.1 | 120 | 4/27/2023 |
1.1.7 | 601 | 4/4/2023 |
1.1.6-godot4.0.2-rc.1 | 805 | 4/3/2023 |
1.1.5 | 203 | 4/3/2023 |
1.1.4 | 1,182 | 4/3/2023 |
1.1.2-godot.4.beta.16 | 2,315 | 1/30/2023 |
1.1.2-beta8 | 183 | 12/17/2022 |
1.1.2-beta6 | 100 | 11/25/2022 |
1.1.2-beta.4.0.0.17 | 702 | 2/6/2023 |
1.1.2-beta.4.0.0.16 | 170 | 2/6/2023 |
1.1.1-beta6 | 96 | 11/25/2022 |
1.1.0-beta6 | 95 | 11/24/2022 |
1.0.0 | 507 | 9/17/2022 |
0.0.4 | 485 | 6/19/2022 |
0.0.3 | 404 | 6/19/2022 |
0.0.2 | 395 | 6/19/2022 |
0.0.1 | 440 | 6/19/2022 |
Initial release.