GitHub Actions自动化测试LingBot-Depth:CI/CD实践指南

1. 引言

如果你正在开发或使用3D视觉模型,特别是像LingBot-Depth这样的深度补全和精化模型,那么自动化测试绝对是你需要关注的重点。传统的手动测试方式不仅耗时耗力,而且很难保证测试的一致性和覆盖率。

想象一下这样的场景:每次修改代码后,你需要手动设置测试环境、运行各种测试用例、检查输出结果,然后再生成测试报告。这个过程不仅重复枯燥,还容易出错。更重要的是,当你的模型需要支持多种硬件环境、不同CUDA版本时,手动测试几乎变得不可行。

这就是为什么我们需要GitHub Actions来自动化整个测试流程。通过构建一个完整的CI/CD流水线,你可以实现:

  • 代码推送后自动触发测试
  • 在真实的GPU环境中验证模型性能
  • 支持多版本兼容性测试
  • 自动生成详细的测试报告
  • 确保每次提交的质量和稳定性

本文将手把手带你搭建一个完整的LingBot-Depth自动化测试流水线,让你从此告别手动测试的烦恼。

2. 环境准备与基础配置

2.1 创建测试仓库结构

首先,我们需要为LingBot-Depth项目创建一个规范的测试目录结构。在你的项目根目录下创建如下结构:

lingbot-depth/
├── tests/
│   ├── unit/
│   │   ├── test_model_loading.py
│   │   ├── test_inference.py
│   │   └── test_preprocessing.py
│   ├── integration/
│   │   ├── test_end_to_end.py
│   │   └── test_performance.py
│   ├── data/
│   │   ├── sample_rgb.png
│   │   ├── sample_depth.png
│   │   └── sample_intrinsics.txt
│   └── conftest.py
├── requirements-test.txt
└── .github/
    └── workflows/
        └── test.yml

2.2 编写基础测试用例

让我们从最简单的模型加载测试开始。在tests/unit/test_model_loading.py中:

import torch
import pytest
from mdm.model.v2 import MDMModel

def test_model_loading_cpu():
    """测试CPU环境下的模型加载"""
    model = MDMModel.from_pretrained('robbyant/lingbot-depth-pretrain-vitl-14')
    assert model is not None
    assert isinstance(model, MDMModel)

@pytest.mark.gpu
def test_model_loading_gpu():
    """测试GPU环境下的模型加载"""
    if not torch.cuda.is_available():
        pytest.skip("GPU not available")
    
    model = MDMModel.from_pretrained('robbyant/lingbot-depth-pretrain-vitl-14')
    model = model.to('cuda')
    assert model is not None
    assert next(model.parameters()).is_cuda

2.3 配置测试依赖

创建requirements-test.txt文件:

torch>=2.0.0
torchvision>=0.15.0
opencv-python>=4.5.0
numpy>=1.21.0
pytest>=7.0.0
pytest-cov>=4.0.0
pytest-xdist>=3.0.0
transformers>=4.30.0
huggingface-hub>=0.15.0

3. GitHub Actions流水线配置

3.1 基础测试工作流

.github/workflows/test.yml中创建基础测试配置:

name: LingBot-Depth CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [3.9, 3.10]
        cuda-version: ['11.8', '12.1']

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v4
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install CUDA ${{ matrix.cuda-version }}
      uses: conda-incubator/setup-miniconda@v2
      with:
        miniconda-version: "latest"
        python-version: ${{ matrix.python-version }}
        channels: conda-forge,defaults
        channel-priority: strict

    - name: Install dependencies
      run: |
        conda install -y cudatoolkit=${{ matrix.cuda-version }}
        pip install -r requirements-test.txt

    - name: Run unit tests
      run: |
        python -m pytest tests/unit/ -v --cov=mdm --cov-report=xml

    - name: Upload coverage reports
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage.xml

3.2 GPU测试环境配置

为了在GitHub Actions中使用GPU,我们需要配置自托管Runner。首先创建.github/workflows/gpu-test.yml

name: GPU Tests

on:
  workflow_dispatch:
  schedule:
    - cron: '0 0 * * 0'  # 每周日运行一次全面测试

jobs:
  gpu-test:
    runs-on: [self-hosted, gpu-linux]
    container:
      image: nvidia/cuda:12.1.0-runtime-ubuntu20.04

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.10'

    - name: Install system dependencies
      run: |
        apt-get update && apt-get install -y \
            libgl1-mesa-glx \
            libglib2.0-0

    - name: Install Python dependencies
      run: |
        pip install -r requirements-test.txt

    - name: Run GPU tests
      run: |
        python -m pytest tests/ -m gpu -v --tb=short

    - name: Run performance benchmarks
      run: |
        python tests/integration/test_performance.py

