diff --git a/tests/RHI/D3D12/TEST_SPEC.md b/tests/RHI/D3D12/TEST_SPEC.md index 610ab5c9..c2b49c7f 100644 --- a/tests/RHI/D3D12/TEST_SPEC.md +++ b/tests/RHI/D3D12/TEST_SPEC.md @@ -1,82 +1,52 @@ -# D3D12 测试规范文档 +# D3D12 测试专项规范 -## 1. 测试分类 +本文档是 XCEngine 测试规范的 D3D12 专项补充。 -### 1.1 测试层级 - -| 层级 | 位置 | 执行方式 | 目的 | -|------|------|----------|------| -| 单元测试 | `tests/RHI/D3D12/unit/` | CTest 自动运行 | 验证各组件 API 功能 | -| 集成测试 | `tests/RHI/D3D12/integration/` | CTest + Python wrapper | 端到端渲染验证 | - -### 1.2 单元测试规范 - -**框架**: Google Test -**运行方式**: -```bash -cd build/tests/RHI/D3D12/unit -ctest -C Debug --output-on-failure -``` - -**命名约定**: `Component_Category_SubBehavior` -- Component: 组件名 (Device, Buffer, Texture, CommandQueue, etc.) -- Category: 操作类别 (Create, Get, Set, Map, Reset, etc.) -- SubBehavior: 具体行为 (DefaultHeap, GPUAddress, etc.) - -**示例**: -``` -Device_Create_Success -Device_Get_AdapterInfo -Buffer_Create_DefaultHeap -Buffer_Map_Unmap -Texture_Create_2D -``` - -### 1.3 集成测试规范 - -**运行方式**: Python wrapper 通过 CTest 调用 -```bash -cd build/tests/RHI/D3D12/integration -ctest -C Debug --output-on-failure -``` - -**Python Wrapper 职责**: -1. 启动 D3D12 exe -2. 等待进程完成 -3. 检查输出文件 -4. 调用 compare_ppm.py 比对 Golden Image -5. 返回 0(成功)/1(失败) - -**Golden Image 规范**: -- 文件格式: PPM (P6) -- 存储位置: `tests/RHI/D3D12/integration/` -- 命名: `GT_.ppm` -- 阈值: 默认 5% +**前置阅读**: [tests/TEST_SPEC.md](../TEST_SPEC.md) - 通用测试规范 --- -## 2. 测试命名规则 +## 1. 概述 -### 2.1 禁止模式 +### 1.1 D3D12 测试特点 -❌ 不允许: -- `*_Placeholder` - 无意义的占位测试 -- 驼峰+下划线混用 -- 空操作测试 +| 特点 | 说明 | +|------|------| +| 硬件依赖 | 需要支持 D3D12 的显卡 | +| 窗口依赖 | 集成测试需要 GUI 窗口 | +| GPU 状态 | 测试间可能有 GPU 状态污染 | -### 2.2 标准格式 +### 1.2 测试层级 -✅ 正确格式: -``` -Component_Category_SubBehavior +| 层级 | 位置 | 执行方式 | 框架 | +|------|------|----------|------| +| 单元测试 | `tests/RHI/D3D12/unit/` | CTest | Google Test | +| 集成测试 | `tests/RHI/D3D12/integration/` | CTest + Python | Python wrapper | + +--- + +## 2. 单元测试规范 + +### 2.1 Fixture 设计 + +每个测试独立创建设备,避免 GPU 状态污染: + +```cpp +class D3D12TestFixture : public ::testing::Test { +protected: + void SetUp() override; // 创建设备、命令队列等 + void TearDown() override; // 清理资源 + + ID3D12Device* GetDevice(); + ID3D12CommandQueue* GetCommandQueue(); + ID3D12CommandAllocator* GetCommandAllocator(); + ID3D12GraphicsCommandList* GetCommandList(); + + void WaitForGPU(); +}; ``` -### 2.3 大小写规则 - -- 全小写,单词间用下划线分隔 -- Component 名称与类名一致 (如 `CommandQueue` 不是 `Command_queue`) - -### 2.4 测试前缀对应关系 +### 2.2 测试前缀对应 | 类名 | 测试前缀 | |------|---------| @@ -94,227 +64,159 @@ Component_Category_SubBehavior | D3D12RenderTargetView | RTV | | D3D12DepthStencilView | DSV | ---- +### 2.3 当前测试统计 -## 3. 测试实现规范 - -### 3.1 单元测试结构 - -```cpp -TEST_F(D3D12TestFixture, Component_Category_SubBehavior) { - // Arrange: 准备测试数据 - - // Act: 执行被测操作 - - // Assert: 验证结果 - ASSERT_TRUE(condition); - EXPECT_EQ(expected, actual); -} -``` - -### 3.2 Fixture 使用 - -```cpp -class D3D12TestFixture : public ::testing::Test { -protected: - void SetUp() override; // 创建设备、命令队列等 - void TearDown() override; // 清理资源 - - ID3D12Device* GetDevice(); - ID3D12CommandQueue* GetCommandQueue(); - ID3D12CommandAllocator* GetCommandAllocator(); - ID3D12GraphicsCommandList* GetCommandList(); - - void WaitForGPU(); -}; -``` - -### 3.3 错误处理测试 - -对于负面测试: -```cpp -TEST_F(D3D12TestFixture, Component_Create_InvalidSize) { - // 测试零大小或负数大小应该失败 - ASSERT_FALSE(buffer->Initialize(device, 0)); -} -``` +| 组件 | 测试数 | 状态 | +|------|--------|------| +| Device | 6 | ✅ 通过 | +| Fence | 5 | ✅ 通过 | +| CommandQueue | 2 | ✅ 通过 | +| CommandAllocator | 3 | ✅ 通过 | +| CommandList | 2 | ✅ 通过 | +| Buffer | 5 | ✅ 通过 | +| Texture | 4 | ✅ 通过 | +| DescriptorHeap | 5 | ✅ 通过 | +| PipelineState | 2 | ✅ 通过 | +| RootSignature | 2 | ✅ 通过 | +| Shader | 3 | ✅ 通过 | +| Views | 4 | ✅ 通过 | +| **总计** | **44** | **全部通过** | --- -## 4. 集成测试规范 +## 3. 集成测试规范 -### 4.1 Python Wrapper 模板 +### 3.1 Python Wrapper -```python -import sys -import os -import subprocess -import time +**位置**: `tests/RHI/D3D12/integration/run_integration_test.py` -def run_integration_test(exe_path, output_ppm, gt_ppm, threshold, timeout=120): - """ - Run a D3D12 integration test and compare output with golden template. - - Args: - exe_path: Path to the test executable - output_ppm: Filename of the output screenshot - gt_ppm: Path to the golden template PPM file - threshold: Pixel difference threshold for comparison - timeout: Maximum time to wait (seconds) - - Returns: - 0 on success, non-zero on failure - """ - # 1. 检查文件存在 - # 2. 删除旧输出 - # 3. 启动进程 - # 4. 等待完成 - # 5. 检查输出 - # 6. 比对图片 - # 7. 返回结果 -``` +**职责**: +1. 启动 D3D12 exe +2. 等待进程完成 +3. 检查输出文件 (PPM 截图) +4. 调用 `compare_ppm.py` 比对 Golden Image +5. 返回 0(成功)/1(失败) -### 4.2 CTest 注册格式 +### 3.2 CTest 注册格式 ```cmake find_package(Python3 REQUIRED) enable_testing() -add_test(NAME TestName +add_test(NAME D3D12_Minimal_Integration COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/run_integration_test.py - $ - output.ppm - ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm + $ + minimal.ppm + ${CMAKE_CURRENT_SOURCE_DIR}/GT_minimal.ppm 5 - WORKING_DIRECTORY $ + WORKING_DIRECTORY $ ) ``` -### 4.3 Golden Image 生成 +### 3.3 Golden Image 规范 + +| 属性 | 值 | +|------|-----| +| 格式 | PPM (P6) | +| 命名 | `GT_.ppm` | +| 阈值 | 默认 5% | +| 存储位置 | `tests/RHI/D3D12/integration/` | + +### 3.4 Golden Image 生成流程 1. 在干净硬件环境运行集成测试 2. 截图保存为 `GT_.ppm` 3. 人工验证截图正确性 4. 提交到版本控制 ---- +### 3.5 当前集成测试 -## 5. CMakeLists.txt 规范 - -### 5.1 单元测试 CMakeLists.txt - -```cmake -cmake_minimum_required(VERSION 3.15) -get_filename_component(PROJECT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../.. ABSOLUTE) - -find_package(GTest REQUIRED) - -set(TEST_SOURCES - fixtures/D3D12TestFixture.cpp - test_device.cpp - test_buffer.cpp - # ... 其他测试文件 -) - -add_executable(d3d12_engine_tests ${TEST_SOURCES}) - -target_link_libraries(d3d12_engine_tests PRIVATE - d3d12 - dxgi - d3dcompiler - XCEngine - GTest::gtest - GTest::gtest_main -) - -target_include_directories(d3d12_engine_tests PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/fixtures - ${PROJECT_ROOT_DIR}/engine/include - ${PROJECT_ROOT_DIR}/engine/src -) - -enable_testing() -add_test(NAME D3D12EngineTests COMMAND d3d12_engine_tests) -``` - -### 5.2 集成测试 CMakeLists.txt - -```cmake -cmake_minimum_required(VERSION 3.15) -project(D3D12_Integration) - -set(ENGINE_ROOT_DIR ${CMAKE_SOURCE_DIR}/../engine) -find_package(Python3 REQUIRED) -enable_testing() - -add_executable(D3D12_Test WIN32 main.cpp) - -target_link_libraries(D3D12_Test PRIVATE - d3d12 dxgi d3dcompiler winmm XCEngine -) - -# POST_BUILD: 复制资源文件 -add_custom_command(TARGET D3D12_Test POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory - ${CMAKE_CURRENT_SOURCE_DIR}/Res - $/Res -) - -# CTest 注册 -add_test(NAME D3D12_Test_Integration - COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/run_integration_test.py - $ - output.ppm - ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm - 5 - WORKING_DIRECTORY $ -) -``` +| 测试名 | Golden Image | 状态 | +|--------|-------------|------| +| D3D12_Minimal_Integration | GT_minimal.ppm | ✅ 通过 | +| D3D12_RenderModel_Integration | GT.ppm | ❌ 待修复 | --- -## 6. 测试执行 +## 4. 测试执行 -### 6.1 完整测试流程 +### 4.1 单元测试 ```bash -# 1. 构建 -cd build -cmake .. -cmake --build . --target d3d12_engine_tests D3D12_Test --config Debug +# 方式 1: 使用统一脚本 +python scripts/run_tests.py --unit-only -# 2. 运行单元测试 -cd tests/RHI/D3D12/unit -ctest -C Debug --output-on-failure - -# 3. 运行集成测试 -cd tests/RHI/D3D12/integration +# 方式 2: 直接使用 CTest +cd build/tests/RHI/D3D12/unit ctest -C Debug --output-on-failure ``` -### 6.2 输出格式 +### 4.2 集成测试 -成功: -``` -Test #1: D3D12_Minimal_Integration ....... Passed +```bash +# 方式 1: 使用统一脚本 +python scripts/run_tests.py --integration + +# 方式 2: 直接使用 CTest +cd build/tests/RHI/D3D12/integration +ctest -C Debug --output-on-failure ``` -失败: -``` -Test #1: D3D12_Minimal_Integration ....... Failed -[Integration Test] Different pixels: 39.94% -FAIL: Images differ! +### 4.3 构建和测试 + +```bash +# 构建 +cmake --build . --target d3d12_engine_tests D3D12_Minimal --config Debug + +# 运行测试 +python scripts/run_tests.py --build ``` --- -## 7. 文件结构 +## 5. CI 集成 + +### 5.1 GitHub Actions 配置 + +```yaml +name: D3D12 Tests +on: [push, pull_request] + +jobs: + test: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Configure CMake + run: cmake -B build -DCMAKE_BUILD_TYPE=Debug + + - name: Build D3D12 Tests + run: cmake --build build --target d3d12_engine_tests D3D12_Minimal --config Debug + + - name: Run Unit Tests + run: cd build/tests/RHI/D3D12/unit && ctest -C Debug --output-on-failure + + - name: Run Integration Tests + run: python scripts/run_tests.py --integration +``` + +### 5.2 CI 模式 + +`--ci` 模式会跳过需要 GUI 的集成测试: +```bash +python scripts/run_tests.py --ci # 仅运行单元测试 +``` + +--- + +## 6. 文件结构 ``` tests/RHI/D3D12/ ├── CMakeLists.txt -├── TEST_IMPROVEMENT_PLAN.md # 改进计划 -├── TEST_SPEC.md # 本规范 +├── TEST_SPEC.md # 本文档 (D3D12 专项) +├── TEST_IMPROVEMENT_PLAN.md # 改进计划 ├── unit/ │ ├── CMakeLists.txt │ ├── fixtures/ @@ -326,7 +228,7 @@ tests/RHI/D3D12/ └── integration/ ├── CMakeLists.txt ├── main_minimal.cpp - ├── main_render.cpp + ├── main_render.cpp # 有 API 问题,待修复 ├── run_integration_test.py ├── compare_ppm.py ├── GT.ppm @@ -335,13 +237,27 @@ tests/RHI/D3D12/ --- +## 7. 已知问题 + +### 7.1 main_render.cpp API 不兼容 + +**问题**: `D3D12Buffer::Initialize` 和 `D3D12Screenshot::Capture` API 签名变更 + +**影响**: `D3D12_RenderModel_Integration` 无法编译 + +**状态**: 待修复 + +--- + ## 8. 规范更新记录 | 版本 | 日期 | 变更 | |------|------|------| | 1.0 | 2026-03-20 | 初始版本 | +| 1.1 | 2026-03-20 | 添加 CI 集成章节,补充 Phase 5 内容 | --- -**规范版本**: 1.0 -**最后更新**: 2026-03-20 \ No newline at end of file +**规范版本**: 1.1 +**最后更新**: 2026-03-20 +**前置文档**: [tests/TEST_SPEC.md](../TEST_SPEC.md) \ No newline at end of file diff --git a/tests/TEST_SPEC.md b/tests/TEST_SPEC.md new file mode 100644 index 00000000..b46865df --- /dev/null +++ b/tests/TEST_SPEC.md @@ -0,0 +1,328 @@ +# XCEngine 测试规范 + +## 1. 测试框架 + +### 1.1 框架组成 + +| 组件 | 用途 | 文档位置 | +|------|------|---------| +| Google Test | 单元测试框架 | https://google.github.io/googletest/ | +| CTest | CMake 测试发现和执行 | 内置 CMake 模块 | +| Python | 集成测试辅助 | `scripts/run_tests.py` | + +### 1.2 测试分类 + +| 类型 | 框架 | 特点 | +|------|------|------| +| 单元测试 | Google Test | 快速、独立、无副作用 | +| 集成测试 | CTest + Python | 端到端验证、需要 GUI | + +--- + +## 2. 测试目录结构 + +### 2.1 整体结构 + +``` +tests/ +├── CMakeLists.txt # 主 CMake 配置 +├── TEST_SPEC.md # 本规范文档 +├── run_tests.bat # Windows 测试启动脚本 +├── fixtures/ # 共享测试夹具 +├── scripts/ +│ └── run_tests.py # 统一测试运行脚本 +├── math/ # 数学库测试 +├── core/ # 核心库测试 +├── containers/ # 容器测试 +├── memory/ # 内存管理测试 +├── threading/ # 线程测试 +├── debug/ # 调试系统测试 +├── Resources/ # 资源系统测试 +└── RHI/ + ├── D3D12/ # D3D12 RHI 测试 + │ ├── unit/ # 单元测试 + │ └── integration/ # 集成测试 + └── OpenGL/ # OpenGL RHI 测试 (暂不维护) +``` + +### 2.2 模块命名规范 + +| 模块 | 测试可执行文件 | CTest 名称 | +|------|--------------|-----------| +| math | xcengine_math_tests | MathTests | +| core | xcengine_core_tests | CoreTests | +| containers | xcengine_containers_tests | ContainersTests | +| memory | xcengine_memory_tests | MemoryTests | +| threading | xcengine_threading_tests | ThreadingTests | +| debug | xcengine_debug_tests | DebugTests | +| Resources | xcengine_resources_tests | ResourcesTests | +| RHI/D3D12/unit | d3d12_engine_tests | D3D12EngineTests | +| RHI/D3D12/integration | D3D12_Minimal | D3D12_Minimal_Integration | + +--- + +## 3. 测试命名规范 + +### 3.1 单元测试命名 + +**格式**: `Component_Category_SubBehavior` + +| 部分 | 说明 | 示例 | +|------|------|------| +| Component | 被测组件 | Memory, ResourceHandle, Buffer | +| Category | 操作类别 | Create, Get, Set, Map, Reset | +| SubBehavior | 具体行为 | DefaultHeap, GPUAddress, ValidPointer | + +**示例**: +``` +MemoryTest_GetSystemAllocator_ReturnsValidPointer +ResourceHandle_DefaultConstructor +Buffer_Create_DefaultHeap +Texture_Create_2D +``` + +### 3.2 禁止模式 + +❌ 不允许: +- `*_Placeholder` - 无意义的占位测试 +- 驼峰+下划线混用 +- 空操作测试 + +### 3.3 大小写规则 + +- 全小写,单词间用下划线分隔 +- Component 名称与类名一致 + +--- + +## 4. CMakeLists.txt 规范 + +### 4.1 单元测试模板 + +```cmake +cmake_minimum_required(VERSION 3.15) + +project(XCEngine_ModuleTests) + +find_package(GTest REQUIRED) + +set(TEST_SOURCES + test_module.cpp + # ... 其他测试文件 +) + +add_executable(xcengine_module_tests ${TEST_SOURCES}) + +# MSVC 运行时库排除 +if(MSVC) + set_target_properties(xcengine_module_tests PROPERTIES + LINK_FLAGS "/NODEFAULTLIB:libcpmt.lib /NODEFAULTLIB:libcmt.lib" + ) +endif() + +target_link_libraries(xcengine_module_tests PRIVATE + XCEngine + GTest::gtest + GTest::gtest_main +) + +target_include_directories(xcengine_module_tests PRIVATE + ${CMAKE_SOURCE_DIR}/engine/include + ${CMAKE_SOURCE_DIR}/tests/fixtures +) + +add_test(NAME ModuleTests COMMAND xcengine_module_tests) +``` + +### 4.2 CTest 注册 + +每个模块的 CMakeLists.txt 必须包含: + +```cmake +add_test(NAME COMMAND ) +``` + +### 4.3 测试资源复制 + +如需复制测试资源: + +```cmake +add_custom_command(TARGET POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_SOURCE_DIR}/Res + $>/Res +) +``` + +--- + +## 5. 测试执行 + +### 5.1 统一测试脚本 + +**位置**: `scripts/run_tests.py` + +**功能**: +- 跨平台支持 (Windows/Linux) +- 自动检测测试目录 +- 单元测试 + 集成测试 +- 测试结果汇总 + +### 5.2 使用方式 + +| 命令 | 说明 | +|------|------| +| `python scripts/run_tests.py` | 运行所有测试 | +| `python scripts/run_tests.py --unit-only` | 仅单元测试 | +| `python scripts/run_tests.py --integration` | 含集成测试 | +| `python scripts/run_tests.py --ci` | CI 模式 (跳过 GUI 测试) | +| `python scripts/run_tests.py --build` | 构建并测试 | +| `python scripts/run_tests.py --dir ` | 指定测试目录 | +| `python scripts/run_tests.py --verbose` | 详细输出 | + +### 5.3 直接使用 CTest + +```bash +# 运行特定模块测试 +cd build/tests/ +ctest -C Debug --output-on-failure + +# 列出所有测试 +ctest -N + +# 运行所有测试 +ctest -C Debug --output-on-failure +``` + +--- + +## 6. CI 集成 + +### 6.1 GitHub Actions 配置 + +```yaml +name: XCEngine Tests +on: [push, pull_request] + +jobs: + test: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Configure CMake + run: cmake -B build -DCMAKE_BUILD_TYPE=Debug + + - name: Build + run: cmake --build build --config Debug + + - name: Run Tests + run: python scripts/run_tests.py --ci +``` + +### 6.2 CI 模式说明 + +`--ci` 模式会: +- 运行所有单元测试 +- 跳过需要 GUI 窗口的集成测试 +- 输出机器可读的测试结果 + +### 6.3 本地验证 + +```bash +# 完整构建和测试 +python scripts/run_tests.py --build + +# 仅验证单元测试 +python scripts/run_tests.py --unit-only +``` + +--- + +## 7. 测试实现规范 + +### 7.1 单元测试结构 + +```cpp +#include +#include + +using namespace XCEngine::Module; + +class ComponentTest : public ::testing::Test { +protected: + void SetUp() override { + // 初始化测试环境 + } + + void TearDown() override { + // 清理资源 + } +}; + +TEST_F(ComponentTest, Create_ReturnsValidPointer) { + auto component = Component::Create(); + ASSERT_NE(component, nullptr); +} + +TEST_F(ComponentTest, GetProperty_ReturnsExpectedValue) { + Component component; + EXPECT_EQ(component.GetProperty(), expected_value); +} +``` + +### 7.2 Fixture 使用原则 + +- 每个测试类使用独立的 Fixture +- SetUp/TearDown 用于资源初始化/清理 +- 避免测试间共享状态 + +### 7.3 断言选择 + +| 断言 | 用途 | +|------|------| +| `ASSERT_*` | 致命错误,立即终止测试 | +| `EXPECT_*` | 非致命错误,继续执行 | + +--- + +## 8. 文件结构 + +``` +tests/ +├── CMakeLists.txt +├── TEST_SPEC.md # 本规范 +├── run_tests.bat # Windows 测试脚本 +├── fixtures/ # 共享夹具头文件 +├── scripts/ +│ └── run_tests.py # 统一测试运行脚本 +├── math/ +│ ├── CMakeLists.txt +│ └── test_*.cpp +├── core/ +├── containers/ +├── memory/ +├── threading/ +├── debug/ +├── Resources/ +└── RHI/ + ├── D3D12/ + │ ├── unit/ + │ ├── integration/ + │ ├── TEST_SPEC.md # D3D12 专项规范 + │ └── TEST_IMPROVEMENT_PLAN.md + └── OpenGL/ +``` + +--- + +## 9. 规范更新记录 + +| 版本 | 日期 | 变更 | +|------|------|------| +| 1.0 | 2026-03-20 | 初始版本,统一测试规范体系 | + +--- + +**规范版本**: 1.0 +**最后更新**: 2026-03-20 \ No newline at end of file