Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

비트 시프트

Godot 엔진을 사용하면 C++에서 직접 단위 테스트를 작성할 수 있습니다. 엔진은 doctest 단위 테스트 프레임워크를 통합하여 프로덕션 코드 옆에 테스트 스위트 및 테스트 사례를 작성할 수 있는 기능을 제공하지만 Godot의 테스트는 다른 main 진입점을 거치기 때문에 테스트는 대신 엔진 소스 코드의 루트에 있는 전용 tests/ 디렉토리에 상주합니다.

플랫폼 지원

C++ 단위 테스트는 Linux, macOS 및 Windows 운영 체제에서 실행할 수 있습니다.

테스트는 tools 편집기가 활성화된 상태에서만 실행할 수 있습니다. 이는 현재 내보내기 템플릿을 테스트할 수 없음을 의미합니다.

씬 실행

테스트를 실제로 실행하기 전에 tests 빌드 옵션을 활성화한 상태로 엔진을 컴파일해야 합니다(및 일반적으로 사용하는 다른 빌드 옵션). 테스트는 기본적으로 엔진의 일부로 컴파일되지 않기 때문입니다.

scons tests=yes

빌드가 완료되면 --test 명령줄 옵션을 사용하여 테스트를 실행합니다.

./bin/<godot_binary> --test

테스트 실행은 다양한 doctest 관련 명령줄 옵션을 사용하여 구성할 수 있습니다. 지원되는 옵션의 전체 목록을 검색하려면 --help 옵션과 함께 --test 명령을 실행하세요.

./bin/<godot_binary> --test --help

--test 명령 뒤의 다른 모든 옵션과 인수는 doctest의 인수로 처리됩니다.

참고

dev_mode=yes SCons 옵션을 사용하면 테스트가 자동으로 컴파일됩니다. ``dev_mode=yes``는 컴파일 경고를 자동으로 오류로 처리하므로 엔진 개발에 기여할 계획이라면 권장됩니다. 컴파일 경고가 감지되면 지속적인 통합 시스템이 실패하므로 끌어오기 요청을 열기 전에 모든 경고를 수정하도록 노력해야 합니다.

파일 필터

기본적으로 --test 명령 뒤에 추가 인수를 제공하지 않으면 모든 테스트가 실행됩니다. 그러나 새 테스트를 작성 중이거나 디버깅 목적으로 해당 테스트에서 나오는 성공적인 어설션 출력을 보려면 doctest에서 제공하는 다양한 필터링 옵션을 사용하여 관심 있는 테스트를 실행할 수 있습니다.

와일드카드 구문 ``*``는 테스트 도구 모음, 테스트 사례 및 소스 파일 이름의 문자 수에 관계없이 일치하도록 지원됩니다.

필터 옵션

약어

예제

--test <test>

-ts

-ts="*[GDScript]*"

--no-docbase

-tc

String[]

--quiet

-sf

-sf="*test_color*"

예를 들어 String 단위 테스트만 실행하려면 다음을 실행합니다.

./bin/<godot_binary> --test --test-case="*[String]*"

성공적인 어설션 출력은 --success``(-s``) 옵션을 사용하여 활성화할 수 있으며 위의 필터링 옵션 조합과 결합할 수 있습니다. 예를 들면 다음과 같습니다.

./bin/<godot_binary> --test --source-file="*test_color*" --success

해당 -exclude 옵션을 사용하면 특정 테스트를 건너뛸 수 있습니다. 현재 일부 테스트에는 실행하는 데 시간이 걸리는 무작위 스트레스 테스트가 포함되어 있습니다. 이러한 종류의 테스트를 건너뛰려면 다음 명령을 실행하십시오.

./bin/<godot_binary> --test --test-case-exclude="*[Stress]*"

경고 시스템(Warning system)

Test suites represent C++ implementation files which must include the TEST_FORCE_LINK() macro. Most test suites are located directly under tests/ directory.

All test files are prefixed with test_, and this is a naming convention which the Godot build system relies on to detect tests throughout the engine.

다음은 단일 테스트 사례가 작성된 최소 작업 테스트 모음입니다.

#include "tests/test_macros.h"

TEST_FORCE_LINK(test_string)

namespace TestString {

TEST_CASE("[String] Hello World!") {
    String hello = "Hello World!";
    CHECK(hello == "Hello World!");
}

} // namespace TestString

참고

