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个失败
469 lines
15 KiB
Markdown
469 lines
15 KiB
Markdown
# 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_*|TransformComponent_* |
|
||
| RHI/unit (抽象层) | rhi_unit_tests | D3D12/RHITestFixture.*<br>OpenGL/RHITestFixture.* |
|
||
| RHI/D3D12 (后端) | rhi_d3d12_tests | D3D12TestFixture.*<br>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 <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 配置
|
||
|
||
```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 | 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 分模块构建命令(推荐)
|
||
|
||
```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_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 按功能组构建和运行
|
||
|
||
```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_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 抽象层测试**:运行时间~60s,138次测试(69用例×2后端)。推荐优先测试,可快速验证接口兼容性和跨平台一致性
|
||
- **OpenGL 后端测试**:构建时间较长(~46s),因为需要编译 glad.c。建议单独构建
|
||
- **D3D12 后端测试**:运行时间较长(~55s),适合 CI 自动化
|
||
- **Resources 模块**:运行时间~31s,包含大量资源加载测试
|
||
- **Math 模块**:运行时间~26s,包含140个数学运算测试
|
||
|
||
---
|
||
|
||
**最后更新**: 2026-03-23
|
||
|
||
---
|
||
|
||
## 附录 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后端封装测试
|
||
```
|