mcpField
G
godot-testing

godot-testing

github.com/jame581测试与质量889224 次安装4 天前更新
代码仓库

关于 godot-testing

面向 Godot 4.3+ 开发者的测试技能,讲解如何使用 GUT 或 gdUnit4。内容涵盖框架选择、TDD、常见测试模式,以及本地和 CI 测试运行。

主要功能

  1. 01GUT 与 gdUnit4 框架选择
  2. 02RED-GREEN-REFACTOR 测试流程
  3. 03测试目录与命名规范
  4. 04命令行及 CI 测试运行
  5. 05场景、信号、模拟与异步测试

适用场景

  1. 01为 GDScript 或 C# 项目选择测试框架
  2. 02按 TDD 流程实现 Godot 功能
  3. 03在本地或 CI 中运行测试套件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jame581/godotprompter --skill godot-testing

安装后在 Claude Code 中输入/godot-testing确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

gdunit4-reference.md
gut-reference.md
references/
running-tests.md
tdd-workflow.md
testing-patterns.md

详细介绍

Godot 测试

本技能介绍如何在 Godot 4.3+ 项目中使用 GUT(Godot Unit Testing)和 gdUnit4 进行测试驱动开发(TDD)。内容包括框架选择、完整的 RED-GREEN-REFACTOR 示例、测试结构、在 CI 中运行测试,以及常见测试模式。

相关技能: godot-code-review 提供审查清单,dependency-injection 介绍适合测试的架构,export-pipeline 介绍 CI/CD 测试自动化。

框架选择

特性GUTgdUnit4
语言GDScript 优先,有限支持 C#GDScript + C#(一等支持)
安装AssetLib 或 git 子模块AssetLib 或 git 子模块
编辑器集成内置 GUT 面板内置检查器 + 面板
模拟double() / stub() APImock() / spy() API
场景测试add_child_autofree()auto_free() + 场景运行器
CI 支持gut_cmdln.gd CLI 脚本runtest.sh / GdUnitCmdTool.gd
C# 支持最少(仅限 GDScript 封装)原生 C# 断言 + 生命周期
成熟度成熟(Godot 3 + 4)专注于 Godot 4,持续更新
最适用于纯 GDScript 项目GDScript/C# 混合项目或纯 C# 项目

经验法则: 纯 GDScript 项目使用 GUT。C# 项目,或需要一等 C# 支持和场景运行器工具时,使用 gdUnit4。


TDD 工作流:RED-GREEN-REFACTOR

标准的测试驱动开发循环:编写一个失败的测试(RED),编写最少的代码使测试通过(GREEN),然后在不破坏测试的前提下重构。每个步骤都有各自的规范——不要跳过 RED(否则你会写出轻易就能通过的测试),也不要跳过 REFACTOR(技术债会不断累积)。

参见 references/tdd-workflow.md,其中通过 HealthComponent 的示例,演示 GDScript + C# 如何完成这三个步骤。


测试目录结构

res://
├── .gutconfig.json                       # GUT default config file (optional)
├── src/
│   └── components/
│       ├── health_component.gd
│       └── HealthComponent.cs
└── tests/
    ├── unit/
    │   ├── test_health_component.gd      # GUT: test_ prefix (default -gprefix)
    │   └── HealthComponentTest.cs        # gdUnit4 C#: [TestSuite] attribute
    └── integration/
        ├── test_player_scene.gd
        └── PlayerSceneTest.cs
命名约定
框架GDScript 文件C# 文件测试方法前缀/属性
GUTtest_*.gd不适用func test_*()
gdUnit4任意名称(生成时为 *_test.gd)*Test.csfunc test_*() / [TestCase]

运行测试

两个框架都附带 CLI 运行器。GUT: 通过 godot --headless --path . -s addons/gut/gut_cmdln.gd -gexit 调用 addons/gut/gut_cmdln.gd(不加 -gexit,运行结束后进程不会退出)。gdUnit4: addons/gdUnit4/runtest.sh -a res://tests(封装了 bin/GdUnitCmdTool.gd;使用 --headless 时还需要 --ignoreHeadlessMode),或使用编辑器中的 GdUnit 停靠面板。CI:配置由标签或 PR 触发的 GitHub Action,安装 Godot、运行测试套件,并在失败时以非零状态码退出。

参见 references/running-tests.md,了解完整的 GUT 和 gdUnit4 CLI 调用方式,以及可直接复制粘贴的 GitHub Actions 工作流。


