Skip to content

Commit 95dabd8

Browse files
committed
Convert blender tests to pytest with unified infrastructure
- Migrate 8 unittest-based files to pytest framework - Standardize all test classes with unified mixins - Implement BlenderTestMixin and TestAssertionsMixin in conftest.py - Convert 4 test classes, 11 test paths, 33 test methods, 104 total tests - Replace unittest imports and decorators with pytest equivalents - Establish consistent mixin-based inheritance patterns - Maintain all existing functionality while modernizing architecture - Resolve complex inheritance chains like TestGenericJoinBefore - Preserve parametrized test support throughout conversion"
1 parent 0b1c309 commit 95dabd8

23 files changed

+2413
-2027
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,9 @@ jobs:
4242
contains(github.ref, 'main') ||
4343
contains(github.ref, 'develop') ||
4444
github.event_name == 'pull_request'
45-
env:
46-
PYTHONPATH: ${{ github.workspace }}:addons
4745
run: |
4846
# Run basic pytest tests (without Blender integration)
49-
uv run pytest tests/test_test.py tests/blender/test_proxy.py -v
50-
continue-on-error: true
47+
PYTHONPATH="$(pwd)/addons:$(pwd) uv run pytest -v
5148
5249
- name: Upload build artifacts
5350
if: contains(github.ref, 'main')

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ dependencies = [
1111
"pytest>=8.0.0",
1212
"bpy==4.5.2",
1313
"ruff>=0.4.10",
14+
"parameterized>=0.7.4",
1415
]
1516

1617
[project.optional-dependencies]
@@ -45,7 +46,7 @@ minversion = "8.0"
4546
addopts = "--strict-markers --disable-warnings"
4647
testpaths = ["tests"]
4748
python_files = ["test_*.py"]
48-
python_classes = ["Test*"]
49+
python_classes = ["*Test*", "Test*", "TestCase*", "TestImage*"]
4950
python_functions = ["test_*"]
5051
pythonpath = [".", "addons"]
5152

