Skip to main content

pytest-blender

PyPI Python versions License Tests

Pytest plugin for Blender testing. Executes your pytest testsuite with Blender in headless mode using its builtin Python interpreter.

Install

pip install pytest-blender

Documentation

Usage

Before execute it, you need to install your testing dependencies inside the builtin Blender Python interpreter. To get the interpreter location you can use the CLI utility pytest-blender, something like:

blender_python="$(pytest-blender)"
$blender_python -m ensurepip
$blender_python -m pip install -r test-requirements.txt

After installing dependencies, just call pytest as usually.

pytest -svv
Blender 2.82 (sub 7)
Read prefs: ~/.config/blender/2.82/config/userpref.blend
=================== test session starts ===================
platform linux -- Python 3.8.5, pytest-6.1.2, py-1.9.0, pluggy-0.13.1 -- /usr/bin/blender
cachedir: .pytest_cache
rootdir: /home/mondeja/files/code/pytest-blender
collected 1 item

tests/test_bpy_import.py::test_inside_blender <module 'bpy' from '/usr/share/blender/scripts/modules/bpy/__init__.py'>
PASSED
==================== 1 passed in 0.01s ====================

Reference

Configuration

All options can be passed as a CLI argument like --[option-name] or defined inside a configuration file.

blender-executable

Specify a custom blender executable location.

pytest --blender-executable ~/blender-2.91.2-linux64/blender
[pytest]
blender-executable = ~/blender-2.91.2-linux64/blender
Blender 2.91.2 (hash 5be9ef417703 built 2021-01-19 16:16:34)
Read prefs: ~/.config/blender/2.91/config/userpref.blend
found bundled python: ~/blender-2.91.2-linux64/2.91/python
=================== test session starts ===================
platform linux -- Python 3.7.7, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
rootdir: ~/pytest-blender
collected 1 item

tests/test_bpy_import.py .                                                [100%]

==================== 1 passed in 0.00s ====================
blender-template

Load a custom startup .blend template.

pytest -svv --blender-template ~/.config/blender/2.93/config/startup.blend
[pytest]
blender-template = ~/.config/blender/2.93/config/startup.blend
addopts = -svv
blender-addons-dirs

Install addons inside Blender before executing the test suite. This allows you to easily test them.

By "addons" Blender understands Python scripts whose file names end with .py, .zip files for compressed packages with multiple modules or directories for Python packages which contain a __init__.py file. These must be located in the root of each directory passed to blender-addons-dirs.

For example, given the next directory tree:

📁 addons-dirs
├── 📁 private-addons
│   └── 📁 package_addon
│       ├── 📄 __init__.py 
│       └── 📄 main.py
|
└── 📁 public-addons
    ├── 📄 module_addon.py
    └── 📄 compressed_addon.zip
        ├── 📄 __init__.py 
        └── 📄 main.py

The next configurations will install the addons package_addon, module_addon and compressed_addon.

pytest tests --blender-addons-dirs addons-dirs/private-addons addons-dirs/public-addons
[pytest]
blender-addons-dirs =
    addons-dirs/private-addons
    addons-dirs/public-addons

You can also define a unique addons directory in configuration files defining it as a string:

[pytest]
blender-addons-dirs = addons-dirs/public-addons

If you need more complex setups see the fixtures install_addons_from_dir, disable_addons and uninstall_addons.

blender-addons-cleaning

Define the addons cleaning strategy to follow after executing your test suite. It only affects to the addons installed using blender-addons-dirs.

It accepts one of the next values:

  • uninstall (default): Uninstall the addons after executing the test suite.
  • disable: Just disable the addons in user preferences, but does not uninstall them.
  • keep: Keep the addons enabled. Useful if you want to manually review the addons or while you're developing.
pytest --blender-addons-cleaning disable
[pytest]
blender-addons-cleaning = disable
pytest-blender-debug

Show in STDOUT the command executed by pytest-blender executing your test suite.

