Come posso scrivere test unitari per robot (e altri dispositivi meccanici)?


22

Sono un membro del club di robotica della mia scuola superiore e sono responsabile della programmazione del robot. Un suggerimento che continuo a sentire da vari adulti è che dovrei scrivere unit test per aiutare a convalidare il mio codice. La base di codice sta diventando un po 'grande, e sono d'accordo che i test unitari sarebbero davvero utili per aiutarmi a catturare i bug più velocemente.

Tuttavia, non sono del tutto sicuro di come avrei potuto farlo. Per quanto ne so, il test unitario viene eseguito prendendo una funzione (o un sottosistema del codice) e fornendo un set di input per assicurarsi che esca sempre con lo stesso output. Il codice che ho attualmente non fa alcun crunching di dati pesanti, ma piuttosto manipola direttamente i componenti hardware del robot. La maggior parte della complessità deriva dall'assicurarsi che l'elettronica sia sana, che il codice al momento corrisponda all'hardware reale sul robot, ecc. Spesso, posso solo vedere se c'è un problema caricando il codice sul robot stesso, e tentando di eseguirlo.

Per estensione, come possono essere scritti i test unitari per il codice destinato a far funzionare qualsiasi dispositivo meccanico? Mi sembra che si possano rilevare errori solo osservando fisicamente il funzionamento della macchina.

O sto solo fraintendendo come dovrebbero funzionare i test unitari?

( Se è importante, ecco il codice , è scritto in C ++ e sto partecipando a FRC )

Risposte:


21

Dovrai deridere il livello hardware per eseguire questo test. L'idea è che invece che il tuo codice parli con l'hardware reale, parli con una versione falsa dell'hardware che puoi controllare e quindi utilizzare per verificare che il codice funzioni correttamente.

Sfortunatamente ci sono alcuni problemi che devi superare:

  • Deridere le cose in lingue di livello relativamente basso è più difficile (e quindi molto più lavoro)
  • Deridere cose a livello hardware è più difficile (e quindi molto più lavoro)

Inoltre, la maggior parte del valore delle unità di test automatizzate deriva dalla capacità di eseguire i test in qualsiasi momento per rilevare i bug di regressione per lunghi periodi di tempo dopo aver scritto il codice originale. Con questo tipo di competizioni, il tuo codice non verrà utilizzato affatto dopo la fine del contest, quindi non otterrai davvero gran parte del valore dai test. E considerando quanto sia difficile aggiungere test al tuo caso particolare, potrebbe essere un uso migliore del tuo tempo fare semplicemente test manuali e concentrarti sulle funzionalità del concorso.


1
Bella risposta. Soprattutto il fatto che il codice non verrà utilizzato dopo la competizione e che il grande vantaggio dei test di unità automatizzati arriva ben dopo che i test sono stati scritti. Potresti considerare di automatizzare alcuni dei tuoi test nel caso in cui ti ritrovi a eseguire lo stesso test più e più volte; ma fino a quando ciò non accadrà, non ha molto senso.
Dawood dice di ripristinare Monica il

Non è necessario deridere l'hardware. Se il robot ha la registrazione, eseguire il programma di test e osservare i registri. Il test finale richiede l'osservazione "svoltare a sinistra" nel registro che dovrebbe corrispondere al robot che gira a sinistra. Sarà necessario scrivere un cablaggio di prova per deridere i dispositivi di input - agganciare il codice del dispositivo di input il più vicino possibile al livello hardware
mattnz

4
@DavidWallace Come piccolo spunto di riflessione, quando si utilizza TDD / BDD, i vantaggi del test unitario si verificano immediatamente. In primo luogo, consentendo il refactoring immediato del codice con fiducia, e in secondo luogo incoraggiando l'implementazione a limitarsi all'implementazione minima necessaria per soddisfare i test.
S.Robins,

4
@mattnz cattiva idea, e lo so per esperienza. E se il codice in prova fallisce molto e il robotarm si schianta contro il muro, rovinando un pezzo di hardware xxxx $ ???
stijn

2
@mattnz: i nostri robot sono circa 2 piedi per 3 piedi per 4 piedi e pesano circa 150 libbre. Il kit / registrazione costa 5 mila dollari ogni anno e di solito raccogliamo altri 5-10k per acquistare parti aggiuntive. Lo scenario peggiore probabilmente costerebbe oltre $ 10;)
Michael0x2a

10

Posso pensare a un paio di cose che dovrai considerare. Il primo è quello di rendere il livello di accesso hardware il più sottile possibile, anche se ciò significa creare un livello di tipo wrapper di base per esso. Questo ti offre un paio di vantaggi. Il primo è che ti consente di isolare i comportamenti specifici del tuo codice dall'accesso hardware stesso, il che significa che puoi testare tutto fino alla fine delle comunicazioni hardware senza dover accedere all'hardware stesso.

Ad esempio, se è necessario progettare un protocollo di segnalazione basato su I2C, è possibile verificare che il codice stia generando i segnali I2C corretti senza dover collegare l'hardware ai test.

