best practice durante i test unitari per lo sviluppo integrato

43

Sto cercando alcune strategie di best practice per il codice di test unitario scritto per il sistema embedded. Per sistema incorporato, intendo codice come driver di dispositivo, gestori ISR, ecc., Roba che è abbastanza vicina al metallo.

La maggior parte dei test unitari non è possibile senza testarla sull'hardware con l'aiuto di un ICE. A volte, l'unità incorporata deve anche essere collegata ad altri stimoli come interruttori meccanici, motori passo-passo e lampadine. Questo di solito avviene in modo manuale, l'automazione sarebbe ottima ma difficile e costosa da raggiungere.

Aggiorna

Mi sono imbattuto in un framework di testing C che sembra avere un discreto successo nel test dei progetti embedded. Usa le idee dell'hardware di derisione. Dai un'occhiata a Unity , CMock , ed eventualmente Ceedling .

Aggiornamento 06Jul2016

È giunto su cmocka - sembra essere più attivamente lavorato.

    
posta tehnyit 29.08.2011 - 11:01
fonte

7 risposte

28

Vorrei astrarre le dipendenze dell'hardware al più presto possibile e costruire il sistema su cablaggi di emulazione / test del software, abilitando tutti i tipi di framework di test. Spesso il mio PC di sviluppo è stato utilizzato per testare fino al 95% o più del sistema completo. Il costo dell'overhead extra (un altro livello di astrazione) è stato facilmente riconquistato dal codice più pulito generato come risultato di tale astrazione.

Il testing delle parti veramente nude di un sistema embedded è solitamente un'applicazione separata (Unit test?) che martella il firmware ben oltre ciò che le applicazioni possono sperare di ottenere. L'automazione può essere eseguita a un costo, ma non è tipica.

A meno che non si abbia il budget per costruire un cablaggio hardware di test unitario, compreso l'ICE completo. Questo è assolutamente buono in quanto generalmente i test funzionali sono piccoli.

    
risposta data 29.08.2011 - 11:41
fonte
15

