2012-05-29 10 views
12

Lavoro con manipolazione audio, in genere utilizzando Matlab per la prototipazione e C++ per l'implementazione. Recentemente, ho letto su TDD. Ho esaminato alcuni esempi di base e sono abbastanza entusiasta del paradigma.Sviluppo basato su test per librerie di elaborazione del segnale

Al momento, utilizzo quello che considererei un approccio globale "assistito da test". Per questo, scrivo blocchi di elaborazione del segnale in C++, e quindi realizzo un semplice file mex Matlab che può interfacciarsi con le mie classi. Successivamente aggiungo funzionalità, controllando che i risultati corrispondano con uno script Matlab equivalente mentre procedo. Funziona bene, ma i test diventano obsoleti rapidamente con l'evolversi del sistema. Inoltre, sto testando l'intero sistema, non solo le unità.

Sarebbe bello utilizzare un framework TDD consolidato in cui posso avere una suite di test, ma non vedo come posso convalidare la funzionalità dei blocchi di elaborazione senza test altrettanto complessi come il codice in prova . Come potrei generare i segnali di riferimento in un test C++ per convalidare un blocco di elaborazione senza che il test sia una forma di profezia che si autoavvera?

Se qualcuno ha esperienza in questo settore, o può suggerire alcune metodologie che potrei leggere, sarebbe fantastico.

+1

+1 l'elaborazione del segnale di test non è facile; una nota però: test che i risultati di C++ sono gli stessi dei risultati matlab dimostra solo quel punto, ma non dimostra che i risultati siano corretti: sia matlab che C++ potrebbero dare lo stesso, errato risultato – stijn

risposta

3

penso che sia grande per applicare l'approccio TDD al Signal Processing (mi avrebbe salvato mesi di tempo se lo sapessi anni fa quando stavo facendo elaborazione del segnale da solo). Credo che la chiave è quello di abbattere il sistema in componenti di livello più basso che possono essere testati in modo indipendente, ad esempio:

  • FFT: segnali di test a frequenze conosciute: DC, Fs/Nfft, Fs/2 e diverse fasi etc Controllare i picchi e la fase come previsto, verificare la costante di normalizzazione come previsto
  • picco di prelievo: verificare di aver trovato i massimi/minimi corretti
  • Filtri: generare input a frequenze note e controllare l'ampiezza e la fase di uscita è come previsto

e 'difficile ottenere esattamente gli stessi risultati tra C++ e Matlab, quindi dovrete fornire limiti di errore su alcune delle prove. TDD è un ottimo modo per verificare non solo la correttezza del codice che hai ma è davvero utile quando provi diverse implementazioni. Ad esempio, se si desidera sostituire un'implementazione FFT con un'altra, esistono spesso lievi differenze con il modo in cui i dati vengono compressi o la costante di normalizzazione utilizzata. TDD ti darà un alto grado di confidenza con la nuova libreria correttamente integrata.

2

Faccio qualcosa di simile per il rilevamento dell'euristica e abbiamo un sacco e un sacco di file di acquisizione e un framework per poterli caricare e iniettarli per il test. Hai la possibilità di catturare i segnali di riferimento in un file e fare lo stesso?

Per quanto riguarda i miei 2 centesimi per TDD, è un ottimo modo per svilupparsi, ma come con la maggior parte dei paradigmi, non devi sempre seguirlo alla lettera, ci sono momenti in cui dovresti sapere come piegare un po 'le regole , in modo da non scrivere troppo codice/test throw-away. Ho letto di un approccio che diceva assolutamente che nessun codice dovrebbe essere scritto fino a quando non viene sviluppato un test, che a volte può essere troppo severo.

D'altra parte, mi piace sempre dire: "Se la sua non testato, i suoi rotto" :)

1

È corretto che il test sia complesso o più complesso del codice in fase di sviluppo.Se modifichi (aggiorna, refactor, bug fix) il codice e non il test, il test unitario ti avviserà che qualcosa è cambiato e deve essere rivisto (è stata una correzione di bug per la modalità A che si suppone cambi modalità B? Ecc.)

Inoltre, è possibile mantenere le API per i singoli componenti di calcolo e non solo per l'intero sistema end-to-end.

0

Ho appena iniziato a pensare a TDD nel contesto dell'elaborazione del segnale, quindi posso solo aggiungere un po 'alle risposte precedenti. Quello che ho fatto è sfruttare un po 'di sovrapposizione per testare le primitive. Ad esempio, testando un filtro IIR, ho verificato in modo indipendente gli elementi b0, b1 e b2 con unità e guadagni in scala, quindi ho verificato gli elementi a1 e a2 che seguivano facilmente decadimenti modellati. Il mio segnale di test era una combinazione di funzioni di rampa per il numeratore e le funzioni di impulso per il denominatore. So che è un esempio banale, ma il processo dovrebbe funzionare per molte operazioni lineari. I test dovrebbero anche esercitare le regioni instabili e mostrare che le uscite esplodono in modo appropriato.

In generale, mi aspetto che le risposte all'impulso facciano molto del lavoro per me, dal momento che molte situazioni le vedranno ridotte a funzioni trigonometriche, che possono essere calcolate indipendentemente. Allo stesso modo, se l'operazione ha un'espansione in serie, la funzione di test potrebbe eseguire l'espansione in un ordine rilevante e confrontarla con il blocco di elaborazione. Sarà lento, ma dovrebbe funzionare.