Per le chiamate all'hardware reale, puoi verificare che si comportino correttamente deridendo il tuo livello hardware, ed è qui che mantenere uno strato hardware molto sottile paga davvero, perché puoi ridurre il tuo finto in modo da dover gestire solo le funzioni minime richieste per in realtà si rivolgono all'hardware, ma non è necessario testare i singoli segnali stessi, poiché tutta la segnalazione dovrebbe essere testabile a un livello superiore. Ciò significa che si utilizza la simulazione per verificare che vengano effettuate chiamate a metodi hardware specifici che causano l'invio dei segnali all'hardware. Se hai bisogno di eseguire il polling del tuo hardware, allora il tuo finto deve essere in grado di innescare eventi o metodi solo nel tuo codice, perché di nuovo, la tua segnalazione di ritorno dovrebbe essere gestita in un livello superiore.

Questo si adatta sostanzialmente a ciò che Oleksi ha detto nella sua risposta , in quanto di solito è più lavoro prendere in giro cose a livello hardware, tuttavia non è così difficile se si mantiene il livello minimo di codice minimo / chiamata che si può fare per hardware.

Quando si dispone di codice che supera tutti i test, sarà comunque necessario eseguire una serie di test manuali per essere sicuri di aver assorbito tutto correttamente nel livello hardware.

L'altra cosa che viene in mente a parte la derisione e la stratificazione, è usare una pratica di sviluppo test-first. In sostanza, codifichi i tuoi requisiti come criteri di test e basi la tua implementazione dai test. Ciò ti aiuterà a garantire di ridurre al minimo il codice di implementazione, garantendo al contempo che tutti i casi di test guidino i tuoi sforzi di sviluppo. Non sprecando troppo tempo su un altro codice potenzialmente non critico che potresti essere tentato di fare "solo perché", il test ti aiuta innanzitutto a rimanere concentrato e renderà più facile cambiare il codice durante il debug, così come l'uso dei tuoi test unitari e simulazioni. Il debug dei bug del software attraverso l'hardware è notoriamente complicato e risucchia grandi quantità di tempo che potresti trovare meglio speso per altre attività.


2

Posso dirti come lo fanno sui simulatori di volo

In primo luogo, otterrai solo metà della risposta se poni questa domanda solo ai programmatori, quindi dovresti probabilmente incrociarla su http://electronics.stackexchange.com mentre ci sei.

Non ho lavorato con i robot, ma ho passato 5 anni a fare hardware su simulatori di volo, così posso dirti come funziona la loro architettura.

Il livello hardware è stupido

Contiene un'interfaccia di base in cui è possibile regolare semplici valori di input / output e impostare breakpoint di interpolazione per segnali analogici. Quando si lavora con hardware "nuovo", tutto funzionerà come previsto con una calibrazione minima o nulla, ma nel tempo le parti subiranno un'usura meccanica e dovranno essere regolate.

La calibrazione è una tabella semplice che contiene un intervallo sezionato tra i valori min / max. Per misurare input su questi, viene generalmente utilizzato un servo (ad esempio un potenziometro lineare, trasduttore, accelerometri, ecc.). O nel caso della strumentazione, devi solo giudicare la precisione visivamente e regolarla fino alla calibrazione.

Il livello software è l'opposto

Tutto è complesso e interconnesso, quindi è importante isolare alcune variabili per testare la funzionalità. Non è necessario preoccuparsi di pensare a scenari perché è molto più semplice eseguire scenari realistici in cui è possibile raccogliere dati. Quando si eseguono i test, sostanzialmente si misurano i dati memorizzati rispetto all'output corrente.

Su un simulatore di volo questo è indicato come QTG (Guida al test di qualificazione). Fondamentalmente traccia i dati su una griglia 2D in cui una dimensione è il tempo e l'altra è l'output.

Che ci crediate o no, questa è l'essenza di come sviluppano i modelli. Un vero aereo è dotato di una tonnellata di sensori e volato in giro facendo scenari controllati. Poiché tutti i controlli possono essere guidati senza interazione umana, i test vengono eseguiti (ovvero la sim stessa) dal computer e i dati vengono confrontati.

Anche se la robotica viene creata su una scala molto diversa, i principi sono gli stessi. L'approccio tradizionale consiste nel recidere completamente i livelli hardware e software in modo che entrambi possano essere testati singolarmente. L'input hardware viene raccolto tramite servi e impostato tramite un'interfaccia indipendente. L'input del software può essere impostato / letto misurando e confrontando in modo indipendente la segnalazione che altrimenti andrebbe all'hardware e la stampa su dati "buoni" noti.

I test stessi non devono necessariamente essere complessi purché i risultati siano prevedibili, misurabili e riproducibili.


1

Come detto in precedenza, deridere e stub le parti hardware. Ad esempio, se si dispone di un'interfaccia per il robot, è possibile ereditare da tale interfaccia e quindi eseguirne semplici stub. Quindi è possibile verificare che l'implementazione dello stub sia stata chiamata come previsto. Se questo è previsto funzioni o parametri previsti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.