pytest --pytest-blender-debug
[pytest]
pytest-blender-debug = true
[DEBUG (pytest-blender)] Running blender with: /usr/bin/blender -b --python /home/foo/files/code/pytest-blender/pytest_blender/run_pytest.py -- --pytest-blender-executable /usr/bin/blender -svv --rootdir=/tmp/tmpdsh0wnsf --strict-markers --strict-config -c /tmp/tmpdsh0wnsf/pytest.ini
Blender 2.82 (sub 7)
Read prefs: /home/foo/.config/blender/2.82/config/userpref.blend
=================== test session starts ===================
platform linux -- Python 3.8.10, pytest-7.0.1, pluggy-0.13.1 -- /usr/bin/blender
cachedir: .pytest_cache
rootdir: /tmp/tmpyio7hlc2, configfile: pytest.ini
plugins: cov-3.0.0, Faker-12.1.0
collecting ... collected 1 item

tests/test_foo.py::test_foo PASSED

==================== 1 passed in 0.09s ====================

Fixtures

# blender_executable ⇒ str

Returns the path of the executable that has started the current Blender session.

# blender_version ⇒ str

Returns the version of Blender running in the current session.

# blender_python_executable ⇒ str

Returns the path of the Python executable builtin in the Blender release of the currently running session.

# blender_python_version ⇒ str

Returns the version of the Python executable builtin in the Blender release of the currently running session.

# blender_addons_dir ⇒ str

Returns the scripts/addons directory of Blender (see Blender Directory Layout), the directory in which by default are located the addons installed using the install_addons_from_dir fixture.

It tries to get it using the BLENDER_USER_SCRIPTS environment variable, but if is not defined attempts to discover it from the PATH.

# install_addons_from_dir(addons_dir, addon_ids=None, save_userpref=True, default_set=True, persistent=True, quiet=True, **kwargs) ⇒ list

Function that installs and enables a set of addons which are located in a directory. By "addons" Blender understands Python scripts whose file names end with .py, .zip files for compressed packages with multiple modules or directories for Python packages which contain a __init__.py file.

This function is designed to be executed before the pytest session to install the addons that you want to test, using the others fixtures disable_addons or uninstall_addons to disable or remove them after the execution of the test suite:

import pytest

@pytest.fixture(scope="session", autouse=True)
def register_addons(install_addons_from_dir, disable_addons):
    addons_ids = install_addons_from_dir("src")
    yield
    disable_addons(addons_ids)
import pytest

@pytest.fixture(scope="session", autouse=True)
def register_addons(install_addons_from_dir, uninstall_addons):
    addons_ids = install_addons_from_dir("src")
    yield
    uninstall_addons(addons_ids)

The difference between disabling addons and uninstalling them is that disabling removes the files from the Blender's addons directory but disabling keep the files there, allowing you to enable it manually from the preferences.

  • addons_dir (str) Directory in whose root are located the files of the addons.
  • addons_ids (list) Identifiers of the addons modules, packages or ZIP files (without extensions) to install. If not defined (default) all Python modules, Python packages and ZIP files containing addon packages or modules located at the root of the addons_dir directory will be installed. These identifiers are either:
    • The name of the module for addons composed by a single file ([identifier].py).
    • The name of the directory for addons composed by a package.
    • The name of the ZIP file without extension for addons composed by a ZIP file ([identifier].zip).
  • save_userpref (bool) Save user preferences after installation calling bpy.ops.wm.save_userpref
  • default_set (bool) Set the user-preference calling addon_utils.enable.
  • persistent (bool) Ensure that the addon is enabled for the entire session, after loading new files.
  • quiet (bool) If enabled, don't show standard output produced installing addons.
  • **kwargs (dict) Subsecuent keyword arguments are passed to bpy.ops.preferences.addon_install.

Returns the addons identifiers as a list, ready to be passed to disable_addons or uninstall_addons.

# disable_addons(addons_ids, save_userpref=True, default_set=True, quiet=True, **kwargs)

Function that disables a set of addons by addons identifiers. Is designed to disable your addons after a pytest suite execution (check install_addons_from_dir for an example).

  • addons_ids (list) Identifiers of the addons modules as are returned by install_addons_from_dir.
  • save_userpref (bool) Save user preferences after installation.
  • default_set (bool) Set the user-preference calling addon_utils.disable.
  • quiet (bool) If enabled, don't show stdout produced disabling addons.
  • **kwargs (dict) Subsecuent keyword arguments are passed to addon_utils.disable.

# uninstall_addons(addons_ids, quiet=True)