4. 自定义GPU Runner部署

4.1 准备GPU服务器

如果你有可用的GPU服务器,可以将其设置为自托管Runner。首先在服务器上安装必要的依赖:

# 安装Docker和NVIDIA容器工具包
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# 安装NVIDIA容器工具包
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

sudo apt-get update && sudo apt-get install -y nvidia-docker2
sudo systemctl restart docker

4.2 配置GitHub自托管Runner

在GitHub仓库的Settings → Actions → Runners中点击"New self-hosted runner",然后按照指引在服务器上执行提供的命令。

创建启动脚本start-runner.sh

#!/bin/bash
cd /home/ubuntu/actions-runner

# 配置环境变量
export ENV=production
export GPU_TYPE=$(nvidia-smi --query-gpu=name --format=csv,noheader | head -n1)

./run.sh

4.3 使用Docker容器进行测试

为了确保测试环境的一致性,我们可以使用Docker容器。创建Dockerfile.test

FROM nvidia/cuda:12.1.0-runtime-ubuntu20.04

# 设置工作目录
WORKDIR /app

# 安装系统依赖
RUN apt-get update && apt-get install -y \
    python3.10 \
    python3-pip \
    libgl1-mesa-glx \
    libglib2.0-0 \
    && rm -rf /var/lib/apt/lists/*

# 复制项目文件
COPY . .

# 安装Python依赖
RUN pip install --no-cache-dir -r requirements-test.txt

# 设置入口点
ENTRYPOINT ["python", "-m", "pytest", "tests/", "-v"]

5. 多版本兼容性测试

5.1 矩阵测试配置

扩展我们的测试矩阵,覆盖更多环境组合:

jobs:
  compatibility-test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - python-version: '3.9'
            torch-version: '2.0.0'
            cuda-version: '11.8'
          - python-version: '3.10'
            torch-version: '2.1.0'
            cuda-version: '12.1'
          - python-version: '3.10'
            torch-version: '2.1.0'
            cuda-version: 'cpu'

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v4
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install specific torch version
      run: |
        if [ "${{ matrix.cuda-version }}" = "cpu" ]; then
          pip install torch==${{ matrix.torch-version }} --index-url https://download.pytorch.org/whl/cpu
        else
          pip install torch==${{ matrix.torch-version }} --index-url https://download.pytorch.org/whl/cu118
        fi

    - name: Run compatibility tests
      run: |
        python -m pytest tests/unit/test_compatibility.py -v

5.2 编写兼容性测试用例

创建tests/unit/test_compatibility.py

import torch
import pytest
from mdm.model.v2 import MDMModel

@pytest.mark.parametrize("device", ["cpu", "cuda"])
def test_model_device_compatibility(device):
    """测试模型在不同设备上的兼容性"""
    if device == "cuda" and not torch.cuda.is_available():
        pytest.skip("CUDA not available")
    
    try:
        model = MDMModel.from_pretrained('robbyant/lingbot-depth-pretrain-vitl-14')
        model = model.to(device)
        
        # 验证模型参数在正确的设备上
        for param in model.parameters():
            assert param.device.type == device
            
    except Exception as e:
        pytest.fail(f"Model failed on {device}: {str(e)}")

def test_mixed_precision_compatibility():
    """测试混合精度兼容性"""
    if not torch.cuda.is_available():
        pytest.skip("CUDA not available")
    
    try:
        from torch.cuda.amp import autocast
        
        model = MDMModel.from_pretrained('robbyant/lingbot-depth-pretrain-vitl-14')
        model = model.to('cuda').half()  # 使用半精度
        
        with autocast():
            # 创建一个简单的测试输入
            dummy_input = torch.randn(1, 3, 224, 224).half().cuda()
            output = model(dummy_input)
            
            assert output is not None
            
    except Exception as e:
        pytest.fail(f"Mixed precision failed: {str(e)}")

6. 测试报告与结果分析

6.1 自动化测试报告生成

我们可以使用pytest插件来生成丰富的测试报告。首先安装必要的依赖:

pip install pytest-html pytest-json-report

然后在GitHub Actions中配置报告生成:

- name: Run tests with detailed reporting
  run: |
    python -m pytest tests/ \
      -v \
      --html=test-report.html \
      --json-report \
      --json-report-file=test-report.json \
      --cov=mdm \
      --cov-report=html:coverage-html

- name: Upload test reports
  uses: actions/upload-artifact@v3
  with:
    name: test-reports
    path: |
      test-report.html
      test-report.json
      coverage-html/

6.2 性能基准测试

创建性能测试脚本tests/integration/test_performance.py

import time
import torch
import pytest
from mdm.model.v2 import MDMModel

@pytest.mark.performance
class TestPerformance:
    @classmethod
    def setup_class(cls):
        cls.device = 'cuda' if torch.cuda.is_available() else 'cpu'
        cls.model = MDMModel.from_pretrained('robbyant/lingbot-depth-pretrain-vitl-14')
        cls.model = cls.model.to(cls.device)
        cls.model.eval()
        
        # 准备测试数据
        cls.batch_sizes = [1, 2, 4]
        cls.resolutions = [(224, 224), (448, 448), (672, 672)]

    def test_inference_latency(self):
        """测试推理延迟"""
        results = {}
        
        for batch_size in self.batch_sizes:
            for height, width in self.resolutions:
                # 准备输入数据
                image = torch.randn(batch_size, 3, height, width).to(self.device)
                depth = torch.randn(batch_size, 1, height, width).to(self.device)
                intrinsics = torch.randn(batch_size, 3, 3).to(self.device)
                
                # 预热
                for _ in range(3):
                    _ = self.model.infer(image, depth, intrinsics)
                
                # 正式测试
                start_time = time.time()
                for _ in range(10):
                    _ = self.model.infer(image, depth, intrinsics)
                elapsed = time.time() - start_time
                
                avg_latency = elapsed / 10
                results[f'bs{batch_size}_{height}x{width}'] = avg_latency
                
                print(f"Batch {batch_size}, {height}x{width}: {avg_latency:.3f}s")
        
        return results

    def test_memory_usage(self):
        """测试内存使用情况"""
        if self.device == 'cpu':
            pytest.skip("Memory test requires GPU")
        
        memory_stats = {}
        torch.cuda.empty_cache()
        
        for batch_size in [1, 2]:
            image = torch.randn(batch_size, 3, 224, 224).to(self.device)
            depth = torch.randn(batch_size, 1, 224, 224).to(self.device)
            intrinsics = torch.randn(batch_size, 3, 3).to(self.device)
            
            torch.cuda.reset_peak_memory_stats()
            _ = self.model.infer(image, depth, intrinsics)
            
            peak_memory = torch.cuda.max_memory_allocated() / 1024**2  # MB
            memory_stats[f'batch_{batch_size}'] = peak_memory
            
            print(f"Batch {batch_size}: {peak_memory:.1f}MB")
        
        return memory_stats

7. 高级功能与优化技巧

7.1 分布式测试支持

对于大型测试套件,我们可以使用分布式测试来加速执行:

- name: Run distributed tests
  run: |
    python -m pytest tests/ \
      -n auto \
      --dist=loadscope \
      --junitxml=junit.xml \
      -rf

7.2 缓存优化

通过缓存依赖项来加速CI/CD流程:

- name: Cache pip packages
  uses: actions/cache@v3
  with:
    path: ~/.cache/pip
    key: ${{ runner.os }}-pip-${{ hashFiles('requirements-test.txt') }}
    restore-keys: |
      ${{ runner.os }}-pip-

- name: Cache model weights
  uses: actions/cache@v3
  with:
    path: ~/.cache/huggingface/hub
    key: ${{ runner.os }}-models-${{ hashFiles('requirements-test.txt') }}
    restore-keys: |
      ${{ runner.os }}-models-

7.3 安全扫描集成

在测试流水线中集成安全扫描:

- name: Security scan
  uses: actions/codeql-analysis@v2
  with:
    languages: python

- name: Dependency vulnerability scan
  uses: actions/dependency-review-action@v3

8. 总结

通过本文的实践,我们成功构建了一个完整的LingBot-Depth自动化测试流水线。这个流水线不仅能够自动运行单元测试和集成测试,还能在真实的GPU环境中验证模型性能,支持多版本兼容性测试,并自动生成详细的测试报告。

实际使用下来,这套自动化测试方案确实大大提高了开发效率。每次代码提交后,GitHub Actions会自动运行所有测试用例,及时发现潜在的问题。多环境兼容性测试也帮助我们提前发现了很多在不同CUDA版本和硬件环境下的兼容性问题。

如果你也在开发类似的3D视觉模型,强烈建议尽早引入自动化测试。刚开始可能会觉得配置比较麻烦,但一旦搭建完成,后续的维护成本其实很低,而带来的收益却是巨大的。特别是对于需要支持多种部署环境的项目,自动化测试几乎是必不可少的。

下一步,你可以考虑进一步扩展测试覆盖范围,比如增加更多的边缘用例测试、性能回归测试,或者集成端到端的系统测试。也可以考虑使用更高级的监控和告警机制,确保测试失败时能够及时通知到相关人员。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