143 lines
5.3 KiB
Python
143 lines
5.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Blender Python script that runs INSIDE Blender to test texture generation.
|
|
This script has NO mocks - it uses the real addon code with real bpy.
|
|
|
|
CRITICAL: This test calls the ACTUAL Blender operator (bpy.ops.text_texture.generate_shader)
|
|
because the bug is in the OPERATOR's truthiness check at generation_ops.py:241-247,
|
|
not in the generate_texture_image() function itself.
|
|
"""
|
|
|
|
import sys
|
|
import bpy
|
|
|
|
|
|
def test_shader_creation_with_texture():
|
|
"""
|
|
E2E test: Call the ACTUAL Blender operator to expose truthiness bug.
|
|
|
|
BUG LOCATION: src/operators/generation_ops.py:241-247
|
|
```python
|
|
result = generate_texture_image(props, final_width, final_height)
|
|
if not result: # ❌ BUG: (None, None) is TRUTHY in Python!
|
|
self.report({'ERROR'}, "Failed to generate texture image")
|
|
return {'CANCELLED'}
|
|
```
|
|
|
|
When generate_texture_image() returns (None, None):
|
|
- `not result` evaluates to False (non-empty tuple is truthy)
|
|
- Error check is bypassed
|
|
- Code continues until line 263 where it tries to use None values
|
|
|
|
This test MUST call bpy.ops.text_texture.generate_shader() (the operator)
|
|
NOT generate_texture_image() (the function) to expose the bug.
|
|
"""
|
|
|
|
# Clean slate - remove default objects
|
|
bpy.ops.object.select_all(action='SELECT')
|
|
bpy.ops.object.delete()
|
|
|
|
# Create a new cube (we need an object to attach material to)
|
|
bpy.ops.mesh.primitive_cube_add()
|
|
cube = bpy.context.active_object
|
|
|
|
# Set up scene properties for texture generation
|
|
props = bpy.context.scene.text_texture_props
|
|
|
|
# Configure text using the actual property structure
|
|
props.text = "böhm Kabel"
|
|
props.append_text = "NYY"
|
|
|
|
# Set dimensions (user-specified, not generated)
|
|
props.texture_width = 4096
|
|
props.texture_height = 512
|
|
|
|
# Configure shader settings
|
|
props.shader_type = 'PRINCIPLED'
|
|
props.shader_connection = 'BASE_COLOR'
|
|
props.auto_assign_material = True
|
|
props.generate_normal_map = False
|
|
props.background_transparent = True
|
|
|
|
print(f"\nTest scenario:")
|
|
print(f" Main text: {props.text}")
|
|
print(f" Append text: {props.append_text}")
|
|
print(f" Dimensions: {props.texture_width}x{props.texture_height}")
|
|
print(f"\nCalling bpy.ops.text_texture.generate_shader()...")
|
|
|
|
# CRITICAL: Call the OPERATOR (not the function!)
|
|
# This is the REAL code path that users trigger from the UI
|
|
try:
|
|
result = bpy.ops.text_texture.generate_shader()
|
|
print(f"Operator returned: {result}")
|
|
except Exception as e:
|
|
print(f"FAILURE: Operator raised exception: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
sys.exit(1)
|
|
|
|
# Assert 1: Operator should return {'FINISHED'} on success
|
|
# Current bug: Will return {'CANCELLED'} because truthiness check at line 241 is wrong
|
|
if result != {'FINISHED'}:
|
|
print(f"FAILURE: Operator returned {result} instead of {{'FINISHED'}}")
|
|
print(f"This confirms the truthiness bug at generation_ops.py:241-247")
|
|
print(f"The check 'if not result:' fails when result is (None, None)")
|
|
print(f"because non-empty tuples are truthy in Python!")
|
|
sys.exit(1)
|
|
|
|
# Assert 2: Material should be created
|
|
# The material name is based on sanitized text
|
|
materials = [m.name for m in bpy.data.materials]
|
|
print(f"Available materials: {materials}")
|
|
|
|
# Check for TextTexture_Mat prefix (the actual naming pattern used)
|
|
material_found = any("TextTexture_Mat" in m for m in materials)
|
|
if not material_found:
|
|
print(f"FAILURE: No TextTexture_Mat material found")
|
|
print(f"This indicates the operator failed to complete shader creation")
|
|
sys.exit(1)
|
|
|
|
# Assert 3: Texture image should be created
|
|
images = [i.name for i in bpy.data.images]
|
|
print(f"Available images: {images}")
|
|
|
|
# Check for TextTexture prefix (the actual naming pattern used)
|
|
image_found = any("TextTexture" in i for i in images)
|
|
if not image_found:
|
|
print(f"FAILURE: No TextTexture image found")
|
|
print(f"This indicates generate_texture_image() returned None or (None, None)")
|
|
sys.exit(1)
|
|
|
|
# Get the actual image
|
|
img = None
|
|
for image in bpy.data.images:
|
|
if "TextTexture" in image.name and "Normal" not in image.name:
|
|
img = image
|
|
break
|
|
|
|
if not img:
|
|
print(f"FAILURE: Could not retrieve texture image")
|
|
sys.exit(1)
|
|
|
|
# Assert 4: Verify dimensions
|
|
actual_width = img.size[0]
|
|
actual_height = img.size[1]
|
|
|
|
if actual_width != 4096 or actual_height != 512:
|
|
print(f"FAILURE: Wrong dimensions. Expected 4096x512, got {actual_width}x{actual_height}")
|
|
sys.exit(1)
|
|
|
|
# Assert 5: Material should be assigned to cube
|
|
if not cube.data.materials or len(cube.data.materials) == 0:
|
|
print(f"FAILURE: No material assigned to cube")
|
|
sys.exit(1)
|
|
|
|
# Success markers for test_addon_real_blender.py to detect
|
|
print("SUCCESS: Texture generated successfully with correct dimensions and shader connected")
|
|
print(f"SUCCESS: Texture '{img.name}' created with size {actual_width}x{actual_height}")
|
|
print(f"SUCCESS: Shader nodes created and connected")
|
|
sys.exit(0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
test_shader_creation_with_texture() |