You can quickly generate new tests using the create_test.py script found in the tests/ directory. This script automatically creates a new test file with the required boilerplate code in the appropriate location. To view usage instructions, run the script with the -h flag.

tests/test_macros.h 헤더는 Godot에서 C++ 단위 테스트를 작성하는 데 필요한 모든 것을 캡슐화합니다. 여기에는 위에서 본 ``CHECK``와 같은 doctest 어설션 및 로깅 매크로와 물론 테스트 사례 자체를 작성하기 위한 정의가 포함됩니다.

테스트 케이스는 TEST_CASE 함수형 매크로를 사용하여 생성됩니다. 각 테스트 케이스에는 [String], [Stress] 등과 같이 런타임에 테스트를 필터링할 수 있는 사용자 정의 태그를 선택적으로 포함하여 괄호 안에 작성된 간단한 설명이 있어야 합니다.

테스트 케이스는 전용 네임스페이스에 작성됩니다. 이는 필수는 아니지만 각 테스트에 대한 공통 테스트 데이터 채우기 또는 매개변수화된 테스트 작성과 같은 반복 테스트 절차를 수용하기 위해 다른 정적 도우미 함수를 작성할 때 이름 지정 충돌을 방지할 수 있습니다.

Godot는 C++ 모듈별로 테스트 작성을 지원합니다. 모듈 테스트 작성 방법에 대한 지침은 :ref:`doc_custom_module_unit_tests`를 참조하세요.

하위 사례

약간의 변형만 있는 여러 테스트 사례에 대한 공통 설정이 있는 상황에서는 하위 사례가 매우 유용할 수 있습니다. 예는 다음과 같습니다.

TEST_CASE("[SceneTree][Node] Testing node operations with a very simple scene tree") {
    // ... common setup (e.g. creating a scene tree with a few nodes)
    SUBCASE("Move node to specific index") {
        // ... setup and checks for moving a node
    }
    SUBCASE("Remove node at specific index") {
        // ... setup and checks for removing a node
    }
}

``SUBCASE``는 ``TEST_CASE``가 처음부터 실행되도록 합니다. 하위 사례는 임의의 깊이로 중첩될 수 있지만 중첩을 한 수준 이하로 제한하는 것이 좋습니다.

버전

Godot 테스트 전반에 걸쳐 일반적으로 사용되는 모든 주장의 목록으로, 심각도에 따라 정렬됩니다.

버전

설명

REQUIRE

조건이 참인지 테스트합니다. 조건이 true가 아닌 경우 전체 테스트가 즉시 실패합니다.

REQUIRE_FALSE

조건이 참이 아닌지 테스트합니다. 조건이 true이면 전체 테스트가 즉시 실패합니다.

CHECK

조건이 참인지 테스트합니다. 테스트 실행을 실패로 표시하지만 다른 어설션을 실행하도록 허용합니다.

CHECK_FALSE

조건이 참이 아닌지 테스트합니다. 테스트 실행을 실패로 표시하지만 다른 어설션을 실행하도록 허용합니다.

WARN

조건이 참인지 테스트합니다. 어떠한 상황에서도 테스트에 실패하지 않지만, 사실이 아닌 경우 경고를 기록합니다.

WARN_FALSE

조건이 참이 아닌지 테스트합니다. 어떤 상황에서도 테스트에 실패하지 않지만, 사실인 경우 경고를 기록합니다.

위의 모든 주장에는 대응하는 *_MESSAGE 매크로가 있으며, 이를 통해 무슨 일이 일어나야 하는지에 대한 이론적 근거와 함께 선택적 메시지를 인쇄할 수 있습니다.

더 나은 설명이 필요하다고 생각되면 자체 설명이 가능한 주장에는 ``CHECK``를 사용하고 더 복잡한 주장에는 ``CHECK_MESSAGE``를 사용하는 것이 좋습니다.

디버깅

테스트 출력은 doctest 자체에 의해 처리되며 Godot 인쇄나 로깅 기능에 전혀 의존하지 않으므로 doctest가 작성한 형식으로 테스트 출력을 기록할 수 있는 전용 매크로를 사용하는 것이 좋습니다.

매크로

설명

MESSAGE

메시지를 인쇄합니다.

FAIL_CHECK

테스트를 실패로 표시하지만 실행을 계속합니다. 복잡한 검사를 위해 조건문으로 래핑될 수 있습니다.

FAIL

