tests
This commit is contained in:
3
tests/integration/__init__.py
Normal file
3
tests/integration/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Integration tests for Text Texture Generator.
|
||||
"""
|
||||
BIN
tests/integration/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
tests/integration/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
204
tests/integration/test_text_generation_pipeline.py
Normal file
204
tests/integration/test_text_generation_pipeline.py
Normal file
@@ -0,0 +1,204 @@
|
||||
"""
|
||||
Integration tests for the complete text generation pipeline.
|
||||
Tests how the core modules work together.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import Mock, patch, MagicMock
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add src to path for importing modules
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../src'))
|
||||
|
||||
from fixtures.sample_data import *
|
||||
|
||||
|
||||
class TestTextGenerationPipeline:
|
||||
"""Integration tests for the complete text generation workflow"""
|
||||
|
||||
@pytest.mark.integration
|
||||
@patch('src.core.text_processor.process_multiline_text')
|
||||
@patch('src.core.text_fitting.find_optimal_font_size')
|
||||
@patch('src.core.text_fitting.calculate_text_position')
|
||||
def test_basic_text_generation_workflow(self, mock_calc_position, mock_find_size, mock_process_text):
|
||||
"""Test the basic workflow from text input to positioned output"""
|
||||
# Setup mocks
|
||||
mock_process_text.return_value = {
|
||||
'lines': ['Hello', 'World'],
|
||||
'total_height': 40,
|
||||
'line_count': 2
|
||||
}
|
||||
mock_find_size.return_value = 24
|
||||
mock_calc_position.return_value = {
|
||||
'x': 50, 'y': 50,
|
||||
'text_width': 100, 'text_height': 40
|
||||
}
|
||||
|
||||
# Simulate a basic workflow
|
||||
text = "Hello\nWorld"
|
||||
font = Mock()
|
||||
canvas_width, canvas_height = 300, 200
|
||||
|
||||
# Step 1: Process multiline text
|
||||
from src.core.text_processor import process_multiline_text
|
||||
processed = process_multiline_text(text, font, canvas_width, canvas_height)
|
||||
|
||||
# Step 2: Find optimal font size
|
||||
from src.core.text_fitting import find_optimal_font_size
|
||||
optimal_size = find_optimal_font_size(text, "/fake/font.ttf", 200, 100)
|
||||
|
||||
# Step 3: Calculate position
|
||||
from src.core.text_fitting import calculate_text_position
|
||||
available_area = {'x': 0, 'y': 0, 'width': canvas_width, 'height': canvas_height}
|
||||
position = calculate_text_position(text, font, available_area, 'center')
|
||||
|
||||
# Verify workflow completed
|
||||
assert processed['line_count'] == 2
|
||||
assert optimal_size == 24
|
||||
assert position['x'] == 50 and position['y'] == 50
|
||||
|
||||
# Verify functions were called in sequence
|
||||
mock_process_text.assert_called_once()
|
||||
mock_find_size.assert_called_once()
|
||||
mock_calc_position.assert_called_once()
|
||||
|
||||
@pytest.mark.integration
|
||||
@patch('src.core.text_fitting.check_text_overlap')
|
||||
@patch('src.core.text_fitting.resolve_text_conflicts')
|
||||
def test_overlap_detection_and_resolution_workflow(self, mock_resolve, mock_check):
|
||||
"""Test the workflow for detecting and resolving text overlaps"""
|
||||
# Setup mocks
|
||||
mock_check.return_value = [(0, 1)] # Positions 0 and 1 overlap
|
||||
mock_resolve.return_value = [
|
||||
{'x': 0, 'y': 0, 'width': 100, 'height': 50},
|
||||
{'x': 0, 'y': 60, 'width': 100, 'height': 50} # Moved down
|
||||
]
|
||||
|
||||
# Initial overlapping positions
|
||||
positions = [
|
||||
{'x': 0, 'y': 0, 'width': 100, 'height': 50},
|
||||
{'x': 50, 'y': 25, 'width': 100, 'height': 50} # Overlaps
|
||||
]
|
||||
|
||||
# Step 1: Check for overlaps
|
||||
from src.core.text_fitting import check_text_overlap
|
||||
overlaps = check_text_overlap(positions)
|
||||
|
||||
# Step 2: Resolve conflicts
|
||||
from src.core.text_fitting import resolve_text_conflicts
|
||||
resolved = resolve_text_conflicts(positions, 500, 400)
|
||||
|
||||
# Verify workflow
|
||||
assert len(overlaps) == 1
|
||||
assert len(resolved) == 2
|
||||
assert resolved[1]['y'] == 60 # Second position moved down
|
||||
|
||||
mock_check.assert_called_once_with(positions)
|
||||
mock_resolve.assert_called_once()
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_text_metrics_and_fitting_integration(self):
|
||||
"""Test integration between text metrics calculation and fitting"""
|
||||
with patch('src.core.text_processor.calculate_text_metrics') as mock_metrics, \
|
||||
patch('src.core.text_fitting.calculate_text_scaling') as mock_scaling:
|
||||
|
||||
# Setup mocks
|
||||
mock_metrics.return_value = {
|
||||
'width': 200, 'height': 50,
|
||||
'ascent': 40, 'descent': 10
|
||||
}
|
||||
mock_scaling.return_value = (1.5, 2.0, 1.5) # width_scale, height_scale, uniform_scale
|
||||
|
||||
# Test workflow
|
||||
font = Mock()
|
||||
text = "Sample Text"
|
||||
|
||||
from src.core.text_processor import calculate_text_metrics
|
||||
from src.core.text_fitting import calculate_text_scaling
|
||||
|
||||
# Get text metrics
|
||||
metrics = calculate_text_metrics(text, font)
|
||||
|
||||
# Calculate scaling based on metrics
|
||||
scaling = calculate_text_scaling(text, font, 300, 100)
|
||||
|
||||
# Verify integration
|
||||
assert metrics['width'] == 200
|
||||
assert metrics['height'] == 50
|
||||
assert scaling[2] == 1.5 # uniform_scale
|
||||
|
||||
mock_metrics.assert_called_once_with(text, font)
|
||||
mock_scaling.assert_called_once()
|
||||
|
||||
@pytest.mark.integration
|
||||
@patch('src.core.text_fitting.calculate_available_text_area')
|
||||
@patch('src.core.text_processor.optimize_text_layout')
|
||||
def test_area_calculation_and_layout_optimization(self, mock_optimize, mock_calc_area):
|
||||
"""Test integration between area calculation and layout optimization"""
|
||||
# Setup mocks
|
||||
mock_calc_area.return_value = {
|
||||
'x': 10, 'y': 10, 'width': 300, 'height': 200, 'area': 60000
|
||||
}
|
||||
mock_optimize.return_value = [
|
||||
{'x': 10, 'y': 10, 'width': 100, 'height': 50, 'text': 'Block 1'},
|
||||
{'x': 150, 'y': 10, 'width': 80, 'height': 40, 'text': 'Block 2'}
|
||||
]
|
||||
|
||||
# Test data
|
||||
canvas_width, canvas_height = 400, 300
|
||||
overlays = [{'x': 350, 'y': 250, 'width': 50, 'height': 50}]
|
||||
text_blocks = [
|
||||
{'x': 50, 'y': 50, 'width': 100, 'height': 50, 'text': 'Block 1'},
|
||||
{'x': 75, 'y': 75, 'width': 80, 'height': 40, 'text': 'Block 2'} # Overlaps
|
||||
]
|
||||
|
||||
# Test workflow
|
||||
from src.core.text_fitting import calculate_available_text_area
|
||||
from src.core.text_processor import optimize_text_layout
|
||||
|
||||
# Step 1: Calculate available area
|
||||
available_area = calculate_available_text_area(canvas_width, canvas_height, overlays)
|
||||
|
||||
# Step 2: Optimize layout
|
||||
optimized_blocks = optimize_text_layout(text_blocks, canvas_width, canvas_height)
|
||||
|
||||
# Verify integration
|
||||
assert available_area['width'] == 300
|
||||
assert available_area['area'] == 60000
|
||||
assert len(optimized_blocks) == 2
|
||||
assert optimized_blocks[0]['x'] == 10 # First block positioned in available area
|
||||
|
||||
mock_calc_area.assert_called_once_with(canvas_width, canvas_height, overlays)
|
||||
mock_optimize.assert_called_once_with(text_blocks, canvas_width, canvas_height)
|
||||
|
||||
|
||||
class TestErrorHandlingIntegration:
|
||||
"""Integration tests for error handling across modules"""
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_graceful_degradation_on_font_errors(self):
|
||||
"""Test that the system degrades gracefully when font operations fail"""
|
||||
with patch('PIL.ImageFont.truetype') as mock_truetype:
|
||||
mock_truetype.side_effect = OSError("Font not found")
|
||||
|
||||
# Test that font size finding falls back gracefully
|
||||
from src.core.text_fitting import find_optimal_font_size
|
||||
result = find_optimal_font_size("Test", "/fake/font.ttf", 200, 100)
|
||||
|
||||
assert result == 8 # Should fall back to minimum size
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_error_handling_in_text_processing_chain(self):
|
||||
"""Test error handling when text processing components fail"""
|
||||
with patch('src.core.text_processor.wrap_text_to_width') as mock_wrap:
|
||||
mock_wrap.side_effect = Exception("Text wrapping failed")
|
||||
|
||||
# Test that multiline processing handles wrap failures
|
||||
from src.core.text_processor import process_multiline_text
|
||||
result = process_multiline_text("Test text", Mock(), 200, 100)
|
||||
|
||||
# Should return fallback result instead of crashing
|
||||
assert 'lines' in result
|
||||
assert 'total_height' in result
|
||||
assert 'line_count' in result
|
||||
Reference in New Issue
Block a user