# OpenGL 测试专项规范 本文档是 XCEngine 测试规范的 OpenGL 专项补充。 **前置阅读**: [tests/TEST_SPEC.md](../TEST_SPEC.md) - 通用测试规范 --- ## 1. 概述 ### 1.1 OpenGL 测试特点 | 特点 | 说明 | |------|------| | 平台依赖 | Windows WGL 实现,Win32 原生 API | | 窗口依赖 | 集成测试需要 GUI 窗口 | | GPU 状态 | 测试间可能有 GPU 状态污染 | | 无 GLFW | 已移除 GLFW 依赖,使用 Win32 WGL API | ### 1.2 测试层级 | 层级 | 位置 | 执行方式 | 框架 | |------|------|----------|------| | 单元测试 | `tests/RHI/OpenGL/unit/` | CTest | Google Test | | 集成测试 | `tests/RHI/OpenGL/integration/` | CTest + Python | Python wrapper | --- ## 2. 单元测试规范 ### 2.1 Fixture 设计 每个测试独立创建 OpenGL 上下文,避免 GPU 状态污染: ```cpp class OpenGLTestFixture : public ::testing::Test { protected: void SetUp() override; // 创建窗口、初始化 OpenGL 上下文 void TearDown() override; // 清理资源、销毁上下文 HWND GetHWND(); HDC GetHDC(); HGLRC GetGLRC(); void MakeCurrent(); }; ``` ### 2.2 测试前缀对应 | 类名 | 测试前缀 | |------|---------| | OpenGLDevice | Device | | OpenGLSwapChain | SwapChain | | OpenGLBuffer | Buffer | | OpenGLTexture | Texture | | OpenGLShader | Shader | | OpenGLCommandList | CommandList | | OpenGLPipelineState | PipelineState | | OpenGLRenderTargetView | RTV | | OpenGLDepthStencilView | DSV | | OpenGLFence | Fence | | OpenGLSampler | Sampler | | OpenGLVertexArray | VertexArray | --- ## 3. 集成测试规范 ### 3.1 目录结构 每个集成测试独占一个子文件夹,资源相互隔离: ``` integration/ ├── CMakeLists.txt # 构建配置 ├── run_integration_test.py # 公共测试运行脚本 ├── compare_ppm.py # PPM 图像比对脚本 ├── minimal/ # 最小化测试 │ ├── main.cpp │ ├── GT.ppm │ ├── CMakeLists.txt │ └── run.bat └── ... # 其他测试 ``` ### 3.2 Python Wrapper **位置**: `tests/RHI/OpenGL/integration/run_integration_test.py` **职责**: 1. 启动 OpenGL exe 2. 等待进程完成 3. 检查输出文件 (PPM 截图) 4. 调用 `compare_ppm.py` 比对 Golden Image 5. 返回 0(成功)/1(失败) ### 3.3 CTest 注册格式 ```cmake add_test(NAME OpenGL_Minimal_Integration COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py $ minimal.ppm ${CMAKE_CURRENT_SOURCE_DIR}/minimal/GT.ppm 5 WORKING_DIRECTORY $ ) ``` ### 3.4 Golden Image 规范 | 属性 | 值 | |------|-----| | 格式 | PPM (P6) | | 命名 | `GT.ppm` 或 `GT_.ppm` | | 阈值 | 默认 5% | | 存储位置 | `tests/RHI/OpenGL/integration//` | ### 3.5 Golden Image 生成流程 1. 在干净硬件环境运行集成测试 2. 截图保存为 `minimal.ppm` 3. 人工验证截图正确性 4. 提交到版本控制作为 GT ### 3.6 当前集成测试 | 测试名 | Golden Image | 状态 | |--------|-------------|------| | OpenGL_Minimal_Integration | `minimal/GT.ppm` | ✅ 通过 | --- ## 4. 测试执行 ### 4.1 单元测试 ```bash # 方式 1: 使用统一脚本 python scripts/run_tests.py --unit-only # 方式 2: 直接使用 CTest cd build/tests/RHI/OpenGL/unit ctest -C Debug --output-on-failure ``` ### 4.2 集成测试 ```bash # 方式 1: 使用统一脚本 python scripts/run_tests.py --integration # 方式 2: 直接使用 CTest cd build/tests/RHI/OpenGL/integration ctest -C Debug --output-on-failure ``` ### 4.3 构建和测试 ```bash # 构建 cmake --build . --target OpenGL_Minimal --config Debug # 运行测试 python scripts/run_tests.py --build ``` --- ## 5. CI 集成 ### 5.1 GitHub Actions 配置 ```yaml name: OpenGL 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 OpenGL Tests run: cmake --build build --target OpenGL_Minimal --config Debug - name: Run Unit Tests run: cd build/tests/RHI/OpenGL/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/OpenGL/ ├── CMakeLists.txt ├── TEST_SPEC.md # 本文档 (OpenGL 专项) ├── unit/ │ ├── CMakeLists.txt │ ├── fixtures/ │ │ ├── OpenGLTestFixture.h │ │ └── OpenGLTestFixture.cpp │ └── test_device.cpp └── integration/ ├── CMakeLists.txt ├── run_integration_test.py # 公共脚本 ├── compare_ppm.py # 公共脚本 └── minimal/ # 最小化测试 ├── main.cpp ├── GT.ppm ├── CMakeLists.txt └── run.bat ``` --- ## 7. 已知问题 ### 7.1 窗口尺寸问题 **问题**: `SetWindowPos` 的尺寸参数在 `WS_OVERLAPPEDWINDOW` 风格下是完整窗口尺寸(包含 chrome、边框),而不是客户区尺寸。 **修复**: 使用 `AdjustWindowRect` 计算完整尺寸后再传给 `SetWindowPos`。 --- ## 8. 规范更新记录 | 版本 | 日期 | 变更 | |------|------|------| | 1.0 | 2026-03-20 | 初始版本,移除 GLFW 依赖后的重构版本 | --- **规范版本**: 1.0 **最后更新**: 2026-03-20 **前置文档**: [tests/TEST_SPEC.md](../TEST_SPEC.md)