# XCEngine 测试规范 ## 1. 测试框架 | 组件 | 用途 | |------|------| | Google Test | 单元测试框架 | | CTest | CMake 测试发现和执行 | --- ## 2. 测试目录结构 ``` tests/ ├── CMakeLists.txt # 主 CMake 配置 (包含 enable_testing) ├── fixtures/ # 共享测试夹具 ├── math/ # 数学库测试 ├── Core/ # 核心库测试 │ ├── CMakeLists.txt │ ├── Asset/ # Core/Asset 模块测试 │ │ ├── CMakeLists.txt │ │ ├── test_iresource.cpp │ │ ├── test_resource_types.cpp │ │ ├── test_resource_guid.cpp │ │ ├── test_resource_handle.cpp │ │ ├── test_resource_cache.cpp │ │ └── test_resource_dependency.cpp │ └── IO/ # Core/IO 模块测试 │ ├── CMakeLists.txt │ ├── test_iresource_loader.cpp │ ├── test_resource_path.cpp │ ├── test_resource_filesystem.cpp │ ├── test_file_archive.cpp │ └── test_resource_package.cpp ├── containers/ # 容器测试 ├── memory/ # 内存管理测试 ├── threading/ # 线程测试 ├── debug/ # 调试系统测试 ├── Resources/ # 资源系统测试 (按类型分目录) │ ├── CMakeLists.txt │ ├── Texture/ # 纹理资源测试 │ │ ├── CMakeLists.txt │ │ ├── test_texture.cpp │ │ ├── test_texture_loader.cpp │ │ └── test_texture_import_settings.cpp │ ├── Mesh/ # 网格资源测试 │ │ ├── CMakeLists.txt │ │ ├── test_mesh.cpp │ │ ├── test_mesh_loader.cpp │ │ └── test_mesh_import_settings.cpp │ ├── Material/ # 材质资源测试 │ │ ├── CMakeLists.txt │ │ ├── test_material.cpp │ │ └── test_material_loader.cpp │ ├── Shader/ # 着色器资源测试 │ │ ├── CMakeLists.txt │ │ ├── test_shader.cpp │ │ └── test_shader_loader.cpp │ └── AudioClip/ # 音频资源测试 │ ├── CMakeLists.txt │ ├── test_audio_clip.cpp │ └── test_audio_loader.cpp ├── input/ # 输入模块测试 ├── scene/ # 场景测试 ├── components/ # 组件测试 └── rhi/ ├── CMakeLists.txt # RHI 测试主 CMake (包含 D3D12/OpenGL/unit) ├── unit/ # RHI 抽象层单元测试 (参数化, 同时测 D3D12/OpenGL) │ ├── CMakeLists.txt │ ├── fixtures/ │ └── test_*.cpp ├── d3d12/ # D3D12 后端封装测试 │ ├── CMakeLists.txt │ ├── unit/ # D3D12 单元测试 │ │ ├── fixtures/ │ │ └── test_*.cpp │ └── integration/ # D3D12 集成测试 (minimal/triangle/quad/sphere) └── opengl/ # OpenGL 后端封装测试 ├── CMakeLists.txt ├── unit/ # OpenGL 单元测试 │ ├── fixtures/ │ └── test_*.cpp └── integration/ # OpenGL 集成测试 ``` **注意**:Windows 文件系统大小写不敏感,`tests/Core/` 和 `tests/core/` 为同一目录。实际文件位于 `tests/core/`(小写),但 CMakeLists.txt 中配置为 `tests/Core/`(大写)。 ### 2.1 RHI 测试分层架构 RHI 测试分为三个层次,各层测试目标不同: | 层次 | 位置 | 测试目标 | 测试方式 | |------|------|----------|----------| | **RHI抽象层** | `tests/RHI/unit/` | RHI接口定义、跨平台抽象、后端选择 | 参数化测试 (TEST_P),一份代码同时测试 D3D12/OpenGL | | **D3D12后端封装** | `tests/RHI/D3D12/unit/` | D3D12 API封装实现 | 非参数化测试 (TEST_F),直接测试D3D12封装 | | **OpenGL后端封装** | `tests/RHI/OpenGL/unit/` | OpenGL API封装实现 | 非参数化测试 (TEST_F),直接测试OpenGL封装 | **注意**:三层测试不是冗余,而是测试不同层次的封装。各层测试可以验证: - RHI抽象层测试验证接口兼容性和跨平台一致性 - 后端专用测试验证各后端实现的正确性 --- ## 3. 模块命名 | 模块 | 可执行文件 | CTest 名称前缀 | |------|----------|---------------| | math | math_tests | Math_* | | Core | core_tests | Core_* | | containers | containers_tests | Containers_* | | memory | memory_tests | MemoryTest_* | | threading | threading_tests | Threading_* | | debug | debug_tests | Debug_* | | Resources/Texture | resources_texture_tests | Texture_* | | Resources/Mesh | resources_mesh_tests | Mesh_* | | Resources/Material | resources_material_tests | Material_* | | Resources/Shader | resources_shader_tests | Shader_* | | Resources/AudioClip | resources_audioclip_tests | AudioClip_* | | input | input_tests | Input*/WindowsInput* | | scene | scene_tests | Scene*/SceneManager_* | | components | components_tests | Component_*|TransformComponent_* | | RHI/unit (抽象层) | rhi_unit_tests | D3D12/RHITestFixture.*
OpenGL/RHITestFixture.* | | RHI/D3D12 (后端) | rhi_d3d12_tests | D3D12TestFixture.*
SwapChainTestFixture.* | | RHI/OpenGL (后端) | rhi_opengl_tests | OpenGLTestFixture.* | ### 3.1 RHI 参数化测试说明 `tests/RHI/unit/` 使用 Google Test 参数化测试 (TEST_P): ```cpp // 使用 INSTANTIATE_TEST_SUITE_P 创建两个测试变体 INSTANTIATE_TEST_SUITE_P(D3D12, RHITestFixture, ::testing::Values(RHIType::D3D12)); INSTANTIATE_TEST_SUITE_P(OpenGL, RHITestFixture, ::testing::Values(RHIType::OpenGL)); // 测试名称格式: Suite/TestName/Instance // 例如: D3D12/RHITestFixture.Buffer_Create/0 // OpenGL/RHITestFixture.Buffer_Create/0 ``` **CTest 前缀说明**: - `D3D12/` - D3D12 后端实例 - `OpenGL/` - OpenGL 后端实例 --- ## 4. 测试用例命名 **格式**: `Component_Category_SubBehavior` | 部分 | 说明 | 示例 | |------|------|------| | Component | 被测组件 | Memory, Buffer, Texture | | Category | 操作类别 | Create, Get, Set, Map, Reset | | SubBehavior | 具体行为 | DefaultHeap, GPUAddress, ValidPointer | **示例**: ``` Buffer_Create_DefaultHeap Texture_Create_2D Fence_Signal_Wait ``` **禁止模式**: - `*_Placeholder` - 无意义的占位测试 - 驼峰+下划线混用 --- ## 5. CMake 规范 ### 5.1 单元测试模板 ```cmake cmake_minimum_required(VERSION 3.15) find_package(GTest REQUIRED) set(TEST_SOURCES test_module.cpp ) add_executable(module_tests ${TEST_SOURCES}) if(MSVC) set_target_properties(module_tests PROPERTIES LINK_FLAGS "/NODEFAULTLIB:libcpmt.lib /NODEFAULTLIB:libcmt.lib" ) endif() target_link_libraries(module_tests PRIVATE XCEngine GTest::gtest GTest::gtest_main ) target_include_directories(module_tests PRIVATE ${CMAKE_SOURCE_DIR}/engine/include ${CMAKE_SOURCE_DIR}/tests/fixtures ) include(GoogleTest) gtest_discover_tests(module_tests) ``` ### 5.2 RHI 测试 CMakeLists 模板 ```cmake cmake_minimum_required(VERSION 3.15) project(rhi_backend_tests) find_package(GTest REQUIRED) find_package(Python3 REQUIRED) # 集成测试需要 # 单元测试 set(UNIT_TEST_SOURCES fixtures/TestFixture.cpp test_*.cpp ) add_executable(rhi_backend_tests ${UNIT_TEST_SOURCES}) target_link_libraries(rhi_backend_tests PRIVATE d3d12 dxgi d3dcompiler XCEngine GTest::gtest GTest::gtest_main ) target_include_directories(rhi_backend_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/fixtures ${CMAKE_SOURCE_DIR}/engine/include ${CMAKE_SOURCE_DIR}/engine/src ) # 集成测试 add_subdirectory(integration) include(GoogleTest) gtest_discover_tests(rhi_backend_tests) ``` --- ## 6. 测试执行 ### 6.1 增量构建(推荐) **何时需要重新运行 `cmake ..`**: - 新增/删除/重命名源文件 - 修改 CMakeLists.txt(添加 subdirectory、target 等) - 修改编译器选项或宏定义 **增量构建命令**: ```bash # 1. 增量配置(检测 CMakeLists.txt 变化) cd build cmake .. # 2. 只构建特定 target(不重新配置整个项目) cmake --build . --target math_tests --config Debug # 3. 只构建特定模块 cmake --build . --target rhi_unit_tests --config Debug # RHI抽象层测试 cmake --build . --target rhi_d3d12_tests --config Debug # D3D12后端测试 cmake --build . --target rhi_opengl_tests --config Debug # OpenGL后端测试 ``` ### 6.2 完整构建 ```bash cmake --build build --config Debug cd build && ctest -C Debug --output-on-failure ``` ### 6.3 测试运行 ```bash # 列出所有测试 ctest -N # 运行所有测试 ctest -C Debug --output-on-failure # 运行特定模块测试 ctest -R "^Math_" -C Debug --output-on-failure # 运行 RHI 抽象层测试 (D3D12 + OpenGL 同时测试) ctest -R "^D3D12/|^OpenGL/" -C Debug --output-on-failure # 只运行 RHI 抽象层的 D3D12 后端测试 ctest -R "^D3D12/" -C Debug --output-on-failure # 只运行 RHI 抽象层的 OpenGL 后端测试 ctest -R "^OpenGL/" -C Debug --output-on-failure # 运行 D3D12 后端专用测试 ctest -R "D3D12TestFixture|SwapChainTestFixture" -C Debug --output-on-failure # 运行 OpenGL 后端专用测试 ctest -R "OpenGLTestFixture" -C Debug --output-on-failure # 运行特定测试用例 ctest -R "Buffer_Create" -C Debug --output-on-failure ``` --- ## 7. 测试实现规范 ### 7.1 单元测试结构 ```cpp #include #include 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); } ``` ### 7.2 断言选择 | 断言 | 用途 | |------|------| | `ASSERT_*` | 致命错误,立即终止测试 | | `EXPECT_*` | 非致命错误,继续执行 | --- ## 8. CI 配置 ```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: cd build && ctest -C Debug --output-on-failure ``` --- ## 9. 性能参考 ### 9.1 模块构建和运行时间 | 模块 | 构建时间 | 运行时间 | 测试数量 | |------|---------|---------|---------| | math | ~6s | ~26s | 140 | | Core | ~6s | ~4s | 25 | | containers | ~3s | ~10s | 51 | | memory | ~3s | ~4s | 19 | | threading | ~5s | ~4s | 13 | | debug | ~3s | ~2s | 8 | | components | ~3s | ~8s | 39 | | scene | ~4s | ~2s | 14 | | Resources/Texture | ~4s | ~31s | 36 | | Resources/Mesh | ~4s | ~31s | 29 | | Resources/Material | ~4s | ~31s | 14 | | Resources/Shader | ~4s | ~31s | 13 | | Resources/AudioClip | ~4s | ~31s | 15 | | input | ~4s | ~9s | 40 | | RHI/unit (抽象层) | ~20s | ~60s | 138 (69×2后端) | | D3D12 unit | ~3s | ~55s | 54 | | OpenGL unit | ~46s | ~11s | 61 | | **总计** | - | - | **852 (+1 disabled)** | **注意**:RHI/unit 抽象层测试数量为 69 个用例,每个用例同时在 D3D12 和 OpenGL 两个后端上执行,共 138 次测试运行。Resources 模块测试已按类型拆分到独立子目录中。 ### 9.2 分模块构建命令(推荐) ```bash # ==================== 快速开发工作流 ==================== # 1. 修改某个模块代码后,增量构建该模块 cmake --build . --target math_tests --config Debug cmake --build . --target core_tests --config Debug cmake --build . --target containers_tests --config Debug cmake --build . --target memory_tests --config Debug cmake --build . --target threading_tests --config Debug cmake --build . --target debug_tests --config Debug cmake --build . --target components_tests --config Debug cmake --build . --target scene_tests --config Debug cmake --build . --target resources_texture_tests --config Debug cmake --build . --target resources_mesh_tests --config Debug cmake --build . --target resources_material_tests --config Debug cmake --build . --target resources_shader_tests --config Debug cmake --build . --target resources_audioclip_tests --config Debug cmake --build . --target input_tests --config Debug cmake --build . --target rhi_unit_tests --config Debug # RHI抽象层测试 cmake --build . --target rhi_d3d12_tests --config Debug cmake --build . --target rhi_opengl_tests --config Debug # 2. 只运行该模块测试 ctest -R "^Math_" -C Debug --output-on-failure ctest -R "^Core_" -C Debug --output-on-failure ctest -R "^Containers_" -C Debug --output-on-failure ctest -R "MemoryTest_|LinearAllocator|PoolAllocator" -C Debug --output-on-failure ctest -R "^Threading_" -C Debug --output-on-failure ctest -R "^Debug_" -C Debug --output-on-failure ctest -R "Component_Test|TransformComponent_" -C Debug --output-on-failure ctest -R "^Scene_" -C Debug --output-on-failure ctest -R "Texture[A-Z]|Mesh[A-Z]|Shader[A-Z]|AudioClip[A-Z]|Material[A-Z]" -C Debug --output-on-failure ctest -R "Input|WindowsInput" -C Debug --output-on-failure ctest -R "^D3D12/|^OpenGL/" -C Debug --output-on-failure # RHI抽象层测试 ctest -R "D3D12TestFixture|SwapChainTestFixture" -C Debug --output-on-failure # D3D12后端测试 ctest -R "OpenGLTestFixture" -C Debug --output-on-failure # OpenGL后端测试 ``` ### 9.3 按功能组构建和运行 ```bash # ==================== 基础设施模块 ==================== cmake --build . --target math_tests --config Debug cmake --build . --target core_tests --config Debug cmake --build . --target containers_tests --config Debug ctest -R "^Math_|^Core_|^Containers_" -C Debug --output-on-failure # ==================== 核心系统模块 ==================== cmake --build . --target memory_tests --config Debug cmake --build . --target threading_tests --config Debug cmake --build . --target debug_tests --config Debug ctest -R "MemoryTest_|LinearAllocator|PoolAllocator|^Threading_|^Debug_" -C Debug --output-on-failure # ==================== 游戏引擎模块 ==================== cmake --build . --target components_tests --config Debug cmake --build . --target scene_tests --config Debug cmake --build . --target resources_texture_tests --config Debug cmake --build . --target resources_mesh_tests --config Debug cmake --build . --target resources_material_tests --config Debug cmake --build . --target resources_shader_tests --config Debug cmake --build . --target resources_audioclip_tests --config Debug cmake --build . --target input_tests --config Debug ctest -R "Component_Test|TransformComponent_|^Scene_|Texture[A-Z]|Mesh[A-Z]|Shader[A-Z]|AudioClip[A-Z]|Material[A-Z]|Input|WindowsInput" -C Debug --output-on-failure # ==================== RHI 模块 ==================== # RHI抽象层测试 (推荐优先测试,同时验证D3D12和OpenGL) cmake --build . --target rhi_unit_tests --config Debug ctest -R "^D3D12/|^OpenGL/" -C Debug --output-on-failure # RHI后端专用测试 (验证特定后端实现) cmake --build . --target rhi_d3d12_tests --config Debug cmake --build . --target rhi_opengl_tests --config Debug ctest -R "D3D12TestFixture|SwapChainTestFixture" -C Debug --output-on-failure ctest -R "OpenGLTestFixture" -C Debug --output-on-failure ``` ### 9.4 注意事项 - **RHI/unit 抽象层测试**:运行时间~60s,138次测试(69用例×2后端)。推荐优先测试,可快速验证接口兼容性和跨平台一致性 - **OpenGL 后端测试**:构建时间较长(~46s),因为需要编译 glad.c。建议单独构建 - **D3D12 后端测试**:运行时间较长(~55s),适合 CI 自动化 - **Resources 模块**:运行时间~31s,包含大量资源加载测试 - **Math 模块**:运行时间~26s,包含140个数学运算测试 --- **最后更新**: 2026-03-24 --- ## 附录 A. RHI 测试分层详解 ### A.1 为什么需要三层测试? RHI(Render Hardware Interface)抽象层测试的目的是确保: 1. **接口兼容性** - RHI定义的抽象接口在不同后端都能正常工作 2. **跨平台一致性** - 同样的代码逻辑在D3D12和OpenGL上行为一致 3. **后端实现正确性** - 各后端的封装实现符合RHI接口约定 ### A.2 三层测试的关系 ``` ┌─────────────────────────────────────────────────────────────┐ │ RHI 抽象层测试 (unit/) │ │ TEST_P: 一份代码,验证 D3D12/OpenGL 接口兼容 │ │ 实例: D3D12/RHITestFixture.* / OpenGL/RHITestFixture.* │ └─────────────────────────────────────────────────────────────┘ │ ┌───────────────────┴───────────────────┐ ▼ ▼ ┌─────────────────────────┐ ┌─────────────────────────┐ │ D3D12 后端测试 │ │ OpenGL 后端测试 │ │ (D3D12/unit/) │ │ (OpenGL/unit/) │ │ TEST_F: D3D12 专用 │ │ TEST_F: OpenGL 专用 │ │ 验证 D3D12 封装实现 │ │ 验证 OpenGL 封装实现 │ └─────────────────────────┘ └─────────────────────────┘ ``` ### A.3 测试执行建议 | 场景 | 推荐测试 | |------|---------| | 日常开发 (RHI 接口验证) | `rhi_unit_tests` | | 开发 D3D12 后端 | `rhi_unit_tests` + `rhi_d3d12_tests` | | 开发 OpenGL 后端 | `rhi_unit_tests` + `rhi_opengl_tests` | | CI 自动化 | `rhi_unit_tests` + `rhi_d3d12_tests` + `rhi_opengl_tests` | ### A.4 可执行文件命名规范 ``` rhi_<层级>_tests ├── rhi_unit_tests # RHI抽象层测试 ├── rhi_d3d12_tests # D3D12后端封装测试 └── rhi_opengl_tests # OpenGL后端封装测试 ```