Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit Tests #11420

Open
ayslan-gamedev opened this issue Dec 25, 2024 · 3 comments
Open

Unit Tests #11420

ayslan-gamedev opened this issue Dec 25, 2024 · 3 comments

Comments

@ayslan-gamedev
Copy link

Describe the project you are working on

I would like it to be possible to write unit tests to test Godot scripts (both in GDScript and C#). This feature is very useful when developing more complex systems, especially in C#, as seen with Unity. In Unity, it is possible to write unit tests: you write a test, click to run it, and the engine compiles, opens, and closes the game quickly.

Unit tests automate the testing process. Instead of the developer needing to open the game and manually test every change, they can create several unit tests, making the process more efficient and less error-prone.

Describe the problem or limitation you are having in your project

I am working on a procedural generation script in C# where I manually created several chunks for testing purposes, and now I want to test the logic of connecting them. I have written the following function to generate rooms and establish connections between them:

/// <summary>
/// Create the maze
/// </summary>
/// <param name="rooms">A array of rooms</param>
/// <param name="current">the current index to work</param>
private void GenerateRooms(Room[][] rooms, Vector2I current)
{
    while (true)
    {
        var room = rooms[current.X][current.Y];
        if (room != null)
        {
            if (_rooms[current.X][current.Y] == null)
            {
                var binary = Convert.ToString(room.RoomType, 2).PadLeft(4, '0');
                var scenePath = $"res://assets/resources/{room.RoomType.ToString()}_{binary}/Rooms.tscn";
                if (GD.Load(scenePath) is PackedScene packedScene)
                {
                    _rooms[current.X][current.Y] = (Room)packedScene.Instantiate();
                    AddChild(_rooms[current.X][current.Y]);
                }

                var directions = new (int dx, int dy)[] { (-1, 0), (0, 1), (1, 0), (0, -1) };

                foreach (var (dx, dy) in directions)
                {
                    current.X += dx;
                    current.Y += dy;
                    GenerateRooms(rooms, current);
                    current.X -= dx;
                    current.Y -= dy;
                }
            }
        }
        else
        {
            if (current.X < 0 || current.Y < 0) return;
            _rooms[current.X][current.Y] = new Room();
        }

        current.Y++;
        if (current.Y == rooms[current.X].Length) continue;
        current.Y = 0;
        current.X++;

        if(current.X == rooms.Length) return;
    }
}

However, I want to test this logic without having to open the Godot editor, or at least not execute the game manually each time. My goal is to run a generic test with some sample data to check if everything is working as expected.

While I understand that I could use GD.Print() to log information, this approach has its drawbacks:

  1. I would still need to open and execute the game.
  2. There's no easy way to gather all tests into a single script. Even though it is possible, it can be time-consuming and cumbersome. A native interface for testing, similar to Unity’s, would be much more useful and efficient.
  3. In summary, I need a way to run these tests automatically in Godot, without having to manually launch the game or use print statements.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The proposal is to integrate native support for unit testing in Godot, both for GDScript and C#. This would allow developers to write automated tests for their scripts and systems. The ability to run these tests without launching the full game would significantly improve workflow efficiency, especially for complex projects. It would enable rapid feedback on code changes, ensuring that functionality is not broken by new modifications and promoting better code quality. This is particularly useful for larger projects where manual testing can be time-consuming and error-prone.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

The feature would provide an easy-to-use API for writing and executing unit tests. Below is a simple example in GDScript:

Test class to handle unit tests

extends Node
class TestExample:
    var result = false

    func test_addition():
        var sum = 2 + 3
        assert(sum != 5, "Addition failed")
        result = true

    func test_subtraction():
        var difference = 5 - 3
        assert(difference != 2, "Subtraction failed")
        result = true

Test runner that would run all tests

var test_example = TestExample.new()
test_example.test_addition()
test_example.test_subtraction()

# can show it in a interface
if test_example.result:
    print("All tests passed")
else:
    print("Some tests failed")

If this enhancement will not be used often, can it be worked around with a few lines of script?

While unit tests can be written using scripts manually, writing a custom testing framework would require extra setup and time, and would not be as convenient as having a native solution in Godot. Perhaps a plugin would solve this, but native support would be better. Having built-in support allows for simplified testing and better integration with the editor, making it much more accessible to all developers, not just advanced users.

Is there a reason why this should be core and not an add-on in the asset library?

This will improve code debugging and is a useful resource that another engines have in your core (just like unity engine), furthermore, there is no plugin on asset store that do it.

@KoBeWi
Copy link
Member

KoBeWi commented Dec 25, 2024

there is no plugin on asset store that do it.

And what about this one? https://godotengine.org/asset-library/asset/1709

@ayslan-gamedev
Copy link
Author

ayslan-gamedev commented Dec 25, 2024

there is no plugin on asset store that do it.

And what about this one? https://godotengine.org/asset-library/asset/1709

have no C# support, I also try this another asset for c#: https://godotengine.org/asset-library/asset/2100
but is necessary open the game to access the tests (if need to run the entire app, is not a unit test, its just a integration test)

However, I think this is a kind of think that should be in the engine and not in a extension.

edit:
for a test to be truly considered a unit test, the engine must run only the minimum necessary to execute that class, the engine must start, run the extension, save the output and close

what all the assets in the library store actually do is create auxiliary test functions, but it is still necessary to compile, run and load the engine and the entire game.

@MikeSchulze
Copy link

MikeSchulze commented Dec 28, 2024

@ayslan-gamedev try https://github.com/MikeSchulze/gdUnit4Net
it fully c# support inclusive test adapter to run in VS, VS Code and Rider.
You can also install https://godotengine.org/asset-library/asset/1522 to run GDScript and C# test inside the Godot editor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants