Table of Contents

Tests

LoopbackTranscriber.Tests usa xUnit 2.9.3 y se compila para net10.0-windows con WPF, porque los ViewModels dependen de tipos de WPF como DispatcherTimer. Los tests se ejecutan sin ventana, sin dispositivos de audio, sin modelos y sin procesos auxiliares: todo lo externo se sustituye por dobles.

Ejecutar

Comando Ejecuta
dotnet test LoopbackTranscriber.slnx -c Release Todos los tests.
dotnet test LoopbackTranscriber.slnx --filter Category=Unit Solo los unitarios.
dotnet test LoopbackTranscriber.slnx --filter Category=Integration Solo los de integración.
dotnet test LoopbackTranscriber.slnx --filter "FullyQualifiedName~RecordingWorkflow" Los de una clase, por su nombre.

En Visual Studio: Prueba → Explorador de pruebas → Ejecutar todas. Para agrupar por categoría, usa Agrupar por → Rasgos.

Organización

Carpeta o fichero Contenido
GlobalUsings.cs Espacios de nombres comunes y el alias TranscriptSegment.
Infrastructure\ Utilidades compartidas por los tests.
Fakes\ Dobles de las interfaces de la aplicación.
Models\ Un fichero por tipo de Models\.
Services\ Un fichero por servicio.
ViewModels\ Un fichero por ViewModel.

Cada clase de test se llama como la clase que prueba más Tests. Cada test tiene la forma Situacion_ResultadoEsperado, por ejemplo WhileRecording_No_ExitsAtOnce_KeepingTheAudioToProcessLater.

Categorías

Cada clase lleva un rasgo [Trait(TestCategory.Name, …)]:

Categoría Significado
Unit Lógica pura: sin disco, sin reloj y sin hilos. Tarda milisegundos.
Integration Usa una carpeta temporal, ficheros WAV reales o tiempos reales. Sigue siendo rápida y aislada.

Infraestructura

Tipo Para qué
TestEnvironment [ModuleInitializer] que se ejecuta antes de cualquier test. Crea %TEMP%\LoopbackTranscriber.Tests\<pid>, redirige AppLog.LogPath ahí para no escribir en el registro real y fija el idioma en español.
TempDirectory Carpeta temporal propia de cada test. Se borra al liberarla.
TestSettings AppSettings con todas las carpetas dentro de la temporal. CreateModelFiles crea modelos falsos de 1 byte para que la aplicación crea que están instalados.
WavFile Escribe y lee WAV de prueba: tonos, silencio, PCM o float, cabeceras rotas a propósito, duración y formato.
Eventually.Until(condición, motivo) Espera sin bloquear, comprobando la condición cada 10 ms, hasta 5 s por defecto. Si no se cumple, falla con el motivo.
CollectingProgress<T> IProgress<T> síncrono que guarda los valores.
InterfaceLanguage.Use(lang) Cambia el idioma de la interfaz y lo restaura al liberarse.
InterfaceLanguageTestGroup Colección de xUnit sin paralelismo. El idioma es estado global, así que los tests que lo cambian van en ella.
RecordingRig Monta el flujo de grabación completo con dobles: CaptureCoordinator, RecordingWorkflow, RecordingProcessor, RecordingViewModel, el almacén de fallidas y Teams como aplicación. Incluye ayudas como StartRecordingAsync, WhisperSays y LeaveOrphan.
ShellRig MainViewModel con todos sus hijos, sobre un RecordingRig.

Dobles

Doble Sustituye a Qué permite
FakeProcess IProcessCapture Escribir un WAV de prueba, retrasar el arranque (StartGate), contar arranques y fijar el pico.
FakeDevice IDeviceCapture Devolver pistas del dispositivo con el pico que se quiera.
FakeMic IMicCapture Simular un micrófono que arranca o no (StartSucceeds).
FakeWhisper IWhisperTranscriber Devolver segmentos por nombre de fichero, un idioma detectado, retener la transcripción (Gate) y registrar las peticiones.
FakeAudio IAudioPreparer Duración, mapas de actividad y de nivel, y fallos de la puerta de ruido.
FakeSettingsStore ISettingsStore Ajustes en memoria. Cada lectura devuelve una copia, como el servicio real. Cuenta las actualizaciones.
FakeDialogs IDialogService Respuestas fijas a Sí/No y Sí/No/Cancelar. Registra errores e información.
FakeTargetWatcher ITargetWatcher Marcar aplicaciones como abiertas o cerradas (SetRunning).
FakeCustomApps ICustomAppsService Añadir y quitar aplicaciones.
FakeSummarizer ISummarizer Resumen fijo y contador de llamadas.
FakeLiveHost IRecordingHost Grabación simulada para la ventana flotante y la bandeja: retrasar o hacer fallar el arranque y reaccionar a la parada (OnStop).
FakePageFactory IPageFactory Contar las páginas creadas.
FakeModelVerifier IModelVerifier Resultado o excepción de la verificación de modelos.

Pautas

  • Ningún test toca el estado real del usuario: ni settings.json, ni %LocalAppData%, ni el registro, ni procesos o dispositivos reales.
  • Los servicios que guardan en disco reciben su ruta por el constructor, como SettingsService(notices, settingsPath) o FailedRecordingStore(rootFolder). Los tests les pasan una ruta dentro de su TempDirectory.
  • Para esperar algo asíncrono, usa Eventually.Until, no Task.Delay con un tiempo fijo. Para controlar cuándo termina una operación, usa un TaskCompletionSource (los Gate de los dobles).
  • Los mensajes entre ViewModels se prueban con un WeakReferenceMessenger propio de cada test, no con WeakReferenceMessenger.Default.
  • Los textos esperados se obtienen con Strings.Instance.Get(...) o Format(...) en lugar de escribirlos a mano, salvo cuando lo que se prueba es la traducción.
  • No uses tu nombre real en los datos de prueba: los tests usan pgomur.