mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 17:21:16 +08:00
test(game): 添加游戏模块集成测试项目
- 创建了 GFramework.Game.Tests 测试项目配置文件 - 添加了 Microsoft.NET.Test.Sdk、Moq、NUnit 等测试依赖包 - 配置了项目引用包括 GFramework.Game、GFramework.Core 和源代码生成器 - 实现了自动生成配置消费者集成测试验证功能 - 添加了怪物配置模式定义用于端到端测试验证 - 创建了源代码生成器目标文件实现自动化配置收集 - 验证了消费者项目自动拾取 schema 并生成绑定的功能
This commit is contained in:
parent
14ed42cabe
commit
f63714f1e1
@ -0,0 +1,125 @@
|
||||
using System.IO;
|
||||
using GFramework.Game.Config;
|
||||
using GFramework.Game.Config.Generated;
|
||||
|
||||
namespace GFramework.Game.Tests.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 验证消费者项目通过 `schemas/**/*.schema.json` 自动拾取 schema 后,
|
||||
/// 可以直接编译并使用生成的注册辅助、强类型访问入口与运行时加载链路。
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class GeneratedConfigConsumerIntegrationTests
|
||||
{
|
||||
/// <summary>
|
||||
/// 为每个端到端测试准备独立的配置根目录,避免编译期 schema 资产与运行时写入互相污染。
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_rootPath = Path.Combine(Path.GetTempPath(), "GFramework.GeneratedConfigTests", Guid.NewGuid().ToString("N"));
|
||||
Directory.CreateDirectory(_rootPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理测试过程中创建的临时消费者目录。
|
||||
/// </summary>
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
if (Directory.Exists(_rootPath))
|
||||
{
|
||||
Directory.Delete(_rootPath, true);
|
||||
}
|
||||
}
|
||||
|
||||
private string _rootPath = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 验证生成器自动拾取消费者项目的 schema 后,
|
||||
/// 可以用生成的注册辅助完成加载,并通过强类型表包装访问运行时数据。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task LoadAsync_Should_Support_Generated_Bindings_In_Consumer_Project()
|
||||
{
|
||||
CreateFile(
|
||||
"schemas/monster.schema.json",
|
||||
"""
|
||||
{
|
||||
"title": "Monster Config",
|
||||
"description": "Defines one monster entry for the end-to-end consumer integration test.",
|
||||
"type": "object",
|
||||
"required": ["id", "name", "hp"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"description": "Monster identifier."
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Monster display name."
|
||||
},
|
||||
"hp": {
|
||||
"type": "integer",
|
||||
"description": "Monster base health."
|
||||
}
|
||||
}
|
||||
}
|
||||
""");
|
||||
CreateFile(
|
||||
"monster/slime.yaml",
|
||||
"""
|
||||
id: 1
|
||||
name: Slime
|
||||
hp: 10
|
||||
""");
|
||||
CreateFile(
|
||||
"monster/goblin.yaml",
|
||||
"""
|
||||
id: 2
|
||||
name: Goblin
|
||||
hp: 30
|
||||
""");
|
||||
|
||||
var registry = new ConfigRegistry();
|
||||
var loader = new YamlConfigLoader(_rootPath)
|
||||
.RegisterMonsterTable();
|
||||
|
||||
await loader.LoadAsync(registry);
|
||||
|
||||
var table = registry.GetMonsterTable();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(MonsterConfigBindings.TableName, Is.EqualTo("monster"));
|
||||
Assert.That(MonsterConfigBindings.ConfigRelativePath, Is.EqualTo("monster"));
|
||||
Assert.That(MonsterConfigBindings.SchemaRelativePath, Is.EqualTo("schemas/monster.schema.json"));
|
||||
Assert.That(table.Count, Is.EqualTo(2));
|
||||
Assert.That(table.Get(1).Name, Is.EqualTo("Slime"));
|
||||
Assert.That(table.Get(2).Hp, Is.EqualTo(30));
|
||||
Assert.That(registry.TryGetMonsterTable(out var generatedTable), Is.True);
|
||||
Assert.That(generatedTable, Is.Not.Null);
|
||||
Assert.That(generatedTable!.All().Select(static config => config.Name),
|
||||
Is.EquivalentTo(new[] { "Slime", "Goblin" }));
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在临时消费者根目录中创建测试文件。
|
||||
/// </summary>
|
||||
/// <param name="relativePath">相对根目录的文件路径。</param>
|
||||
/// <param name="content">要写入的文件内容。</param>
|
||||
private void CreateFile(
|
||||
string relativePath,
|
||||
string content)
|
||||
{
|
||||
var path = Path.Combine(_rootPath, relativePath.Replace('/', Path.DirectorySeparatorChar));
|
||||
var directoryPath = Path.GetDirectoryName(path);
|
||||
if (!string.IsNullOrEmpty(directoryPath))
|
||||
{
|
||||
Directory.CreateDirectory(directoryPath);
|
||||
}
|
||||
|
||||
File.WriteAllText(path, content.Replace("\n", Environment.NewLine, StringComparison.Ordinal));
|
||||
}
|
||||
}
|
||||
@ -19,6 +19,21 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GFramework.Game\GFramework.Game.csproj"/>
|
||||
<ProjectReference Include="..\GFramework.Core\GFramework.Core.csproj"/>
|
||||
<ProjectReference Include="..\GFramework.SourceGenerators.Abstractions\GFramework.SourceGenerators.Abstractions.csproj"
|
||||
OutputItemType="Analyzer"
|
||||
ReferenceOutputAssembly="false"/>
|
||||
<ProjectReference Include="..\GFramework.SourceGenerators.Common\GFramework.SourceGenerators.Common.csproj"
|
||||
OutputItemType="Analyzer"
|
||||
ReferenceOutputAssembly="false"/>
|
||||
<ProjectReference Include="..\GFramework.SourceGenerators\GFramework.SourceGenerators.csproj"
|
||||
OutputItemType="Analyzer"
|
||||
ReferenceOutputAssembly="false"/>
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
通过仓库内的 targets 复用消费者默认约定,确保测试项目与真实消费项目一样
|
||||
自动拾取 schemas/**/*.schema.json 作为 Source Generator 的 AdditionalFiles。
|
||||
-->
|
||||
<Import Project="..\GFramework.SourceGenerators\GeWuYou.GFramework.SourceGenerators.targets"/>
|
||||
|
||||
</Project>
|
||||
|
||||
24
GFramework.Game.Tests/schemas/monster.schema.json
Normal file
24
GFramework.Game.Tests/schemas/monster.schema.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"title": "Monster Config",
|
||||
"description": "Defines one monster entry for the generated consumer integration test.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"hp"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"description": "Monster identifier."
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Monster display name."
|
||||
},
|
||||
"hp": {
|
||||
"type": "integer",
|
||||
"description": "Monster base health."
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,9 +12,17 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Analyzer Include="$(MSBuildThisFileDirectory)../analyzers/dotnet/cs/GFramework.SourceGenerators.dll"/>
|
||||
<Analyzer Include="$(MSBuildThisFileDirectory)../analyzers/dotnet/cs/GFramework.SourceGenerators.Abstractions.dll"/>
|
||||
<Analyzer Include="$(MSBuildThisFileDirectory)../analyzers/dotnet/cs/GFramework.SourceGenerators.Common.dll"/>
|
||||
<!--
|
||||
仅在 NuGet 打包布局存在时自动注入 analyzer。
|
||||
仓库内项目引用场景会通过 ProjectReference(OutputItemType=Analyzer) 提供生成器,
|
||||
因此这里需要避免对不存在的打包路径做无效引用。
|
||||
-->
|
||||
<Analyzer Include="$(MSBuildThisFileDirectory)../analyzers/dotnet/cs/GFramework.SourceGenerators.dll"
|
||||
Condition="Exists('$(MSBuildThisFileDirectory)../analyzers/dotnet/cs/GFramework.SourceGenerators.dll')"/>
|
||||
<Analyzer Include="$(MSBuildThisFileDirectory)../analyzers/dotnet/cs/GFramework.SourceGenerators.Abstractions.dll"
|
||||
Condition="Exists('$(MSBuildThisFileDirectory)../analyzers/dotnet/cs/GFramework.SourceGenerators.Abstractions.dll')"/>
|
||||
<Analyzer Include="$(MSBuildThisFileDirectory)../analyzers/dotnet/cs/GFramework.SourceGenerators.Common.dll"
|
||||
Condition="Exists('$(MSBuildThisFileDirectory)../analyzers/dotnet/cs/GFramework.SourceGenerators.Common.dll')"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="Exists('$(MSBuildProjectDirectory)/$(GFrameworkConfigSchemaDirectory)')">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user