즉시 테스트에 실패합니다. 복잡한 검사를 위해 조건문으로 래핑될 수 있습니다.

런타임 시 다양한 리포터를 선택할 수 있습니다. 예를 들어 출력을 XML 파일로 리디렉션하는 방법은 다음과 같습니다.

./bin/<godot_binary> --test --source-file="*test_validate*" --success --reporters=xml --out=doctest.txt

번역 가져오기

예상 결과를 테스트하는 것이 항상 가능한 것은 아닙니다. 엔진이 충돌해서는 안 되며 치명적이지 않은 오류가 발생할 때마다 정상적으로 복구해야 한다는 Godot 개발 철학을 통해 해당 오류 경로가 엔진 충돌 없이 실행하기에 실제로 안전한지 확인하는 것이 중요합니다.

예기치 않은 동작은 다른 것과 동일한 방식으로 테스트할 수 있습니다. 이로 인해 발생하는 유일한 문제는 오류 인쇄가 엔진 자체에서 발생하는 오류로 테스트 출력을 불필요하게 오염시킨다는 것입니다(최종 결과가 성공하더라도).

이 문제를 완화하려면 테스트 사례 내에서 ERR_PRINT_OFFERR_PRINT_ON 매크로를 직접 사용하여 엔진에서 나오는 오류 출력을 일시적으로 비활성화하세요. 예:

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.");
}

테스트 케이스 이름의 특수 태그

이러한 태그를 테스트 사례 이름에 추가하여 테스트 환경을 수정하거나 확장할 수 있습니다.

태그

설명

씬트리

MessageQueue를 사용할 수 있는 씬 트리를 사용하는 테스트 사례에 필요합니다. 또한 모의 렌더링 서버 및 :ref:`ThemeDB<class_ThemeDB>`를 활성화합니다.

[Editor]

``[SceneTree]``와 비슷하지만 :ref:`EditorSettings<class_EditorSettings>`와 같은 추가 편집기 관련 인프라를 사용할 수 있습니다.

[Audio]

모의 오디오 드라이버를 사용하여 :ref:`AudioServer<class_AudioServer>`를 초기화합니다.

[Navigation2D]

기본 2D 탐색 서버를 생성하고 테스트에 사용할 수 있도록 합니다.

[Navigation3D]

기본 3D 탐색 서버를 생성하고 테스트에 사용할 수 있도록 합니다.

이를 함께 사용하여 여러 테스트 환경 확장을 결합할 수 있습니다.

시그널 테스트하기

다음 매크로를 사용하여 시그널를 테스트할 수 있습니다.

매크로

설명

SIGNAL_WATCH(object, "signal_name")

지정된 개체에서 지정된 시그널 감시를 시작합니다.

SIGNAL_UNWATCH(object, "signal_name")

지정된 개체에서 지정된 시그널 감시를 중지합니다.

SIGNAL_CHECK("signal_name", Vector<Vector<Variant>>)

실행된 모든 시그널의 인수를 확인합니다. 외부 벡터에는 실행된 각 시그널가 포함되고, 내부 벡터에는 해당 시그널에 대한 인수 목록이 포함됩니다. 시그널의 순서가 중요합니다.

SIGNAL_CHECK_FALSE("signal_name")

지정된 시그널가 실행되지 않았는지 확인합니다.

SIGNAL_DISCARD("signal_name")

지정된 시그널의 모든 레코드를 삭제합니다.

다음은 이러한 매크로의 사용을 보여주는 예입니다.

//...
SUBCASE("[Timer] Timer process timeout signal must be emitted") {
    SIGNAL_WATCH(test_timer, SNAME("timeout"));
    test_timer->start(0.1);

    SceneTree::get_singleton()->process(0.2);

    Array signal_args;
    signal_args.push_back(Array());

    SIGNAL_CHECK(SNAME("timeout"), signal_args);

    SIGNAL_UNWATCH(test_timer, SNAME("timeout"));
}
//...

2D 툴

테스트 도구는 엔진 내부의 수동 테스트 및 디버깅 프로세스를 용이하게 하기 위해 임의의 절차를 실행할 수 있는 고급 방법입니다.

이러한 도구는 --test 명령줄 옵션 뒤에 도구 이름을 제공하여 실행할 수 있습니다. 예를 들어, GDScript 모듈은 토크나이저, 파서 및 컴파일러의 디버깅을 돕는 여러 도구를 구현하고 등록합니다.