tests/blender/blender_testcase.py

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,46 +17,48 @@ class BlenderTestCase(MixerTestCase):
1717
Test case for the Full Blender protocol
1818
"""
1919

20-
def __init__(self):
20+
def __init__(self, *args, **kwargs):
2121
# in case @parameterized_class is missing
2222
if not hasattr(self, "vrtist_protocol"):
2323
self.vrtist_protocol = False
24-
super().__init__()
24+
super().__init__(*args, **kwargs)
2525

26-
def setup_method(self, *args, **kwargs):
27-
super().setup_method(*args, **kwargs)
26+
# Add failureException for unittest compatibility
27+
self.failureException = AssertionError
28+
29+
def setup_method(self, method):
30+
super().setup_method()
31+
32+
33+
def create_basic_blender_setup(join=True):
34+
"""Helper function to create basic Blender setup"""
35+
sender_blendfile = files_folder() / "empty.blend"
36+
receiver_blendfile = files_folder() / "empty.blend"
37+
sender = BlenderDesc(load_file=sender_blendfile, wait_for_debugger=False)
38+
receiver = BlenderDesc(load_file=receiver_blendfile, wait_for_debugger=False)
39+
blenderdescs = [sender, receiver]
40+
return blenderdescs
2841

2942

3043
class TestGeneric(BlenderTestCase):
3144
"""Test that joins a room before message creation"""
3245

33-
def __init__(self):
34-
self._join = True # Default value
35-
36-
def setup_method(self):
37-
sender_blendfile = files_folder() / "empty.blend"
38-
receiver_blendfile = files_folder() / "empty.blend"
39-
sender = BlenderDesc(load_file=sender_blendfile, wait_for_debugger=False)
40-
receiver = BlenderDesc(load_file=receiver_blendfile, wait_for_debugger=False)
41-
blenderdescs = [sender, receiver]
42-
super().setup_method(blenderdescs=blenderdescs, server_args=None, join=self._join)
46+
def setup_method(self, method):
47+
blenderdescs = create_basic_blender_setup(join=True)
48+
super().setup_method(blenderdescs=blenderdescs, server_args=None, join=True)
4349

4450

4551
class TestGenericJoinBefore(TestGeneric):
4652
"""Test that joins a room before message creation"""
4753

48-
def __init__(self):
49-
self._join = True
50-
51-
def setup_method(self):
52-
super().setup_method()
54+
def setup_method(self, method):
55+
blenderdescs = create_basic_blender_setup(join=True)
56+
super().setup_method(blenderdescs=blenderdescs, server_args=None, join=True)
5357

5458

5559
class TestGenericJoinAfter(TestGeneric):
5660
"""Test that does not join a room before message creation"""
5761

58-
def __init__(self):
59-
self._join = False
60-
61-
def setup_method(self):
62-
super().setup_method()
62+
def setup_method(self, method):
63+
blenderdescs = create_basic_blender_setup(join=False)
64+
super().setup_method(blenderdescs=blenderdescs, server_args=None, join=False)

tests/blender/test_animation.py

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,7 @@
1-
import pytest
2-
# Create a pytest-compatible wrapper for MixerTestCase
3-
from tests.mixer_testcase import MixerTestCase as BaseMixerTestCase
4-
from tests.mixer_testcase import BlenderDesc
5-
from tests import files_folder
1+
from tests.conftest import BlenderTestMixin, TestAssertionsMixin
62

73

8-
class MixerTestCaseWrapper(BaseMixerTestCase):
9-
"""Pytest-compatible wrapper for MixerTestCase"""
10-
11-
def __init__(self):
12-
# Initialize the base class directly
13-
super().__init__()
14-
# Add pytest-compatible assertion methods
15-
self.failureException = AssertionError
16-
17-
def setup_method(self):
18-
# Call the base setup_method with Blender configurations
19-
sender_blendfile = files_folder() / "empty.blend"
20-
receiver_blendfile = files_folder() / "empty.blend"
21-
sender = BlenderDesc(load_file=sender_blendfile, wait_for_debugger=False)
22-
receiver = BlenderDesc(load_file=receiver_blendfile, wait_for_debugger=False)
23-
blenderdescs = [sender, receiver]
24-
super().setup_method(blenderdescs=blenderdescs, join=True)
25-
26-
def teardown_method(self):
27-
# Clean up blender instances
28-
super().teardown_method()
29-
30-
31-
class TestCase(MixerTestCaseWrapper):
4+
class TestCase(BlenderTestMixin, TestAssertionsMixin):
325
pass
336

347

@@ -185,7 +158,3 @@ def test_add_variable(self):
185158
self.send_string(action)
186159

187160
self.end_test()
188-
189-
190-
if __name__ == "__main__":
191-
pytest.main([__file__])

tests/blender/test_armatures.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
import unittest
1+
import pytest
22

33
from tests import files_folder
4-
from tests.blender.blender_testcase import BlenderTestCase
4+
from tests.conftest import BlenderTestMixin, TestAssertionsMixin
55
from tests.mixer_testcase import BlenderDesc
66

77

8-
class TestCase(BlenderTestCase):
8+
class TestCase(BlenderTestMixin, TestAssertionsMixin):
9+
@pytest.fixture(autouse=True)
10+
def setup_testcase(self, tmp_path, blender_empty_blend):
11+
"""Pytest fixture for setup that runs automatically"""
12+
self.tmp_path = tmp_path
13+
self.blender_empty_blend = blender_empty_blend
14+
self.setup_blender_instances()
915
def setUp(self):
1016
sender_blendfile = files_folder() / "empty.blend"
1117
receiver_blendfile = files_folder() / "empty.blend"
@@ -95,7 +101,3 @@ def test_reverse_bones_parenting(self):
95101
command = override_context + create
96102
self.send_string(command, sleep=1)
97103
self.end_test()
98-
99-
100-
if __name__ == "__main__":
101-
unittest.main()

0 commit comments

Comments
 (0)