Files
XCEngine/tests/TEST_SPEC.md
ssdfasd bc6b47ffcf fix: RHI单元测试修复与命名规范统一
RHI抽象层测试修复:
- OpenGL Shader: 空描述符正确返回nullptr
- OpenGL Texture: 修复TextureType映射(case 2/3)
- OpenGL Buffer: 设置stride和state支持
- OpenGL Texture: 添加Format和State支持
- OpenGL SwapChain: 修复IsFullscreen硬编码false问题

命名规范统一( snake_case + _test后缀):
- D3D12_Minimal -> d3d12_minimal_test
- D3D12_Triangle -> d3d12_triangle_test
- D3D12_Quad -> d3d12_quad_test
- D3D12_Sphere -> d3d12_sphere_test
- OpenGL_Minimal -> opengl_minimal_test
- OpenGL_Triangle -> opengl_triangle_test
- OpenGL_Quad -> opengl_quad_test
- OpenGL_Sphere -> opengl_sphere_test
- CTest名称去掉_Integration后缀

测试结果: 138个测试中从21个失败减少到16个失败
2026-03-23 20:32:33 +08:00

15 KiB
Raw Blame History

XCEngine 测试规范

1. 测试框架

组件 用途
Google Test 单元测试框架
CTest CMake 测试发现和执行

2. 测试目录结构

tests/
├── CMakeLists.txt              # 主 CMake 配置 (包含 enable_testing)
├── fixtures/                   # 共享测试夹具
├── math/                      # 数学库测试
├── core/                      # 核心库测试
├── containers/                # 容器测试
├── memory/                    # 内存管理测试
├── threading/                 # 线程测试
├── debug/                     # 调试系统测试
├── resources/                 # 资源系统测试
├── 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 集成测试

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 resources_tests Resource*/Texture*/Mesh* 等
input input_tests Input*/WindowsInput*
scene scene_tests Scene*/SceneManager_*
components components_tests Component_*
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)

// 使用 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_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_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 等)
  • 修改编译器选项或宏定义

增量构建命令

# 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 完整构建

cmake --build build --config Debug
cd build && ctest -C Debug --output-on-failure

6.3 测试运行

# 列出所有测试
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 单元测试结构

#include <gtest/gtest.h>
#include <XCEngine/Module/Component.h>

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 配置

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 18
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 ~4s ~31s 131
input ~4s ~9s 40
RHI/unit (抽象层) ~20s ~60s 138 (69×2后端)
D3D12 unit ~3s ~55s 54
OpenGL unit ~46s ~11s 61
总计 - - ~760

注意RHI/unit 抽象层测试数量为 69 个用例,每个用例同时在 D3D12 和 OpenGL 两个后端上执行,共 138 次测试运行。

9.2 分模块构建命令(推荐)

# ==================== 快速开发工作流 ====================

# 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_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 "Resource[A-Z]|Texture[A-Z]|Mesh[A-Z]|Shader[A-Z]|Audio[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 按功能组构建和运行

# ==================== 基础设施模块 ====================
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_tests --config Debug
cmake --build . --target input_tests --config Debug
ctest -R "Component_Test|TransformComponent_|^Scene_|Resource[A-Z]|Texture[A-Z]|Mesh[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 抽象层测试:运行时间~60s138次测试69用例×2后端。推荐优先测试可快速验证接口兼容性和跨平台一致性
  • OpenGL 后端测试:构建时间较长(~46s),因为需要编译 glad.c。建议单独构建
  • D3D12 后端测试:运行时间较长(~55s),适合 CI 自动化
  • Resources 模块:运行时间~31s包含大量资源加载测试
  • Math 模块:运行时间~26s包含140个数学运算测试

最后更新: 2026-03-23


附录 A. RHI 测试分层详解

A.1 为什么需要三层测试?

RHIRender 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后端封装测试