# Testing, packaging, installing, and releasing Blender extensions The goal is to test the same artifact a user installs, while keeping local Blender preferences and production scenes out of the test. ## Test layers ### 1. Syntax and registration Import/register the extension in Blender's Python, not system Python. Ordinary Python usually has no compatible `bpy` module. A useful smoke test should: 1. start from `--factory-startup --background`; 2. register or enable the extension; 3. build its own minimal scene and data-blocks; 4. invoke the public operator/API; 5. assert outputs and persistent results; 6. assert selection, active object, render state, and source data restoration; 7. assert temporary objects/materials/meshes/images were removed; 8. print one unmistakable success marker. The current extension test is: ```bash ./blender/scripts/test.sh ``` When more extensions are added, give each one a focused test file and make the shared test helper run each in a fresh Blender process. Fresh processes prevent registration and global-state leakage between tests. ### 2. Manifest validation Validate source metadata before packaging: ```bash blender --factory-startup --command extension validate \ blender/material_id_baker ``` Then validate the actual ZIP: ```bash VERSION=1.2.0 blender --factory-startup --command extension validate \ "dist/material_id_baker-${VERSION}.zip" ``` ZIP validation catches package-root and build-exclusion mistakes that source validation cannot. ### 3. Installed-package test Build all packages: ```bash ./build-all.sh ``` Install into an isolated Blender profile on Linux/macOS: ```bash test_profile="$(mktemp -d)" BLENDER_USER_RESOURCES="$test_profile" ./install-all.sh ``` Then launch Blender with the same `BLENDER_USER_RESOURCES` and assert registered operators/classes are present. Do not point install tests at the developer's real profile unless the user explicitly wants to update it. On Windows, set `BLENDER_USER_RESOURCES` to a temporary directory before running `install-all.bat` from the same Command Prompt. ### 4. Manual UI test Headless tests do not prove layout quality or interactive behavior. Before a release, install the ZIP and check: - panel location, labels, spacing, disabled states, and tooltips; - behavior with no object, wrong object type, wrong mode, missing UV/material, linked data, shared data, and unsaved `.blend` paths as relevant; - Undo/Redo for scene changes; - disabling and re-enabling without restarting Blender; - saving/reopening the `.blend` when properties or generated data persist; - output in the Image Editor, Shader Editor, Outliner, and exporter as relevant. ## Build helpers in this repository `build-all.sh` recursively discovers `blender_manifest.toml` under `blender/` and writes versioned packages to `dist/`: ```bash BLENDER_BIN=/path/to/blender-5.2 ./build-all.sh ``` `install-all.sh` builds, installs, and enables only the packages produced by that invocation: ```bash BLENDER_EXTENSION_REPO=user_default ./install-all.sh ``` Windows: ```bat set "BLENDER_BIN=C:\Program Files\Blender Foundation\Blender 5.2\blender.exe" set "BLENDER_EXTENSION_REPO=user_default" install-all.bat ``` Close open Blender processes before replacing an extension. Reinstalling files does not reload a module already imported by a running process. ## Versioning and release checklist Use semantic versions in `blender_manifest.toml`: - patch: compatible bug fix or internal improvement; - minor: backward-compatible user-visible feature; - major: breaking behavior/configuration/workflow change. Release sequence: 1. Finish source and documentation changes. 2. Update/add automated tests and run them. 3. Bump the manifest version. 4. Validate the source directory. 5. Run `./build-all.sh`. 6. Validate the new versioned ZIP. 7. Install the ZIP into an isolated profile and confirm it enables. 8. Perform the relevant manual UI/export test in the target Blender version. 9. Inspect ZIP contents; source/tests/repository files must not leak into it. 10. Distribute the immutable ZIP. Do not replace a published ZIP without also changing its version. Inspect package contents on Unix-like systems with: ```bash unzip -l dist/-.zip ``` An add-on extension ZIP should normally contain `blender_manifest.toml`, `__init__.py`, its internal modules/assets, and declared wheels—nothing from other extensions or repository-level tests. ## Headless installation scopes For the current Blender user, the supported CLI operation is: ```bash blender --factory-startup --command extension install-file \ -r user_default -e dist/-.zip ``` `-e` enables the extension and updates that user's preferences. For a machine-wide deployment, extract packages into the read-only system repository layout: ```text $BLENDER_SYSTEM_EXTENSIONS/ system/ / blender_manifest.toml __init__.py ``` System-repository availability is separate from per-user enablement. Managed deployments can use a startup script under `BLENDER_SYSTEM_SCRIPTS/startup/` to enable required packages. See Blender's [production deployment guide](https://docs.blender.org/manual/en/dev/advanced/deploying_blender.html). ## Official references - [Creating extensions](https://docs.blender.org/manual/en/dev/advanced/extensions/getting_started.html) - [Extension CLI](https://docs.blender.org/manual/en/dev/advanced/command_line/extension_arguments.html) - [Production/system extension deployment](https://docs.blender.org/manual/en/dev/advanced/deploying_blender.html) - [Python wheels](https://docs.blender.org/manual/en/dev/advanced/extensions/python_wheels.html)