EU-Utility/tests/conftest.py

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)