docs: OpenWiki-Dokumentation und Auto-Update-Workflow hinzufügen
Fügt generierte OpenWiki-Docs (Architektur, Domain, Betrieb, Tests, Workflows) sowie den GitHub-Actions-Workflow zur automatischen Aktualisierung hinzu. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
---
|
||||
type: TestingGuide
|
||||
title: Test-Leitfaden
|
||||
description: pytest-Setup für whisper-local. Plattformspezifische Tests via skipif, AsyncMock für asyncio-Callbacks, Mocking-Muster für sounddevice und faster-whisper.
|
||||
tags: [testing, pytest, asyncio, mocking, platform-specific]
|
||||
---
|
||||
|
||||
# Test-Leitfaden
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
uv run pytest # alle Tests
|
||||
uv run pytest -v # verbose
|
||||
uv run pytest tests/test_main.py # einzelne Datei
|
||||
```
|
||||
|
||||
Dev-Dependencies: `pytest>=8.0.0`, `pytest-asyncio>=0.24.0` (in `pyproject.toml` unter `[dependency-groups] dev`).
|
||||
|
||||
## Plattformspezifische Tests
|
||||
|
||||
Plattformabhängige Tests werden mit `@pytest.mark.skipif` übersprungen:
|
||||
|
||||
```python
|
||||
import sys
|
||||
import pytest
|
||||
|
||||
@pytest.mark.skipif(sys.platform != "linux", reason="nur Linux")
|
||||
def test_evdev_listener():
|
||||
...
|
||||
|
||||
@pytest.mark.skipif(sys.platform != "win32", reason="nur Windows")
|
||||
def test_pynput_listener():
|
||||
...
|
||||
```
|
||||
|
||||
Dieses Muster wird durchgehend angewendet — z.B. in `test_hotkey.py` (evdev vs. pynput), `test_media_mpris.py` (Linux), `test_media_smtc.py` (Windows).
|
||||
|
||||
## Async-Tests
|
||||
|
||||
Async-Tests verwenden `pytest-asyncio`:
|
||||
|
||||
```python
|
||||
@pytest.mark.asyncio
|
||||
async def test_on_press_starts_recording():
|
||||
app = App(config=Config())
|
||||
app.on_press = AsyncMock()
|
||||
await app.on_press()
|
||||
...
|
||||
```
|
||||
|
||||
Async-Callbacks (`on_press`, `on_release`, Mikrofon-Monitor-Callbacks) werden mit `unittest.mock.AsyncMock` gemockt.
|
||||
|
||||
## Mocking-Muster
|
||||
|
||||
### sounddevice
|
||||
|
||||
`Recorder` und `PollMonitor` verwenden `sounddevice`. In Tests wird `sd.InputStream` bzw. `sd.query_devices` gemockt:
|
||||
|
||||
```python
|
||||
@patch("whisper_local.recorder.sd.InputStream")
|
||||
def test_recorder_start(mock_stream):
|
||||
recorder = Recorder()
|
||||
recorder.start()
|
||||
mock_stream.assert_called_once()
|
||||
```
|
||||
|
||||
### faster-whisper
|
||||
|
||||
`Transcriber` wird mit einem gemockten `WhisperModel` instanziiert, um Modell-Downloads zu vermeiden:
|
||||
|
||||
```python
|
||||
def test_transcriber(mock_model):
|
||||
transcriber = Transcriber(model=mock_model, language="de")
|
||||
...
|
||||
```
|
||||
|
||||
Der `Transcriber` akzeptiert ein optionales `model`-Argument, das in Tests genutzt wird — ein expliziter Design-Entscheidung (Commit `3a58099`).
|
||||
|
||||
### Windows COM / winrt
|
||||
|
||||
`test_media_smtc.py` sichert `winrt`-Imports plattformabsichern ab. `test_main.py` mockt `create_monitor`, um COM-Abhängigkeiten zu umgehen.
|
||||
|
||||
## Test-Übersicht
|
||||
|
||||
| Test-Datei | Fokus | Plattform |
|
||||
|---|---|---|
|
||||
| `test_config.py` | Config laden/speichern, Defaults, TOML-Escaping | alle |
|
||||
| `test_recorder.py` | Recorder start/stop, min_duration-Filter | alle |
|
||||
| `test_transcriber.py` | Transcriber mit gemocktem Model | alle |
|
||||
| `test_hotkey.py` | Beide Backends, Key-Repeat-Unterdrückung | je `skipif` |
|
||||
| `test_inserter.py` | Wayland + Win32, Clipboard-Restaurierung | je `skipif` |
|
||||
| `test_media_factory.py` | Factory-Dispatch | alle |
|
||||
| `test_media_mpris.py` | MprisController, Circuit-Breaker | Linux |
|
||||
| `test_media_smtc.py` | SmtcController, Circuit-Breaker | Windows |
|
||||
| `test_microphone_monitor.py` | PollMonitor, Start-Check | alle |
|
||||
| `test_tray.py` | Tray-App, AppState, Icon, Settings | alle |
|
||||
| `test_download_progress.py` | Download-Dialog | alle |
|
||||
| `test_main.py` | App-Integration: Zyklus, Config-Reload, Mikrofon | alle |
|
||||
|
||||
## Wichtige Test-Konventionen
|
||||
|
||||
- **Mocks statt echter Hardware**: Kein echtes Mikrofon, keine echte Tastatur, kein D-Bus, kein SMTC in Tests.
|
||||
- **`create_monitor` mocken in `test_main.py`**: Verhindert COM-Initialisierung auf Nicht-Windows-Plattformen (Commit `1f8adc5`).
|
||||
- **Recorder vor Ersatz stoppen**: `test_main.py` stellt sicher, dass der Recorder gestoppt wird, bevor er durch Config-Reload ersetzt wird (Commit `1f8adc5`).
|
||||
Reference in New Issue
Block a user