Up to date
This page is up to date for Godot 4.2
.
If you still find outdated information, please open an issue.
Unit-Tests¶
Die Godot Engine ermöglicht das Schreiben von Unit-Tests direkt in C++. Die Engine integriert das doctest-Unit-Testing-Framework, das die Möglichkeit bietet, Test-Suites und Test-Cases neben dem Produktionscode zu schreiben. Da die Tests in Godot jedoch über einen anderen main
-Einstiegspunkt laufen, befinden sich die Tests stattdessen in einem eigenen tests/
-Verzeichnis, das sich im Stammverzeichnis des Quellcodes der Engine befindet.
Unterstützung von Plattformen und Targets¶
C++-Unit-Tests können auf Linux-, macOS- und Windows-Betriebssystemen ausgeführt werden.
Tests können nur mit aktivierten Editor-Tools
durchgeführt werden, was bedeutet, dass Exportvorlagen derzeit nicht getestet werden können.
Ausführen von Tests¶
Bevor die Tests tatsächlich ausgeführt werden können, muss die Engine mit der Build-Option tests
kompiliert werden (plus jede andere Build-Option, die Sie normalerweise verwenden), da die Tests nicht als Teil der Engine standardmäßig kompiliert werden:
scons tests=yes
Sobald der Build fertig ist, führen Sie die Tests mit der Kommandozeilenoption --test
aus:
./bin/<godot_binary> --test
Der Testlauf kann mit den verschiedenen doctest-spezifischen Kommandozeilenoptionen konfiguriert werden. Um die vollständige Liste der unterstützten Optionen zu erhalten, führen Sie den Befehl --test
mit der Option --help
aus:
./bin/<godot_binary> --test --help
Alle anderen Optionen und Argumente nach dem Befehl --test
werden als Argumente für doctest behandelt.
Bemerkung
Tests werden automatisch kompiliert, wenn Sie die dev_mode=yes
SCons Option verwenden. dev_mode=yes
wird empfohlen, wenn Sie vorhaben, zur Entwicklung der Engine beizutragen, da Compilerwarnungen automatisch als Fehler behandelt werden. Das Continuous-Integration-System wird fehlschlagen, wenn Compilerwarnungen entdeckt werden, daher sollten Sie sich bemühen, alle Warnungen zu beheben, bevor Sie einen Pull Request erstellen.
Filtern von Tests¶
Standardmäßig werden alle Tests ausgeführt, wenn Sie keine zusätzlichen Argumente nach dem --test
Befehl angeben. Wenn Sie jedoch neue Tests schreiben oder die Ausgabe der erfolgreichen Assertions aus diesen Tests zu Debugging-Zwecken sehen möchten, können Sie die Tests, die Sie interessieren, mit den verschiedenen Filteroptionen von doctest ausführen.
Die Wildcard-Syntax *
wird für die Suche nach einer beliebigen Anzahl von Zeichen in Testsuiten, Testfällen und Quellcode-Dateinamen unterstützt:
Filter-Optionen |
Abkürzung |
Beispiele |
|
|
|
|
|
|
|
|
|
Um zum Beispiel nur die String
-Unit-Tests auszuführen, führen Sie aus:
./bin/<godot_binary> --test --test-case="*[String]*"
Die Ausgabe erfolgreicher Assertions kann mit der Option --success
(-s
) aktiviert werden und kann z.B. mit jeder Kombination der oben genannten Filteroptionen kombiniert werden:
./bin/<godot_binary> --test --source-file="*test_color*" --success
Bestimmte Tests können mit den entsprechenden -exclude
Optionen übersprungen werden. Zur Zeit beinhalten einige Tests zufällige Stresstests, die eine gewisse Zeit zur Ausführung benötigen. Um diese Art von Tests zu überspringen, führen Sie den folgenden Befehl aus:
./bin/<godot_binary> --test --test-case-exclude="*[Stress]*"
Schreiben von Tests¶
Test-Suites sind C++ Headerdateien, die als Teil des Haupteinstiegspunktes in tests/test_main.cpp
eingebunden werden müssen. Die meisten Test-Suites befinden sich direkt im Verzeichnis tests/
.
Allen Header-Dateien wird das Präfix test_
vorangestellt. Dies ist eine Namenskonvention, auf die sich das Godot-Buildsystem verlässt, um Tests in der gesamten Engine zu erkennen.
Hier ist eine minimale funktionierende Testsuite mit einem einzigen geschriebenen Test-Case:
#ifndef TEST_STRING_H
#define TEST_STRING_H
#include "tests/test_macros.h"
namespace TestString {
TEST_CASE("[String] Hello World!") {
String hello = "Hello World!";
CHECK(hello == "Hello World!");
}
} // namespace TestString
#endif // TEST_STRING_H
Der Header tests/test_macros.h
kapselt alles, was zum Schreiben von C++-Unit-Tests in Godot benötigt wird. Er enthält Doctest-Assertion- und Logging-Makros wie CHECK
(siehe oben) und natürlich die Definitionen zum Schreiben von Test-Cases selbst.
Siehe auch
tests/test_macros.h Quellcode für derzeit implementierte Makros und Aliase für diese Makros.
Test-Cases werden mit dem funktionsähnlichen Makro TEST_CASE
erstellt. Jeder Test-Case muss eine kurze Beschreibung in Klammern haben, optional mit eigenen Tags, die es erlauben, die Tests zur Laufzeit zu filtern, wie [String]
, [Stress]
usw.
Test-Cases werden in einem eigenen Namespace geschrieben. Dies ist nicht erforderlich, ermöglicht es aber, Namenskollisionen zu vermeiden, wenn andere statische Hilfsfunktionen geschrieben werden, um sich wiederholende Testverfahren unterzubringen, wie z.B. das Auffüllen gemeinsamer Testdaten für jeden Test oder das Schreiben parametrisierter Tests.
Godot unterstützt das Schreiben von Tests pro C++-Modul. Anweisungen zum Schreiben von Modultests finden Sie in Schreiben von benutzerdefinierten Unit-Tests.
Assertions¶
Eine Liste aller häufig verwendeten Assertions, die in den Godot-Tests verwendet werden, sortiert nach Schweregrad.
Assertion |
Beschreibung |
|
Testet, ob die Bedingung erfüllt ist. Der gesamte Test schlägt sofort fehl, wenn die Bedingung nicht zutrifft. |
|
Testet, wenn die Bedingung nicht erfüllt ist. Der gesamten Test schlägt sofort fehl, wenn die Bedingung erfüllt ist. |
|
Testet, ob die Bedingung erfüllt ist. Markiert den Testlauf als fehlgeschlagen, erlaubt aber die Ausführung anderer Assertions. |
|
Testet, ob die Bedingung nicht erfüllt ist. Markiert den Testlauf als fehlgeschlagen, erlaubt aber die Ausführung anderer Assertions. |
|
Testet, ob die Bedingung erfüllt ist. Lässt den Test unter keinen Umständen fehlschlagen, gibt aber eine Warnung aus, etwas nicht "true" ergibt. |
|
Testet, ob die Bedingung nicht zutrifft. Lässt den Test unter keinen Umständen fehlschlagen, gibt aber eine Warnung aus, wenn etwas "true" ergibt. |
Alle oben genannten Assertions haben entsprechende *_MESSAGE
-Makros, die es erlauben, eine optionale Nachricht mit der Begründung auszugeben, was erwartet wird.
Bevorzugen Sie CHECK
für selbsterklärende Assertions und CHECK_MESSAGE
für komplexere, wenn Sie denken, dass diese eine bessere Erklärung verdienen.
Siehe auch
Logging¶
Die Testausgabe wird von doctest selbst gehandhabt und verlässt sich nicht auf die Print- oder Logging-Funktionalität von Godot. Es wird daher empfohlen, spezielle Makros zu verwenden, die es ermöglichen, die Testausgabe in einem von doctest geschriebenen Format zu loggen.
Makro |
Beschreibung |
|
Gibt eine Nachricht aus. |
|
Markiert den Test als fehlgeschlagen, setzt aber die Ausführung fort. Kann für komplexe Prüfungen in Conditionals verpackt werden. |
|
Der Test schlägt sofort fehl. Kann für komplexe Prüfungen in Conditionals verpackt werden. |
Zur Laufzeit können verschiedene Reporter gewählt werden. So kann zum Beispiel die Ausgabe in eine XML-Datei umgeleitet werden:
./bin/<godot_binary> --test --source-file="*test_validate*" --success --reporters=xml --out=doctest.txt
Siehe auch
Testen von Fehlerpfaden¶
Manchmal ist es nicht möglich, auf ein erwartetes Ergebnis zu testen. Da die Godot-Entwicklungsphilosophie vorsieht, dass die Engine nicht abstürzen und sich bei Auftreten eines nicht-kritischen Fehlers ordnungsgemäß erholen soll, ist es wichtig zu prüfen, ob diese Fehlerpfade tatsächlich sicher ausgeführt werden können, ohne dass die Engine abstürzt.
Unerwartetes Verhalten kann auf die gleiche Weise getestet werden wie alles andere. Das einzige Problem, das dadurch entsteht, ist, dass der Fehlertext die Testausgabe unnötig mit Fehlern vermüllt, die von der Engine selbst stammen (selbst wenn das Endergebnis erfolgreich ist).
Um dieses Problem zu umgehen, können Sie die Makros ERR_PRINT_OFF
und ERR_PRINT_ON
direkt in den Testfällen verwenden, um z.B. die Fehlerausgabe der Engine vorübergehend zu deaktivieren:
TEST_CASE("[Color] Constructor methods") {
ERR_PRINT_OFF;
Color html_invalid = Color::html("invalid");
ERR_PRINT_ON; // Don't forget to re-enable!
CHECK_MESSAGE(html_invalid.is_equal_approx(Color()),
"Invalid HTML notation should result in a Color with the default values.");
}
Test-Tools¶
Test-Tools sind fortgeschrittene Methoden, die es Ihnen ermöglichen, beliebige Prozeduren auszuführen, um den Prozess des manuellen Testens und des Debuggens der Engine-Interna zu erleichtern.
Diese Tools können durch die Angabe des Namens eines Tools nach der --test
Kommandozeilenoption gestartet werden. Zum Beispiel implementiert und registriert das GDScript-Modul mehrere Tools, die bei der Fehlersuche im Tokenizer, Parser und Compiler helfen:
./bin/<godot_binary> --test gdscript-tokenizer test.gd
./bin/<godot_binary> --test gdscript-parser test.gd
./bin/<godot_binary> --test gdscript-compiler test.gd
Wird ein solches Tool entdeckt, werden die restlichen Unit-Tests übersprungen.
Test-Tools können überall in der Engine registriert werden, da der Registrierungsmechanismus dem von doctest ähnelt, wenn Testfälle mit dynamischer Initialisierungstechnik registriert werden, aber normalerweise können diese in den entsprechenden register_types.cpp
-Quellen (pro Modul oder Kern) registriert werden.
Hier ist ein Beispiel dafür, wie GDScript Test-Tools in modules/gdscript/register_types.cpp
registriert:
#ifdef TESTS_ENABLED
void test_tokenizer() {
TestGDScript::test(TestGDScript::TestType::TEST_TOKENIZER);
}
void test_parser() {
TestGDScript::test(TestGDScript::TestType::TEST_PARSER);
}
void test_compiler() {
TestGDScript::test(TestGDScript::TestType::TEST_COMPILER);
}
REGISTER_TEST_COMMAND("gdscript-tokenizer", &test_tokenizer);
REGISTER_TEST_COMMAND("gdscript-parser", &test_parser);
REGISTER_TEST_COMMAND("gdscript-compiler", &test_compiler);
#endif
Das benutzerdefinierte Parsen der Kommandozeile kann von einem Test-Tool selbst mit Hilfe der Methode OS get_cmdline_args durchgeführt werden.
Integrationstests für GDScript¶
Godot verwendet doctest, um Regressions-Bugs in GDScript während der Entwicklung zu verhindern. Es gibt mehrere Arten von Testskripten, die geschrieben werden können:
Tests für erwartete Fehler;
Tests für Warnungen;
Tests für Performancemerkmale.
Der Prozess der Erstellung von Integrationstests für GDScript sieht daher wie folgt aus:
Wählen Sie einen Typ eines Testskripts, das Sie schreiben möchten, und erstellen Sie eine neue GDScript-Datei im Verzeichnis
modules/gdscript/tests/scripts
im entsprechenden Unterverzeichnis.Schreiben Sie GDScript-Code. Das Testskript muss eine Funktion namens
test()
enthalten, die keine Argumente benötigt. Diese Funktion wird vom Test-Runner aufgerufen. Der Test sollte keine Abhängigkeiten haben, es sei denn, sie sind auch Teil des Tests. Globale Klassen (mitclass_name
) werden vor dem Start des Test-Runners registriert, so dass diese bei Bedarf funktionieren sollten.Hier ist ein Beispiel für ein Testskript:
func test(): if true # Missing colon here. print("true")
Wechseln Sie in das Stammverzeichnis des Godot-Quellcode-Repositorys.
cd godot
Erzeugen Sie
*.out
-Dateien, um die erwarteten Ergebnisse der Ausgabe zu aktualisieren:bin/<godot_binary> --gdscript-generate-tests modules/gdscript/tests/scripts
Sie können die Option --print-filenames
hinzufügen, um die Dateinamen zu sehen, während die Testausgaben erzeugt werden. Wenn Sie an einem neuen Feature arbeiten, die schwere Abstürze verursacht, können Sie diese Option verwenden, um schnell herauszufinden, welche Testdatei den Absturz verursacht, und von dort aus debuggen.
Führen Sie GDScript-Tests aus mit:
./bin/<godot_binary> --test --test-suite="*GDScript*"
Dies akzeptiert auch die Option --print-filenames
(siehe oben).
Wenn keine Fehler ausgegeben werden und alles gut geht, sind Sie fertig!
Warnung
Vergewissern Sie sich, dass die Ausgabe die erwarteten Werte hat, bevor Sie einen Pull Request einreichen. Wenn --gdscript-generate-tests
*.out
-Dateien erzeugt, die nichts mit den neu hinzugefügten Tests zu tun haben, sollten Sie diese Dateien reverten und nur *.out
Dateien für neue Tests committen.
Bemerkung
Der GDScript-Testrunner ist zum Testen der GDScript-Implementierung gedacht, nicht zum Testen von Benutzerskripten oder zum Testen der Engine mithilfe von Skripten. Wir empfehlen, neue Tests für bereits gelöste Issues im Zusammenhang mit GDScript auf GitHub zu schreiben, oder Tests für derzeit in Arbeit befindliche Features zu schreiben.
Bemerkung
Wenn Ihr Test Case erfordert, dass innerhalb der Skriptdatei keine test()
Funktion vorhanden ist, können Sie den Laufzeitabschnitt des Tests deaktivieren, indem Sie die Skriptdatei so benennen, dass sie dem Muster *.notest.gd
entspricht. Zum Beispiel: "test_empty_file.notest.gd".