Blender Add-on Testing Tips: How to Debug, Reload, and Automate with Python
Spencer Magnusson is the instructor of Utility: Scripting Your First Blender Add-on and is an active creator on Superhive.
Smooth Add-on Development Testing
Updated October 7th, 2025
Blender add-ons are valuable. They can save time and often money. That's why I code them. This makes add-ons even more frustrating when they don't work. How can we code bigger add-ons while also lessening the chance of bugs?
The answer is testing. While it requires more effort, especially upfront, it saves time fixing bugs later.
Key Takeaways
- Regardless of your testing method, make sure you test all aspects of your Blender add-on, from installation to turning it off.
- Use Blender’s native “Reload Scripts” button to see your code changes live, without having to restart Blender.
- Automate your testing with Python libraries like unittest or pytest as your add-on grows.
Why Testing Your Blender Add-ons Matters
I’ve managed and updated add-ons for over five years now. As a coder, you quickly realize you are not immune to bugs. Every once in a while, especially with my non-tested add-ons:
- I fix a bug in one release, and accidentally re-introduce it in a later update.
- I create a bug that shows up inconsistently. Maybe it only happens to some users, and unless I remember to recreate specific circumstances, I may never catch it, let alone fix it.
- Create an add-on so big, that manually testing could take an hour.
Both in college and at past jobs, I was introduced to rigorous testing of code. I know it’s the “not fun” part of coding. But testing your code will reduce headaches and broken add-ons down the road, for you and for users.
What To Test For
Whether you test your add-on with a script or just by hand, here are things to look out for:
- Enabling the add-on: when the user checks the box to turn on the add-on, the add-on has to register all the components it plans to use. Make sure that works successfully each time.
- UI checks: making sure the UI is as expected (panels and menus show up where they should, especially if there’s conditional logic, e.g. only when an object is selected).
- Operators: running add-on operators, both in the UI and in a script, including handling errors and various types of user input.
- Disabling the add-on: turning off the add-on (which also happens when closing Blender), should go just as smoothly as turning it on. Check Blender’s system console so there’s no errors!
Also, a good rule of thumb: for every bug you find, make a test for it. That way, once you fix it, you can always check in future updates that it’s still gone.
Use Blender’s Reload Scripts Button (Live Reloading)
Often, I update my code with Blender open. To have my changes seen in the add-on live, Blender needs to unregister and re-register that add-on. Since Python is cached, Blender would normally need to completely restart to see these changes.
But there is a better way. A workaround has been set up and supported by the Blender developers. In the menu under the Blender icon, there’s an option called Reload Scripts, along with a few other related debugging operations.