Uno strumento necessario da sviluppare è un iniettore di segnali. Il sistema embedded avrà un modo di interfacciarsi con un sistema host (in genere tramite una porta seriale riservata per il debug). Usalo per inviare i dati del test (l'opzione migliore è ascii e ascii, quindi è simulata facilmente anche dagli umani).

Non sono assolutamente d'accordo con questa parte della tua domanda: "l'automazione sarebbe ottima ma difficile e costosa da raggiungere".

Usando TeraTerm come un iniettore di segnale per porta seriale e scrivendo alcuni macro TeraTerm (ci vogliono circa 20 minuti), esiste un'enorme suite di test automatici che possono essere eseguiti su qualsiasi parte di un sistema embedded, indipendentemente dal livello driver, O / S, layer 4-5, ecc. TeraTerm: link

Se la porta seriale non è disponibile sul sistema incorporato, utilizzare uno strumento hardware per convertire i dati della porta USB / seriale in segnali digitali (anche economici e facili da ottenere). Mentre leggi questo, sto usando una scheda microcontroller da $ 30 (UBW: link ) per testare un sistema embedded per la produzione, iniettando stimolo tramite macro TeraTerm che viene inviato tramite USB / seriale al microcontrollore, che esegue firmware modificato che esercita input digitali e monitora le uscite digitali del sistema embedded target. Insieme a questo, abbiamo sviluppato uno script python (utilizza pyserial e pexpect) per automatizzare l'iniezione dei dati e la convalida dei dati. Nessuno di questi è difficile e nessuno di questi è costoso . Secondo la mia esperienza, i manager spendono cifre esorbitanti (come $ 30.000 test equipment) quando il team di test è inesperto e non riesce a concepire queste soluzioni facili - sfortunatamente, l'attrezzatura per uso generale di grandi dimensioni spesso non include i casi di test che colgono i tempi / il caso peggiore del sistema di destinazione. Quindi il metodo più economico è preferibile per la copertura del test. Credici o no.

    
risposta data 01.09.2011 - 01:28
fonte
5

Questo è un problema molto difficile.

Ho in realtà progettato un'unità di cablaggio per testare un sistema embedded, che consentirebbe di simulare eventi / interruzioni hardware e controllare i tempi dell'esecuzione (per garantire che copriamo tutti i possibili intrecci dovuti alla concorrenza), e ci sono voluti un team di programmatori più di 2 anni per implementarlo e metterlo in pratica. Quel progetto è uno sviluppo proprietario, ma un progetto simile (più semplice nella progettazione) è disponibile qui .

Quindi sì, l'automazione sarebbe grandiosa. Sì, è molto difficile e costoso da raggiungere. Sì, a volte devi farlo. Raramente però, nella mia esperienza nella maggior parte dei casi, è più veloce ed economico usare i motori passo passo e le lampadine e fare in modo che tutto funzioni manualmente.

    
risposta data 29.08.2011 - 11:12
fonte
3

I simulatori CPU integrati possono generalmente essere programmati per simulare anche l'hardware. Tutte le tecnologie di virtualizzazione diverse da Xen lo fanno. Ma è necessario scrivere codice che pretenda di avere alcuni registri su un indirizzo fisico o, su x86, un indirizzo sul bus I / O, e quindi è necessario rispondere a letture e scritture a questi indirizzi come se il software fosse un chip a cui è stato effettuato l'accesso ai registri di controllo e di stato.

Se vuoi farlo, ti suggerisco di modificare QEMU. Ma non sarebbe facile. Questo genere di cose viene generalmente fatto solo quando si progetta un chip personalizzato con un microcontrollore e alcuni altri core per l'I / O.

Il sistema di sviluppo venduto da ARM Holdings prevede questo ed è probabilmente più facile da gestire rispetto all'hacking su QEMU, ma è molto costoso.

Esistono diversi emulatori ARM Open Source che eseguono una singola subroutine, che a sua volta può chiamare altre subroutine, che è possibile utilizzare per eseguire il debug di ottimizzazione delle prestazioni delle subroutine che non dipendono dall'accesso all'hardware. Ho usato uno di questi con grande successo per ottimizzare un crittografo AES per ARM7TDMI.

Potresti scrivere una semplice unità test harness in C o C ++, collegare la classe o subroutine sotto test ad essa, quindi eseguirla nel simulatore.

Ho riflettuto su un problema simile per anni, su come testare il codice del kernel Linux o Mac OS X. Dovrebbe essere possibile, ma non l'ho mai provato. È possibile costruire un kernel completo piuttosto che testare il codice in isolamento, con il framework di test dell'unità collegato direttamente nel kernel. Spegnerebbero quindi i test unitari da qualche tipo di interfaccia esterna.

Forse sarebbe più produttivo utilizzare uno strumento di copertura del codice, quindi testare il firmware come un pacchetto completo attraverso la sua interfaccia esterna. Lo strumento di copertura troverebbe percorsi di codice che non erano ancora stati testati, quindi potresti aggiungere ulteriori test esterni nel tentativo di ottenere una copertura maggiore.

    
risposta data 29.08.2011 - 12:13
fonte
3

Modifica: la mia risposta è vicina a quella di mattnz, credo ...

Voglio mettere in relazione questo problema con gli altri, tutti i test che dipendono da qualcosa di esterno al tuo codice (come l'orologio di sistema, un filesystem persistente o un database, che contatta un servizio web esterno ...). Suggerisco la stessa politica per tutti loro, isola i due livelli in due strati di codice.

Test di una singola operazione esterna

Potresti voler testare fisicamente ogni operazione. Verifica che l'orologio di sistema dia l'ora corretta, verifica che un file ricordi effettivamente ciò che è stato scritto, verifica che un dispositivo riceva una singola operazione ...

Questi test:

  • dovrebbe essere il più semplice possibile: nessun algoritmo di sorta, nessuna condizione o ciclo
  • potrebbe essere dipendente dall'ordine e dipendente dalla macchina: quindi è necessario seguire un ordine rigoroso e ripetere su ogni hardware
  • sono per lo più stabili nel corso del tuo progetto, quindi non è necessario eseguirli spesso
  • quindi eseguirli manualmente è un'opzione; l'automazione è ancora migliore, se non eccessivamente complessa
  • Tieni presente che ciò che viene testato non è il tuo codice , è uno strumento di cui il tuo codice ha bisogno ... Quindi testare questo potrebbe essere facoltativo per te, potrebbe essere stato fatto da un altro team ...

Test della logica (codice, algoritmo) che unisce le operazioni esterne

Avendo uno strato di codice per rendere effettive le operazioni esterne, nascondendole dietro un'interfaccia che puoi facilmente prendere in giro, la tua logica non dipende più dai dispositivi fisici reali ...

Puoi testare semplicemente, come qualsiasi progetto normale, non ti trovi più in un codice difficile da testare incorporato .

    
risposta data 29.08.2011 - 19:08
fonte
3

Come per i TDD non incorporati, oggetti fittizi sono sicuramente tuoi amici.

Mantieni l'interfaccia con l'hardware sottostante pulito e semplice in modo che tutto ciò che si trova al di sopra del livello più basso possa essere deriso e ti sarà molto più facile crearlo - se si progetta l'applicazione incorporata tenendo a mente la testabilità, i test andranno sempre molto più agevolmente.

Inoltre, solo perché potresti non essere in grado di testare online fino a tardi nel progetto non significa che non dovresti preparare una suite di test on-line.

Questi dovrebbero (inizialmente) solo testare i bit che non possono essere testati offline. Certo, non è TDD (dal momento che stai creando i test in anticipo) ma il tuo sviluppo TDD offline dovrebbe darti un'idea di come deve essere l'interfaccia hardware e quindi quali test online devi eseguire.

Inoltre, se lo sviluppo online costa molto più dello sviluppo offline (come succede dove lavoro), potrebbe risparmiare molto tempo online con un insieme ben compreso di test da eseguire.

    
risposta data 31.08.2011 - 18:43
fonte
1

Nello sviluppo integrato fai spesso scansioni di confine per verificare che l'intera applicazione (incluso l'hardware) funzioni. Vedi anche JTAG per il debug del sistema.

Il test di routine software pure senza collegamento all'hardware può essere eseguito da un framework C standard di test come Check . Ma fai attenzione alle limitazioni della memoria (in particolare lo spazio di stack ecc. Su dispositivi di piccole dimensioni). Conosci i tuoi contratti! Puoi anche provare ad astrarre le routine software dall'hardware per ottenere una copertura di test più ampia, ma di solito è costosa in termini di prestazioni su dispositivi embedded come PIC PIC o AVR. Tuttavia, puoi prendere in giro le porte hardware per ottenere una copertura più ampia (e ovviamente puoi testare anche quella simulazione).

Puoi anche provare a usare gli emulatori per i chip o i simulatori di circuiti, ma questi tipi di strumenti sono costosi (specialmente in combinazione) e complicati.

    
risposta data 29.08.2011 - 11:14
fonte

Leggi altre domande sui tag