Files
ewoooc/tests/test_ppt_vision_service.py
OoO 2234488378
All checks were successful
CD Pipeline / deploy (push) Successful in 57s
fix: route special ollama fallbacks through cascade
2026-05-13 21:41:43 +08:00

163 lines
5.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
tests/test_ppt_vision_service.py
─────────────────────────────────────────────────────────────────
Operation Ollama-First v5.0 / Phase 14 — PPT vision (minicpm-v) 驗證
"""
import os
import tempfile
import logging
from unittest.mock import patch, MagicMock
import pytest
@pytest.fixture(autouse=True)
def _reset_env(monkeypatch):
monkeypatch.delenv('PPT_VISION_ENABLED', raising=False)
yield
@pytest.fixture
def fake_image():
"""產生 1KB 假 png 檔給 test 用"""
f = tempfile.NamedTemporaryFile(suffix='.png', delete=False)
f.write(b'\x89PNG\r\n\x1a\n' + b'\x00' * 1000) # PNG magic + 1KB padding
f.close()
yield f.name
try:
os.unlink(f.name)
except Exception:
pass
def test_flag_off_returns_disabled_error(fake_image):
"""flag OFF 時 check_image 直接回 success=False不打 HTTP"""
from services.ppt_vision_service import PPTVisionService
svc = PPTVisionService()
with patch('services.ollama_service.requests.post') as mock_post:
result = svc.check_image(fake_image)
assert result.success is False
assert 'PPT_VISION_ENABLED=false' in (result.error or '')
mock_post.assert_not_called()
def test_missing_image_file(monkeypatch):
monkeypatch.setenv('PPT_VISION_ENABLED', 'true')
from services.ppt_vision_service import PPTVisionService
svc = PPTVisionService()
result = svc.check_image('/tmp/this_file_does_not_exist_xyz.png')
assert result.success is False
assert 'image not found' in (result.error or '')
def test_no_issues_response(fake_image, monkeypatch):
"""minicpm-v 回「✅ 無視覺異常」→ issues_found 應為空 list"""
monkeypatch.setenv('PPT_VISION_ENABLED', 'true')
from services.ppt_vision_service import PPTVisionService
fake_resp = MagicMock(status_code=200)
fake_resp.json.return_value = {'response': '✅ 無視覺異常'}
with patch('services.ollama_service.resolve_ollama_host',
return_value='http://test:11434'), \
patch('services.ollama_service.requests.post', return_value=fake_resp) as mock_post:
svc = PPTVisionService()
result = svc.check_image(fake_image)
assert result.success is True
assert result.issues_found == []
assert result.confidence == 1.0
payload = mock_post.call_args.kwargs['json']
assert payload['model'] == 'minicpm-v:latest'
assert payload['images'] and isinstance(payload['images'][0], str)
def test_issues_detected(fake_image, monkeypatch):
"""minicpm-v 回多個 ⚠️ marker → issues_found 應含解析的問題"""
monkeypatch.setenv('PPT_VISION_ENABLED', 'true')
from services.ppt_vision_service import PPTVisionService
fake_resp = MagicMock(status_code=200)
fake_resp.json.return_value = {
'response': '⚠️ 圖表被切掉:右側長條圖超出邊界\n'
'⚠️ 文字溢出:商品標題被遮擋\n'
'其他無問題'
}
with patch('services.ollama_service.resolve_ollama_host',
return_value='http://test:11434'), \
patch('services.ollama_service.requests.post', return_value=fake_resp):
svc = PPTVisionService()
result = svc.check_image(fake_image)
assert result.success is True
assert len(result.issues_found) == 2
assert any('圖表被切掉' in i for i in result.issues_found)
assert any('文字溢出' in i for i in result.issues_found)
assert result.confidence > 0.5
def test_http_500_marks_unhealthy(fake_image, monkeypatch):
"""HTTP 500 → success=False + mark_unhealthy 被呼叫"""
monkeypatch.setenv('PPT_VISION_ENABLED', 'true')
from services.ppt_vision_service import PPTVisionService
fake_resp = MagicMock(status_code=500)
fake_resp.text = 'oops'
with patch('services.ollama_service.resolve_ollama_host',
return_value='http://test:11434'), \
patch('services.ollama_service.mark_unhealthy') as mock_mark, \
patch('services.ollama_service.requests.post', return_value=fake_resp):
svc = PPTVisionService()
result = svc.check_image(fake_image)
assert result.success is False
assert 'HTTP 500' in (result.error or '')
mock_mark.assert_called_once_with('http://test:11434')
def test_http_500_preserves_error_when_mark_unhealthy_fails(fake_image, monkeypatch, caplog):
monkeypatch.setenv('PPT_VISION_ENABLED', 'true')
from services.ppt_vision_service import PPTVisionService
fake_resp = MagicMock(status_code=500)
fake_resp.text = 'oops'
def broken_mark(_host):
raise RuntimeError('mark failed')
caplog.set_level(logging.DEBUG, logger="services.ollama_service")
with patch('services.ollama_service.resolve_ollama_host',
return_value='http://test:11434'), \
patch('services.ollama_service.mark_unhealthy', side_effect=broken_mark), \
patch('services.ollama_service.requests.post', return_value=fake_resp):
svc = PPTVisionService()
result = svc.check_image(fake_image)
assert result.success is False
assert 'HTTP 500' in (result.error or '')
assert 'mark_unhealthy failed' in caplog.text
def test_timeout_returns_failure(fake_image, monkeypatch):
monkeypatch.setenv('PPT_VISION_ENABLED', 'true')
from services.ppt_vision_service import PPTVisionService
import requests
with patch('services.ollama_service.resolve_ollama_host',
return_value='http://test:11434'), \
patch('services.ollama_service.mark_unhealthy'), \
patch('services.ollama_service.requests.post',
side_effect=requests.Timeout('60s')):
svc = PPTVisionService()
result = svc.check_image(fake_image)
assert result.success is False
assert 'timeout' in (result.error or '').lower()