test: 100% coverage on core modules with headless CI support
Some checks failed
SonarQube Code Quality Scan / SonarQube Scan (push) Failing after 1m20s

- Fix dead exception handler in discord_rpc.py (unreachable DiscordNotFound)
- Replace QMediaPlayer=None stub with proper _StubQMediaPlayer in player.py
- Make AudioVisualizer color stops Qt-free (raw tuples instead of QColor)
- Add conftest QApplication creation check for headless CI detection
- Add test_gui_widgets.py _qt_available() guard for headless environments
- Add test_main.py (30 tests) for main.py entry point and env vars
- Add test_import_fallbacks.py (14 tests) for Qt import fallback paths
- Extend test_gui_helpers.py with _css, _get_thumbnail_nam, _cached_thumb_path tests
- Extend test_discord_rpc.py with direct _connect() test for DiscordNotFound
- Extend test_player_helpers.py with SearchWorker test-mode tests
- Ensure import fallback tests clean up sys.modules to avoid cross-test pollution

100% coverage achieved on: config.py, discord_rpc.py, main.py, music_db.py
This commit is contained in:
2026-06-04 20:53:00 +03:00
parent 5ce18506c1
commit dc3c735655
9 changed files with 897 additions and 30 deletions

View File

@@ -58,13 +58,62 @@ try:
except (ImportError, OSError):
_HAS_QT = False
QObject = object
QThread = type("QThread", (), {"start": lambda s: None,
"quit": lambda s: None,
"wait": lambda s, t=3000: True})
class _StubQThread:
"""Stub replacement for PySide6.QtCore.QThread."""
def start(self) -> None: pass
def quit(self) -> None: pass
def wait(self, timeout: int = 3000) -> bool: return True
QThread = _StubQThread
Signal = lambda *a: lambda f: f
Slot = lambda *a: lambda f: f
QUrl = None
QMediaPlayer = None
class _StubPlaybackState:
StoppedState = 0
PlayingState = 1
PausedState = 2
class _StubMediaStatus:
NoMedia = 0
LoadingMedia = 1
LoadedMedia = 2
StalledMedia = 3
BufferingMedia = 4
BufferedMedia = 5
EndOfMedia = 6
InvalidMedia = 7
class _StubError:
NoError = 0
ResourceError = 1
FormatError = 2
NetworkError = 3
AccessDeniedError = 4
ServiceMissingError = 5
class _StubQMediaPlayer:
PlaybackState = _StubPlaybackState
MediaStatus = _StubMediaStatus
Error = _StubError
def __init__(self):
self._playback_state = _StubPlaybackState.StoppedState
def setSource(self, url) -> None: pass
def play(self) -> None: pass
def pause(self) -> None: pass
def stop(self) -> None: pass
def setPosition(self, ms: int) -> None: pass
def position(self) -> int: return 0
def duration(self) -> int: return 0
def playbackState(self) -> int:
return self._playback_state
def audioOutput(self): return None
def setAudioOutput(self, output) -> None: pass
QMediaPlayer = _StubQMediaPlayer
QAudioOutput = None
log = logging.getLogger("tunetti.player")