测试模式

四种常见模式:带节点的场景(在 before_each 中通过 add_child 实例化,并在 after_each 中释放)、信号测试(断言发射信号有效,并验证连接后发射信号会触发回调)、模拟/替身(在 GDScript 中使用 gdUnit4 的 mock();在 C# 中通过 @export 注入手写的伪实现)、异步(在测试中等待 yield、信号和帧)。

参见 references/testing-patterns.md,查看每种模式的完整代码(适用时包含 GDScript + C#)。


常见断言

GUT 断言
断言描述
assert_eq(actual, expected)相等
assert_ne(actual, expected)不相等
assert_true(value)为真
assert_false(value)为假
assert_null(value)为 null
assert_not_null(value)不为 null
assert_gt(actual, expected)大于
assert_lt(actual, expected)小于
assert_gte(actual, expected)大于或等于
assert_lte(actual, expected)小于或等于
assert_has(collection, item)集合包含项目
assert_does_not_have(collection, item)集合不包含项目
assert_string_contains(str, sub)字符串包含子字符串
assert_almost_eq(actual, expected, margin)浮点数在误差范围内相等
assert_signal_emitted(obj, signal_name)已发出信号
assert_signal_not_emitted(obj, signal_name)未发出信号
gdUnit4 断言(GDScript + C#)
GDScriptC#描述
assert_that(val).is_equal(exp)AssertThat(val).IsEqual(exp)相等
assert_that(val).is_not_equal(exp)AssertThat(val).IsNotEqual(exp)不相等
assert_that(val).is_true()AssertThat(val).IsTrue()为真
assert_that(val).is_false()AssertThat(val).IsFalse()为假
assert_that(val).is_null()AssertThat(val).IsNull()为 null
assert_that(val).is_not_null()AssertThat(val).IsNotNull()不为 null
assert_that(val).is_greater(exp)AssertThat(val).IsGreater(exp)大于
assert_that(val).is_less(exp)AssertThat(val).IsLess(exp)小于
assert_that(val).is_between(min, max)AssertThat(val).IsBetween(min, max)在范围内(含边界)
assert_that(arr).contains([a, b])AssertThat(arr).Contains(a, b)数组包含元素
assert_that(str).contains("sub")AssertThat(str).Contains("sub")字符串包含子字符串
assert_that(val).is_equal_approx(exp, margin)AssertThat(val).IsEqualApprox(exp, margin)浮点数在误差范围内
await assert_signal(mon).is_emitted("name")await AssertSignal(node).IsEmitted("name")已发出信号

不要测试的内容

避免测试那些会增加噪声、却无法发现真实错误的内容:

  • Godot 引擎内部机制 —— 不要断言 Node.add_child() 能正常工作,或 @export 变量会显示在编辑器中
  • 私有实现细节 —— 通过公共 API 测试行为;如果重构导致一个只覆盖私有状态的测试失败,那么这个测试就有问题
  • 视觉/渲染输出 —— 像素级渲染结果很脆弱;应测试驱动视觉效果的数据
  • 没有容差的时序敏感浮点数 —— 对物理值使用 assert_almost_eq / IsEqualApprox
  • 对内置功能进行简单封装的单行代码 —— 只返回字段的属性 getter 无需测试
  • 所有可能的无效输入 —— 测试文档规定的契约,而非所有可以想象到的误用

检查清单

  • 每个测试文件都符合所选框架的命名约定(GUT test_*.gd;gdUnit4 *_test.gd / *Test.cs)
  • 测试继承自正确的基类(GutTest / GdUnitTestSuite);C# gdUnit4 测试套件是普通的 [TestSuite] 类
  • C#:在 Godot 4.3 上,gdUnit4.api 固定为 4.3.x;在 5.x(Godot 4.4+)上,涉及节点或场景的测试套件需带有 [RequireGodotRuntime]
  • 添加到场景树中的节点使用 add_child_autofree 或 auto_free,切勿手动调用 queue_free()
  • 在触发信号的操作执行之前监听信号
  • 对外部依赖使用 Mock/替身,而非被测单元
  • 每个测试只覆盖一种行为(每个测试包含一个逻辑断言)
  • CI 工作流在每次推送和 PR 时都以无头模式运行测试
  • 对易不稳定的异步测试使用显式超时,而非任意设置休眠时长
  • 合并前测试必须通过(只有在积极实现功能时才允许 RED)

评论

支持 Markdown