Blender 插件开发需要更多 DevOps

发布: (2025年12月6日 GMT+8 08:47)
8 min read
原文: Dev.to

Source: Dev.to

概览

编写测试代码并实现自动化。
在多个 Blender 版本上运行测试,以安心发布。

  • 想要(或已经)开发 Blender 插件的个人开发者。
  • 想确保质量但不知道如何引入 CI/CD 的人。
  • 对手动修复和检查感到厌倦的人。
  • 对使用 GitHub Actions 实现 CI/CD 感兴趣的人(本文将通用的 CI/CD 流水线应用到 Blender 插件开发中)。

关于 DevOps 的文献非常丰富,这里就不深入探讨了。简而言之,它被视为通用软件开发的最佳实践。在这种方法论中,开发流程被表示为以下阶段的无限循环:

阶段Blender 插件开发中的过程
Plan规划功能实现、Bug 修复等
Code编写 Python 代码
Build创建干净的 ZIP 文件
Test手动或自动化测试
Release发布已测试的 ZIP(GitHub/Extensions)
Deploy用户下载 ZIP 并在 Blender 中安装
Operate用户在生产环境中实际使用插件
Monitor接收用户的 issue 与反馈

本文重点关注标有 的阶段:CodeBuildTestRelease

问题

Blender 5 上个月正式发布。我安装了 5 的 beta 版以及约 30 个插件(付费和免费都有),其中很多都报错。即使在正式版发布后,仍有若干插件没有可用的发行版。当插件描述写着 “支持 4.2 及以上” 但在 Blender 5 中失效时,用户只能纠结是等待更新还是自行修复。

一个简单的 CI 设置,即使只跑一次,也能检测出基本的兼容性错误。维护者随后可以临时声明不再支持 Blender 5,或明确结束支持。如果维护者已经失联,那也只能无计可施。

在不同规模的仓库中观察到,Blender 插件生态的测试文化相较于其他软件开发领域更为薄弱。官方类项目往往拥有自动化测试和交付流水线,但许多个人开发者的仓库——即使是热门仓库——也缺乏任何测试自动化。手动测试流程常常缺失,导致提交 PR 时缺乏信心,因为潜在的副作用未知。大型插件随着功能请求的增加往往变得臃肿,进一步加大维护难度。

根本原因在于通用软件开发的常用实践尚未渗透到 Blender 插件社区。本文提出一种可以直接采用的方法。

一个已准备好进行 DevOps 的插件示例:SavePoints

我最近在 Blender Extensions 上发布了我的第一个插件 SavePoints。它可以为 .blend 文件保存缩略图和备注,并执行定期自动保存。该插件从一开始就以 DevOps 为目标构建,作为模板供大家参考。

  • 扩展页面:

可维护性目标

  1. 可测试性 – 将逻辑隔离以便进行单元测试。
  2. CI 兼容性 – 确保插件能够在无头环境(-b 参数)下运行。
  3. 明确分层 – 将 Blender‑specific 代码保持在最小范围。

无头环境

无头环境指在没有 GUI 的情况下运行 Blender:

blender -b -P my_script.py

参考文献:

实现细节

轻量的 Operator 层

operators.py 只包含 UI 粘合层。核心处理逻辑位于 core.py,且 依赖 bpy

# operators.py
class SAVEPOINTS_OT_delete(bpy.types.Operator):
    # ...
    def execute(self, context):
        # 实际处理调用 core.py 中的函数
        delete_version_by_id(item.version_id)
        return {'FINISHED'}

# core.py
def delete_version_by_id(version_id: str) -> None:
    # 标准 Python 逻辑(shutil、json 等)– 不使用 bpy
    ...

这种分离使得单元测试可以在不启动 Blender 的情况下运行。

优先使用 bpy.data 而非 bpy.ops

经验法则:尽可能使用 bpy.data;只有在绝对必要时才回退到 bpy.opsbpy.ops 会模拟用户操作,需要合适的 UI 上下文,在 CI 中常常因 poll 错误而失败。

为无头模式添加守卫子句

在使用 OpenGL 捕获缩略图时,无头模式没有窗口。代码捕获异常并跳过缩略图生成:

def capture_thumbnail(context: bpy.types.Context, thumb_path: str) -> None:
    try:
        if context.window_manager.windows:
            bpy.ops.render.opengl(write_still=True)
            # ... 保存缩略图 ...
        else:
            pass  # 在无头模式下跳过
    except Exception as e:
        print(f"Thumbnail generation failed: {e}")

虽然引入了与环境相关的分支,但可以防止 CI 崩溃。

测试策略

我将测试分为两层,以实现成本效益。

逻辑测试

  • 工具pytest + fake-bpy-module
  • 范围:验证纯 Python 逻辑(路径处理、数据计算等),不启动 Blender。
  • 频率:每次提交本地和 CI 都运行。

端到端(E2E)测试

  • 工具:在无头模式下启动真实的 Blender 并运行插件。
  • 范围:验证插件与 Blender API 的交互是否正确。
  • 频率:在开发期间偶尔运行,以及在关键 CI 事件(如合并到 main)时运行。

因为大多数兼容性问题来源于 API 变动,E2E 测试对于捕获 Blender 更新导致的破坏至关重要。

使用 GitHub Actions 设置 CI

一个最小化的工作流,运行两层测试:

name: CI

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

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        blender-version: [ "3.6", "4.0", "5.0" ]

    steps:
      - uses: actions/checkout@v3

      - name: Install Blender
        run: |
          sudo add-apt-repository ppa:thomas-schiex/blender
          sudo apt-get update
          sudo apt-get install blender=${{ matrix.blender-version }}

      - name: Install Python dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pytest fake-bpy-module

      - name: Run Logic Tests
        run: pytest tests/logic

      - name: Run E2E Tests
        run: |
          blender -b -P tests/e2e/run_tests.py

请根据你的平台自行调整 Blender 安装步骤。 该工作流会构建一个干净的 ZIP(Build 阶段),并可以将其作为发布制品(Release 阶段)上传。

结论

把 Blender 插件开发当作普通软件项目来对待——拆分代码、编写单元与 E2E 测试、并使用 CI 自动化流水线,你可以:

  • 及早发现兼容性问题(尤其是跨 Blender 版本的差异)。
  • 减少手动测试工作量。
  • 为维护者和贡献者在提交 PR 时提供信心。

采用这些实践能够让 Blender 插件生态更接近现代 DevOps 标准,从而产出更稳定、可维护的插件。

Back to Blog

相关文章

阅读更多 »