./bin/<godot_binary> --test gdscript-tokenizer test.gd
./bin/<godot_binary> --test gdscript-parser test.gd
./bin/<godot_binary> --test gdscript-compiler test.gd

그러한 도구가 감지되면 나머지 단위 테스트를 건너뜁니다.

테스트 도구는 동적 초기화 기술을 사용하여 테스트 사례를 등록하는 동안 doctest가 제공하는 등록 메커니즘과 매우 유사하므로 엔진 전체의 어느 곳에나 등록할 수 있지만 일반적으로 해당 register_types.cpp 소스(모듈 또는 코어당)에 등록할 수 있습니다.

다음은 GDScript가 ``modules/gdscript/register_types.cpp``에 테스트 도구를 등록하는 방법에 대한 예입니다.

#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

사용자 정의 명령줄 구문 분석은 OS get_cmdline_args 방법을 사용하여 테스트 도구 자체에서 수행할 수 있습니다.

GDScript에서 C# 노드 인스턴스화 하기

Godot는 개발 중에 GDScript의 회귀를 방지하기 위해 doctest를 사용합니다. 작성할 수 있는 테스트 스크립트에는 여러 유형이 있습니다.

  • 예상되는 오류에 대한 테스트;

  • 경고 테스트;

  • 기능에 대해 테스트합니다.

따라서 GDScript에 대한 통합 테스트를 작성하는 과정은 다음과 같습니다:

  1. 작성하려는 테스트 스크립트 유형을 선택하고 해당 하위 디렉터리 내의 modules/gdscript/tests/scripts 디렉터리에 새 GDScript 파일을 만듭니다.

  2. GDScript 코드를 작성합니다. 테스트 스크립트에는 인수를 사용하지 않는 test()``라는 함수가 있어야 합니다. 이러한 함수는 테스트 실행기에 의해 호출됩니다. 테스트도 테스트의 일부가 아닌 이상 종속성을 가져서는 됩니다. Global classes (using ``class_name) are registered before the runner starts, so those should work if needed.

    여기에 테스트 스크립트의 예시가 있습니다:

    func test():
        if true # Missing colon here.
            print("true")
    
  3. 디렉토리를 Godot 소스 저장소 루트로 변경하세요.

    cd godot
    
  4. *.out 파일을 생성하여 출력에서 예상되는 결과를 업데이트합니다.

    bin/<godot_binary> --gdscript-generate-tests modules/gdscript/tests/scripts
    

테스트 출력이 생성될 때 파일 이름을 보려면 --print-filenames 옵션을 추가할 수 있습니다. 심각한 충돌을 일으키는 새로운 기능을 작업하는 경우 이 옵션을 사용하면 충돌을 일으키는 테스트 파일을 신속하게 찾아 거기에서 디버그할 수 있습니다.

  1. 다음으로 GDScript 테스트를 실행합니다:

    ./bin/<godot_binary> --test --test-suite="*GDScript*"
    

이는 --print-filenames 옵션도 허용합니다(위 참조).

오류가 인쇄되지 않고 모든 것이 잘 진행되면 작업이 완료된 것입니다!

경고

끌어오기 요청을 제출하기 전에 출력에 예상된 값이 있는지 확인하세요. --gdscript-generate-tests``가 새로 추가된 테스트와 관련되지 않은 ``*.out 파일을 생성하는 경우 해당 파일을 되돌리고 새 테스트에 대해서만 *.out 파일을 커밋해야 합니다.

참고

GDScript 테스트 실행기는 사용자 스크립트를 테스트하거나 스크립트를 사용하여 엔진을 테스트하기 위한 것이 아니라 GDScript 구현을 테스트하기 위한 것입니다. 이미 해결된 `GitHub의 GDScript 관련 문제 <https://github.com/godotengine/godot/issues?q=is%3Aissue+label%3Atopic%3Agdscript+is%3Aclosed>`_에 대한 새 테스트를 작성하거나 현재 작동 중인 기능에 대한 테스트를 작성하는 것이 좋습니다.

참고

테스트 사례에서 스크립트 파일 내에 test() 함수가 없어야 하는 경우 *.notest.gd 패턴과 일치하도록 스크립트 파일 이름을 지정하여 테스트의 런타임 섹션을 비활성화할 수 있습니다. 예를 들어 "test_empty_file.notest.gd"입니다.