300 lines
8.4 KiB
Python
300 lines
8.4 KiB
Python
"""
|
|
EU-Utility Test Configuration and Shared Fixtures
|
|
|
|
This module provides:
|
|
- Path configuration for test imports
|
|
- Shared fixtures for all test types
|
|
- Mock objects for testing without external dependencies
|
|
"""
|
|
|
|
import sys
|
|
import pytest
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
from typing import Generator
|
|
|
|
# Add project root to Python path
|
|
project_root = Path(__file__).parent.parent
|
|
if str(project_root) not in sys.path:
|
|
sys.path.insert(0, str(project_root))
|
|
|
|
|
|
# ==================== Session Fixtures ====================
|
|
|
|
@pytest.fixture(scope="session")
|
|
def project_root_path() -> Path:
|
|
"""Return the project root path."""
|
|
return Path(__file__).parent.parent
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def test_data_path(project_root_path) -> Path:
|
|
"""Return the test data directory path."""
|
|
return project_root_path / "tests" / "fixtures"
|
|
|
|
|
|
# ==================== Mock Fixtures ====================
|
|
|
|
@pytest.fixture
|
|
def mock_qt_app():
|
|
"""Create a mock Qt application for testing without GUI."""
|
|
mock_app = MagicMock()
|
|
mock_app.exec = MagicMock(return_value=0)
|
|
mock_app.quit = MagicMock()
|
|
return mock_app
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_overlay_window():
|
|
"""Create a mock overlay window for plugin testing."""
|
|
overlay = MagicMock()
|
|
overlay.show = MagicMock()
|
|
overlay.hide = MagicMock()
|
|
overlay.toggle = MagicMock()
|
|
overlay.add_widget = MagicMock()
|
|
overlay.remove_widget = MagicMock()
|
|
overlay.get_position = MagicMock(return_value=(100, 100))
|
|
overlay.set_position = MagicMock()
|
|
return overlay
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_plugin_config():
|
|
"""Return a sample plugin configuration."""
|
|
return {
|
|
"enabled": True,
|
|
"hotkey": "ctrl+shift+t",
|
|
"settings": {
|
|
"auto_start": False,
|
|
"update_interval": 5000
|
|
}
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def reset_singletons():
|
|
"""Reset all singleton instances after test."""
|
|
yield
|
|
# Reset singletons after test
|
|
from core.event_bus import reset_event_bus
|
|
from core.plugin_api import PluginAPI
|
|
from core.nexus_api import NexusAPI
|
|
from core.data_store import DataStore
|
|
|
|
reset_event_bus()
|
|
|
|
# Reset other singletons
|
|
NexusAPI._instance = None
|
|
DataStore._instance = None
|
|
PluginAPI._instance = None
|
|
|
|
|
|
# ==================== Event Bus Fixtures ====================
|
|
|
|
@pytest.fixture
|
|
def fresh_event_bus():
|
|
"""Create a fresh EventBus instance for testing."""
|
|
from core.event_bus import EventBus, reset_event_bus
|
|
|
|
# Reset first
|
|
reset_event_bus()
|
|
|
|
# Create fresh instance
|
|
bus = EventBus(max_history=100)
|
|
yield bus
|
|
|
|
# Cleanup
|
|
bus.shutdown()
|
|
reset_event_bus()
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_events():
|
|
"""Return sample events for testing."""
|
|
from core.event_bus import (
|
|
SkillGainEvent, LootEvent, DamageEvent,
|
|
GlobalEvent, ChatEvent, EconomyEvent
|
|
)
|
|
from datetime import datetime
|
|
|
|
return {
|
|
"skill_gain": SkillGainEvent(
|
|
skill_name="Rifle",
|
|
skill_value=25.5,
|
|
gain_amount=0.01,
|
|
source="test"
|
|
),
|
|
"loot": LootEvent(
|
|
mob_name="Daikiba",
|
|
items=[{"name": "Animal Oil", "value": 0.05}],
|
|
total_tt_value=0.05,
|
|
source="test"
|
|
),
|
|
"damage": DamageEvent(
|
|
damage_amount=150.0,
|
|
damage_type="impact",
|
|
is_critical=True,
|
|
target_name="Atrox",
|
|
attacker_name="Player",
|
|
is_outgoing=True,
|
|
source="test"
|
|
),
|
|
"global": GlobalEvent(
|
|
player_name="Player",
|
|
achievement_type="hof",
|
|
value=1000.0,
|
|
item_name="Uber Item",
|
|
source="test"
|
|
),
|
|
"chat": ChatEvent(
|
|
channel="main",
|
|
sender="OtherPlayer",
|
|
message="Hello!",
|
|
source="test"
|
|
),
|
|
"economy": EconomyEvent(
|
|
transaction_type="sale",
|
|
amount=100.0,
|
|
currency="PED",
|
|
description="Sold item",
|
|
source="test"
|
|
)
|
|
}
|
|
|
|
|
|
# ==================== API Fixtures ====================
|
|
|
|
@pytest.fixture
|
|
def mock_nexus_api():
|
|
"""Create a mock NexusAPI for testing."""
|
|
mock_api = MagicMock()
|
|
mock_api.search_items.return_value = [
|
|
MagicMock(id="item1", name="Test Item", type="weapon")
|
|
]
|
|
mock_api.search_mobs.return_value = [
|
|
MagicMock(id="mob1", name="Test Mob", type="creature")
|
|
]
|
|
mock_api.get_item_details.return_value = MagicMock(
|
|
id="item1",
|
|
name="Test Item",
|
|
tt_value=10.0
|
|
)
|
|
mock_api.get_market_data.return_value = MagicMock(
|
|
item_id="item1",
|
|
current_markup=110.0
|
|
)
|
|
mock_api.is_available.return_value = True
|
|
return mock_api
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_ocr_service():
|
|
"""Create a mock OCRService for testing."""
|
|
mock_ocr = MagicMock()
|
|
mock_ocr.is_available.return_value = True
|
|
mock_ocr.recognize.return_value = {
|
|
"text": "Test OCR Text",
|
|
"confidence": 0.95,
|
|
"results": []
|
|
}
|
|
mock_ocr.capture_screen.return_value = MagicMock()
|
|
return mock_ocr
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_log_reader():
|
|
"""Create a mock LogReader for testing."""
|
|
mock_reader = MagicMock()
|
|
mock_reader.is_available.return_value = True
|
|
mock_reader.read_lines.return_value = [
|
|
"2024-01-01 12:00:00 [System] Test log line",
|
|
"2024-01-01 12:00:01 [Combat] You hit for 50 damage"
|
|
]
|
|
mock_reader.get_stats.return_value = {
|
|
"lines_read": 100,
|
|
"events_parsed": 10
|
|
}
|
|
return mock_reader
|
|
|
|
|
|
# ==================== Data Fixtures ====================
|
|
|
|
@pytest.fixture
|
|
def temp_data_dir(tmp_path):
|
|
"""Create a temporary data directory for testing."""
|
|
data_dir = tmp_path / "test_data"
|
|
data_dir.mkdir()
|
|
return data_dir
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_log_lines():
|
|
"""Return sample log lines for testing."""
|
|
return [
|
|
"2024-01-01 12:00:00 [System] You entered the game",
|
|
"2024-01-01 12:00:05 [Skill] Rifle has improved by 0.01 points",
|
|
"2024-01-01 12:00:10 [Combat] You hit for 45 damage",
|
|
"2024-01-01 12:00:15 [Loot] You received Animal Oil x 1",
|
|
"2024-01-01 12:00:20 [Global] Player received something worth 1000 PED"
|
|
]
|
|
|
|
|
|
# ==================== Plugin Fixtures ====================
|
|
|
|
@pytest.fixture
|
|
def mock_plugin():
|
|
"""Create a mock plugin for testing."""
|
|
plugin = MagicMock()
|
|
plugin.name = "TestPlugin"
|
|
plugin.version = "1.0.0"
|
|
plugin.author = "Test Author"
|
|
plugin.description = "A test plugin"
|
|
plugin.enabled = True
|
|
plugin.initialize = MagicMock()
|
|
plugin.get_ui = MagicMock(return_value=MagicMock())
|
|
plugin.on_show = MagicMock()
|
|
plugin.on_hide = MagicMock()
|
|
plugin.shutdown = MagicMock()
|
|
return plugin
|
|
|
|
|
|
@pytest.fixture
|
|
def plugin_manager_with_mock():
|
|
"""Create a PluginManager with mocked dependencies."""
|
|
from core.plugin_manager import PluginManager
|
|
|
|
with patch('core.plugin_manager.Settings') as MockSettings:
|
|
mock_settings = MagicMock()
|
|
mock_settings.get.return_value = []
|
|
MockSettings.return_value = mock_settings
|
|
|
|
manager = PluginManager()
|
|
yield manager
|
|
|
|
|
|
# ==================== Pytest Configuration ====================
|
|
|
|
def pytest_configure(config):
|
|
"""Configure pytest with custom markers."""
|
|
config.addinivalue_line("markers", "unit: Unit tests for individual components")
|
|
config.addinivalue_line("markers", "integration: Integration tests")
|
|
config.addinivalue_line("markers", "ui: UI automation tests")
|
|
config.addinivalue_line("markers", "performance: Performance benchmarks")
|
|
config.addinivalue_line("markers", "slow: Slow tests")
|
|
config.addinivalue_line("markers", "requires_qt: Tests requiring PyQt6")
|
|
config.addinivalue_line("markers", "requires_network: Tests requiring network")
|
|
|
|
|
|
def pytest_collection_modifyitems(config, items):
|
|
"""Modify test collection to add markers based on test location."""
|
|
for item in items:
|
|
# Add markers based on test file location
|
|
if "unit" in str(item.fspath):
|
|
item.add_marker(pytest.mark.unit)
|
|
elif "integration" in str(item.fspath):
|
|
item.add_marker(pytest.mark.integration)
|
|
elif "ui" in str(item.fspath):
|
|
item.add_marker(pytest.mark.ui)
|
|
elif "performance" in str(item.fspath):
|
|
item.add_marker(pytest.mark.performance)
|