Function that uninstall a set of addons by addon identifiers. Is designed to remove your addons from the Blender's addons directory after a pytest suite execution (check install_addons_from_dir for an example).

  • addons_ids (list) Name of the addons modules as is returned by install_addons_from_dir.
  • quiet (bool) If enabled, don't show stdout produced disabling addons.

Arguments propagation

When you call pytest, all options like --blender-executable are passed to the pytest suite running pytest-blender. If you want to pass arguments to blender in its headless execution, add a -- between pytest and blender arguments. For example:

pytest -svv --blender-executable ~/blender -- --debug

Measuring code coverage

You can use pytest-cov to measure code coverage. If so, instead of using blender-addons-dirs configuration option use pytest's pythonpath option.

Example for pytest.ini:

[pytest]
pythonpath = path/to/blender/addons
addopts = --cov path/to/blender/addons

CI integration

You can use blender-downloader to download multiple versions of Blender in your CI and test against them. There is an example for Github Actions in the CI configuration of this repository, something like:

jobs:
  test:
    name: Test
    runs-on: ${{ matrix.platform }}
    strategy:
      matrix:
        platform:
          - ubuntu-latest
          - macos-latest
        blender-version:
          - '3.1.2'
          - '2.93.9'
          - '2.83.9'
    steps:
      - uses: actions/checkout@v3
      - name: Set up Python v3.9
        uses: actions/setup-python@v3
        with:
          python-version: 3.9
      - name: Upgrade PIP
        run: python -m pip install --upgrade pip
      - name: Cache Blender ${{ matrix.blender-version }}
        uses: actions/cache@v3
        id: cache-blender
        with:
          path: |
            blender-*
            _blender-executable-path.txt
          key: ${{ runner.os }}-${{ matrix.blender-version }}
      - name: Download Blender ${{ matrix.blender-version }}
        if: steps.cache-blender.outputs.cache-hit != 'true'
        id: download-blender
        run: |
          python -m pip install --upgrade blender-downloader
          printf "%s" "$(blender-downloader \
          ${{ matrix.blender-version }} --extract --remove-compressed \
          --quiet --print-blender-executable)" > _blender-executable-path.txt
      - name: Install dependencies
        id: install-dependencies
        run: |
          python -m pip install .[test]
          blender_executable="$(< _blender-executable-path.txt)"
          python_blender_executable="$(pytest-blender --blender-executable $blender_executable)"
          $python_blender_executable -m ensurepip
          $python_blender_executable -m pip install pytest
          echo "blender-executable=$BLENDER_EXECUTABLE" >> $GITHUB_OUTPUT
      - name: Test with pytest
        run: pytest -svv --blender-executable \
          "${{ steps.install-dependencies.outputs.blender-executable }}" tests

Versions compatibility

  • Latest version that officially supports Python3.6 is v1.2.1.

Release files for pytest-blender 3.0.8

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-blender 3.0.8
File Size Uploaded
pytest_blender-3.0.8.tar.gz 23.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-blender 3.0.8
File Interpreter ABI Platform
pytest_blender-3.0.8-py3-none-any.whl Python 3 none any Details

Total release size: 39.6 kB

Release files / pytest_blender-3.0.8.tar.gz

Download URL pytest_blender-3.0.8.tar.gz
Size 23.2 kB
Tags Source
SHA-256 checksum
How to use checksums
1d2592c6b8a7666225905e90d944c3efcf102a3e816eb0d44429112928287cc3
BLAKE2b-256 checksum
How to use checksums
35d04fbf4fafaf7d754c24c2fa02fc093556fb7b27e4ded3852ec209a12e4df1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / pytest_blender-3.0.8-py3-none-any.whl

Download URL pytest_blender-3.0.8-py3-none-any.whl
Size 16.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
78b91e78613a45ff747e7d62b537bc9ab48d1ec8805b003ca164e13ae214085e
BLAKE2b-256 checksum
How to use checksums
960310ffd82d14b7971ec21a2bd4af7f818ece0d291332fae12c53c909753b94
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release history Release notifications | RSS feed

This release

3.0.8 This release

2 release files

3.0.7

2 release files

3.0.6

2 release files

3.0.5

2 release files

3.0.4

2 release files

3.0.3

2 release files

3.0.2

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.0.0

2 release files

1.2.2

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page