By reloading scripts, Blender unloads all Python modules loaded at runtime, which includes scripts made in the text editor and add-ons. For scripts in the text editor, you just need to re-run your script. For add-ons, Blender will also try to reload them, but you have to add a few lines of code to your add-on to reload all the Python modules used by your add-on.
Here is an example below from the official documentation. In short, if your add-on uses multiple files, and you import each one, you simply need to reload each module via importlib.reload():
_needs_reload = "bpy" in locals()
import bpy
from . import (
module1,
module2,
module3,
)
if _needs_reload:
import importlib
module1 = importlib.reload(module1)
module2 = importlib.reload(module2)
module3 = importlib.reload(module3)
print("Add-on Reloaded")
From developer.blender.org. This will allow you to make changes to your code and see them live, without having to restart Blender at all!
Automated Testing
As your add-on gets bigger, manual testing will take longer and become more complex. You will quickly wish code could just test itself. Well, it can!
There are many kinds of tests you can make. Ideally, your tests should be “with this input, I get this output.” Translated into Blender terms, if I run an operator with this input and context, I should expect this result.
For more complicated operations, you can also consider unit tests. Unit tests only test or check pieces of your add-on at a time. Think of it as, if a restaurant was inspecting their kitchen, instead of testing the kitchen by cooking a full meal, they merely test each appliance directly. The hope is that, by testing enough of your add-on in pieces, you can spot most bugs.
Python has its own testing library, unittest, as well as other third-party testing libraries like pytest. Regardless, you can test your scripts in a few ways:
- Create a Python file that will run your tests. Then, either run Blender in a terminal with a command that calls your script, e.g.
blender.exe --background --python my_python_file.py - You can also skip the terminal and open Blender, create a new text file within it, paste your script, and run it within the Blender user interface. This also gives you the benefit to have Blender take the UI into account.
- Install the Blender Python library into your Python environment. You can use sites like PyPI: pypi.org/project/bpy/. Once installed, you can run your tests with the Blender library, without the user interface or even having Blender installed!
The only caveat to this is that automated testing mainly checks things are working regardless of the UI. Your add-on may “work” from the test script, even though a panel may not display in the UI correctly.
No One Way to Test
In conclusion, there are many methods to test your code. For most small add-ons, some quick manual testing is sufficient. As your add-on gets bigger, you can try converting your manual tests into scripts.
And even as you make more thorough tests, automated testing may not catch everything. Often, I run automated tests first, and then do a quick manual test just to make sure I’m not missing anything in the user interface.
FAQ
How can I test Blender-related code using bpy while Blender is not open?
You can either have Blender run your test script for you, or use Blender as a Python module, currently available here: pypi.org/project/bpy/.
How do I install my add-on in Blender for testing?
For add-on extensions, you simply need to add the “parent” folder of the repository where your code lives as an extension repository. Then enable the add-on (note that the module path is dependent on the repository's module name):
# if my code lives in "C:\Users\spencer\Documents\Repos\addon_testing", then add “C:\Users\spencer\Documents\Repos”
repo = “C:\Users\spencer\Documents\Repos”
addon_module = 'addon_module_name'
import bpy
repo_module = 'test_repo'
new_repo = bpy.context.preferences.extensions.repos.new(
name='Test Repo',
module=repo_module,
custom_directory=repo,
source='USER'
)
cls.module_path = 'bl_ext.' + repo_module + '.' + addon_module
bpy.ops.preferences.addon_enable(module=cls.module_path)
As a “legacy” add-on, you will have to install the zip file and enable the add-on by module name.
import bpy
bpy.ops.preferences.addon_install(filepath="my_addon_as_a.zip")
bpy.ops.preferences.addon_enable(module="addon_module_name")
How can I test UI-related components of my add-on?
You can open Blender, create a new text file within it, paste your test script, and run it within the Blender user interface.
If you are running Blender from the command line, there is a relatively new flag to simulate UI events: add --enable-event-simulate and simulate events with bpy.types.Window.event_simulate.
Here's an example that will open Blender and delete the default cube:
"C:\path\to\blender.exe" --enable-event-simulate --factory-startup --python test.py
# test.py
import bpy
def run_iter_from_timer(event_iter):
i = iter(event_iter)
# latency between key presses, bigger numbers will make it run slower
SPEED = 0.0
def event_step():
ret = next(i, None)
if ret is None:
return None
return 0.0
bpy.app.timers.register(event_step, first_interval=0.0)
def delete_default_cube(window):
# template function to simplify things
def preset_event_simulate(window, event_type, value, x=960, y=540):
if value == 'TAP': # just so you don't have to do both 'PRESS' and 'RELEASE'
yield window.event_simulate(event_type, 'PRESS', x=x, y=y)
yield window.event_simulate(event_type, 'RELEASE', x=x, y=y)
else:
yield window.event_simulate(event_type, value, x=x, y=y)
yield from preset_event_simulate(window, 'ESC', 'TAP') # close splash screen
yield from preset_event_simulate(window, 'X', 'TAP') # delete cube, opens confirmation prompt
yield from preset_event_simulate(window, 'RET', 'TAP') # confirms prompt
# end event simulation, allow UI interaction by user
bpy.app.use_event_simulate = False
# optional, close Blender
# import sys
# sys.exit(0)
if __name__ == '__main__':
window = bpy.context.window
run_iter_from_timer(delete_default_cube(window))
Thanks for reading!
Spencer (Visit my Creator Shop)