• Non ci sono risultati.

CAPITOLO 4

N/A
N/A
Protected

Academic year: 2021

Condividi "CAPITOLO 4"

Copied!
13
0
0

Testo completo

(1)

L’automatizzazione dei test

4.1. Introduzione

In questo capitolo saranno brevemente descritte le principali peculiarità del linguaggio Python, attraverso il quale sono stati realizzati i programmi per lo svolgimento dei test, ed i moduli che permettono l’automatizzazione delle prove.

Si premette che lo scopo di questo capitolo non è descrivere nel dettaglio tutte le possibilità offerte da Python e dall’impiego dei moduli, ma quello di fornire le nozioni necessarie per la comprensione di termini come “script” e “modulo” che saranno utilizzati in seguito e del modo con il quale è possibile rendere automatiche le prove. Per maggiori approfondimenti, si rimanda a [13-25].

4.2. Generalità sui linguaggi di programmazione

I linguaggi di programmazione si dividono in linguaggi di alto o basso livello. La differenza tra le due tipologie risiede nel fatto che i computer possono eseguire soltanto programmi scritti in linguaggio di basso livello, talvolta chiamati “linguaggi macchina” o “linguaggi assembly”. I programmi scritti in un linguaggio di alto livello devono necessariamente essere elaborati prima di poter essere eseguiti.

I vantaggi dei linguaggi di alto livello sono fondamentalmente due. In primo luogo, i programmi richiedono meno comandi di esecuzione e sono facilmente interpretabili. Il secondo vantaggio è che essi sono “portabili”, cioè possono essere eseguiti su diversi tipi di computer con poche o addirittura nessuna modifica. Al contrario, i programmi scritti in linguaggi di basso livello possono essere utilizzati solo su un tipo di computer e devono essere riscritti per essere eseguiti su un altro sistema. Oggi quasi tutti i programmi sono scritti in linguaggi di alto livello, mentre quelli di basso livello sono impiegati solo in poche applicazioni specializzate.

(2)

Attraverso due tipi di elaborazione, che sono l’interpretazione e la compilazione, i programmi di alto livello sono convertiti in programmi di basso livello. L’interprete alterna la lettura delle istruzioni e l’esecuzione dei comandi descritti dalle istruzioni: in questo modo il programma di alto livello è eseguito ed ogni riga di istruzioni è trasformata in un'azione.

Fig. 4.1: interpretazione

Lo scopo del compilatore è leggere il programma di alto livello (detto “codice sorgente”) e tradurlo completamente in un programma di basso livello (chiamato “codice oggetto” o “eseguibile”). Dopo la compilazione, il programma può essere eseguito senza la necessità di ulteriori compilazioni fino a quando il codice non viene modificato.

Fig. 4.2: compilazione

4.2.1. Il linguaggio Python

Python è un linguaggio interpretato di alto livello, poiché i suoi programmi sono eseguiti da un interprete. Questo interprete può essere impiegato in due modi differenti, “a linea di comando” o in modo “script”. Nel primo modo, i programmi Python sono scritti una riga alla volta: dopo avere digitato una riga di codice, alla pressione di invio essa è immediatamente analizzata dall’interprete, il quale elabora il risultato. Quando l’interprete può accettare comandi, è visualizzata sul display una riga che inizia con il prompt >>>. Nel modo “script”, è possibile

memorizzare il programma in un file (detto appunto script) ed utilizzare l’interprete per eseguire il contenuto del file. Per convenzione i file contenenti programmi Python hanno estensione .py.

4.2.1.1. I token

Per sintassi di un programma si intende le regole che riguardano la sua struttura. Un programma può essere eseguito da un qualunque linguaggio di programmazione solo se esso è sintatticamente corretto, altrimenti l'elaborazione fallisce ed è restituito un messaggio d'errore.

Le regole sintattiche possono essere divise in due categorie. La prima riguarda i token, ossia gli elementi di base del linguaggio, così come possono essere le parole in letteratura o i numeri

(3)

in matematica. La seconda categoria riguarda la struttura della dichiarazione, cioè il modo in cui i token sono disposti.

In Python sono presenti 28 token:

and continue else for import not raise assert def except from in or return

break del exec global is pass try class elif finally if lambda print while

4.2.1.2. L’indentazione

Una caratteristica fondamentale del linguaggio Python è l’indentazione, cioè il rientro dal margine sinistro: essa non è semplicemente un modo per rendere leggibile un programma, come avviene per molti altri linguaggi di programmazione, ma un requisito fondamentale che consente di suddividere il codice in blocchi logici.

Attraverso l’indentazione, non è necessario dichiarare la fine di funzioni, di iterazioni while

e for o di istruzioni condizionali if...else: considerando un ciclo while, quando l’indentazione

torna al livello della dichiarazione iniziale del ciclo, esso è ritenuto concluso.

Alcuni esempi, che mostrano anche la sintassi da utilizzare per queste istruzioni, sono:

if vettura == "M139":

lista_variabili_test = lista_variabili_m139

elif vettura == "F131Evo":

lista_variabili_test = lista_variabili_f131 elif vettura == "F141": lista_variabili_test = lista_variabili_f141 while i<len(istanze): lista_out[i] = istanze[i].Read() i = i+1

for i in range (len(excel)): lista_out[i] = []

lista_out[i].append(excel[i][0]) lista_out[i].append(excel[i][1])

(4)

def importa_indirizzi(lista_in,out_1): i = 0 while i<len(lista_in): lista_in[i][3].Value = out_1[i][1] lista_in[i][4].Value = out_1[i][2] lista_in[i][2].Value = out_1[i][0] i = i+1 4.2.1.3. Strutture di dati

Le tipologie di dati impiegati da Python sono tre: le liste, le tuple e i dizionari.

Una lista è una serie ordinata di valori, ciascuno dei quali è identificato da un indice. I valori che appartengono alla lista sono detti elementi. Gli elementi possono essere di qualsiasi tipo, numeri, stringhe, istanze (§ 4.2.1.6). Le liste sono oggetti mutabili, cioè gli elementi possono essere modificati. Esempi di liste sono:

lista_nmot = [1000 8000]

lista_variabili = ["nmot_w","rl_w","wped_w","wdkba_w"]

Le tuple sono simili alle liste, ma se ne discostano per il fatto che sono immutabili. Per creare una tupla, la sintassi da utilizzare è:

tupla_res = ("positivo", "negativo", 0, 1)

I dizionari sono insiemi non ordinati di coppie chiave-valore. La chiave è l’indice che viene utilizzato per cercare una voce ed a ciascuna voce è associato un valore. Le chiavi sono immutabili, mentre i valori possono essere modificati. Un esempio di dizionario è:

Eng2Ita = {'one': 'uno', 'two': 'due', 'three': 'tre'}

dove ‘one’, ‘two’ e ‘three’ sono le chiavi e le altre stringhe sono i valori ad esse associati.

4.2.1.4. Le eccezioni

Se un programma è interrotto a causa di un errore durante la sua esecuzione (errore runtime), si crea una eccezione. In questo caso l’interprete si arresta ed è visualizzato un messaggio di errore.

(5)

Alcuni esempi comuni di eccezioni sono: - divisione di un valore per zero:

>>> print 55/0

ZeroDivisionError: integer division or modulo by zero

- richiesta di un elemento della lista con un indice non presente:

>>> lista = [] >>> print lista[1]

IndexError: list index out of range

In tutti i casi il messaggio di errore è composto da due parti separate da due punti, che sono la categoria dell’errore (ad esempio ZeroDivisionError) e le specifiche.

Per evitare l’arresto del programma durante l’esecuzione e la visualizzazione del messaggio di errore, è possibile gestire l’eccezione con le istruzioni try ed except. L’istruzione try esegue

tutti i comandi presenti nel suo blocco e, se non si verificano eccezioni durante l’esecuzione, tutto il blocco corrispondente all’istruzione except viene saltato. Altrimenti, se si verificano

delle eccezioni, viene interrotto il blocco try ed eseguito quello except.

4.2.1.5. Moduli e funzioni

Per funzione si intende una sequenza di istruzioni che esegue una certa operazione, azione che è descritta in una definizione di funzione. La sintassi da utilizzare è:

def Nome( Lista dei parametri ): Istruzioni

Ogni volta che è creata una variabile locale all’interno di una funzione, essa esiste solo all’interno della funzione stessa e non può essere utilizzata all’esterno. Questo significa che, se fosse assegnato ad una variabile x un valore di 20 esternamente alla funzione e successivamente uno di 10 all’interno di essa, sarebbero create due distinte variabili aventi lo stesso nome, una con valore uguale a 10 e l’altra pari a 20. Il valore di x non sarebbe modificato dalla chiamata della funzione, a meno di non dichiarare la variabile x come globale. Ad esempio:

x = 20 def test_variabili(): x = 10 print x test_variabili() print x

Questo script restituisce in output prima 10 (dato dal comando print interno alla funzione

(6)

x = 20 def test_variabili(): global x x = 10 print x test_variabili() print x

restituisce per due volte 10, poiché la dichiarazione “global x“ ha imposto alla funzione

l’utilizzo della variabile esterna.

Nel linguaggio Python esistono una serie di funzioni già definite, come la funzione type, che restituisce il tipo, o formato, del valore di una variabile:

>>> type (4): <type 'int'>

dove ‘int’ sta ad indicare che il formato di 4 è intero.

E’ possibile utilizzare nuove funzioni definite dal programmatore. Per far ciò, occorre semplicemente memorizzarle in uno script e richiamare questo file. Lo script è detto “modulo”, anche se altro non è che un normale file .py. Prima di poter utilizzare le funzioni di un modulo, esso deve essere importato con l’istruzione:

import nome_modulo

Tutto ciò che è definito all’interno di un modulo, è considerato un “attributo del modulo”. Per richiamare una funzione, è necessario ricorrere alla cosiddetta “notazione punto”, ossia:

nome_modulo.nome_funzione()

Se fossero definite alcune costanti anziché funzioni all’interno del modulo, anche tali costanti sarebbero considerate attributi e sarebbe necessario ricorrere alla notazione punto. Per esempio, considerando il modulo math di Python:

>>> import math >>> math.pi

3.1415926535897931

(7)

4.2.1.6. Classi e metodi

Python è un linguaggio orientato agli oggetti: questo significa che è un linguaggio nel quale i dati e le operazioni che li manipolano possono essere organizzati in “classi” e “metodi”.

Una classe può essere creata attraverso l’istruzione class, mediante la quale l’utente può

definire un nuovo tipo di dato; il nome di questo nuovo tipo di dato è lo stesso che è stato assegnato alla classe. I membri che appartengono a tale classe sono detti “istanze del tipo” o “oggetti”. Per chiarire meglio questo concetto, definendo una classe nel seguente modo:

class Punto: pass

è creato un nuovo tipo di dato chiamato Punto. Definendo poi: P1 = Punto()

la variabile P1 diventa un oggetto, o istanza, appartenente alla classe Punto.

Su un oggetto possono essere definiti degli attributi:

P1.x = 3.0 P1.y = 4.0

In tal caso x ed y sono attributi di P1 e non vi è alcun conflitto tra due variabili chiamate x ed y e i due attributi dell’oggetto P1.

Quando una funzione è definita all’interno di una definizione di classe ed è invocata su istanze di quella classe, essa prende il nome di “metodo”. Definiamo nella classe Punto il

seguente metodo:

class Punto:

def stampa_punto(self):

return "( "+str(self.x)+" , "+str(self.y)+" )"

Quando il metodo è invocato sull’istanza, con l’istruzione P1.stampa_punto(), l’istanza stessa

(P1) è automaticamente assegnata al primo parametro. Per convenzione, infatti, il primo

(8)

4.3. Il controllo delle simulazioni

La possibilità offerta dai sistemi Hardware in the loop di svolgere simulazioni real-time, che permettono il monitoraggio di una unità di controllo motore, richiede la presenza sul PC di controllo di opportuni strumenti che consentano all’utente, in modo interattivo, di gestire l’intero processo e di esaminare il comportamento del modello.

Ciò è reso possibile da un apposito software (ControlDesk), con il quale è possibile realizzare interfacce grafiche (dette layout) contenenti strumenti virtuali. Questi strumenti possono essere utilizzati per modificare manualmente i valori dei parametri del modello (cioè quelle grandezze che non dipendono dalla simulazione, ma che l’utente può variare per influenzare le caratteristiche di un blocco Simulink) oppure visualizzare e registrare l’andamento delle variabili (i cui valori subiscono invece gli effetti della simulazione). Un esempio di layout è mostrato nella prossima figura.

Fig. 4.3: layout per il controllo delle simulazioni

La crescente complessità delle ECU e la presenza di numerosi loop di controllo al loro interno richiede una esecuzione automatica dei test, mentre un approccio basato su interfacce di questo tipo non ne permetterebbe una automatizzazione.

La realizzazione manuale di un test potrebbe essere impiegata per verificare e validare una specifica funzione del software della ECU, ad esempio quella che calcola, in funzione di alcune mappe, la posizione obiettivo che i variatori di fase devono raggiungere. Per controllare che tale funzione restituisca in output gli obiettivi fissati, si potrebbe impostare manualmente un punto di

(9)

funzionamento del motore ed andare a monitorare, attraverso INCA, i valori assunti da tutte le variabili contenute nella funzione. Considerando che in un software sono presenti centinaia di funzioni, sarebbe impensabile realizzare procedure automatiche capaci di controllare ciascuna funzione.

D’altra parte, eventuali modifiche delle calibrazioni tra una versione del software di controllo della centralina e la successiva hanno bisogno di una serie di test di regressione ripetibili ed automatici per evidenziare le differenze e permettere la delibera della nuova release software, così come necessitano di tali prove le analisi del comportamento delle funzioni diagnostiche in corrispondenza di guasti elettrici sulle linee di collegamento tra la ECU ed i vari sensori ed attuatori.

Utilizzando appositi moduli Python, è possibile realizzare un controllo remoto di tutto l’ambiente HIL, il che significa mettere in grado l’utente di svolgere test sistematici ed automatici mediante la programmazione di script.

4.3.1. I moduli per l’automatizzazione

I principali moduli impiegati saranno brevemente descritti, con lo scopo di far intuire che cosa accade con il loro utilizzo all’interno degli script realizzati. Come espresso all’inizio del capitolo, questa descrizione non vuole avere l’obiettivo di spiegare nel dettaglio la struttura di ciascuno di essi, le sue numerose sottoclassi ed i suoi metodi. A tale scopo si rimanda ai riferimenti indicati precedentemente.

La figura 4.4 mostra la struttura di alcuni moduli presenti, evidenziando per ognuno le principali classi.

(10)

4.3.1.1. Il modulo rtplib

Questo modulo consente l’accesso a tutte le variabili ed i parametri del simulatore, cosicché i loro valori possono essere letti istantaneamente, catturati nel tempo o scritti mediante Python. Tutte le variabili ed i parametri del modello Simulink possono essere richiamati.

m = rtplib.Appl(file_sdf,"DS1005","PPC")

keyon = m.Variable(sup+'state machines/ignition/Value')

pedal = m.Variable(sup+'Dyno controller/control_setpoints/Pedal_man/Value') keyon.Write(1)

act_pedal = pedal.Read()

Con il comando rtplib.Appl è creata una istanza del modello eseguito dalla scheda DS1005.

Le due righe successive creano le istanze di due variabili, lo stato “key-on” e la posizione del pedale. E’ poi impostata la condizione “key-on”, assegnando alla variabile il valore di 1 (keyon.Write(1)), ed è letta e memorizzata nella variabile act_pedal la posizione del pedale.

4.3.1.2. Il modulo asap3lib

Con asap3lib è possibile collegare il software di gestione del simulatore, ossia ControlDesk, ed il sistema di misura e calibrazione (INCA per le applicazioni Ferrari e Maserati), attraverso una porta seriale RS232 che utilizza il protocollo di comunicazione standard ASAM MCD 3MC. Così è possibile, direttamente con uno script, leggere tutte le variabili ed acquisire e calibrare mappe e parametri della ECU.

Fig. 4.5: schema di collegamento tra ControlDesk e la ECU

Nel seguente esempio, il modulo è impiegato per modificare i valori di una mappa (“SetLookUpTable”), di un parametro (“SetParameter”) e per leggere i valori di una lista di variabili (“GetOnlineValue”). interfaccia = asap3lib.asap3Interface() interfaccia.SelectLookUpTable(Lun,"KFRLMN") KFRLMN = interfaccia.SetLookUpTable(KFRLMN[0],1,1,KFRLMN[1],KFRLMN[2],1) interfaccia.SetParameter(Lun,"CWPWF",1) interfaccia.ParameterForValueAcquisition(Lun,1000,len(variabili),variabili) interfaccia.GetOnlineValue()

(11)

4.3.1.3. Il modulo dtslib

Il modulo dtslib consente di comunicare, mediante Python, con la linea K della ECU, permettendo di catturare, analizzare ed eventualmente cancellare i codici di errore immagazzinati dalla diagnostica di bordo della centralina.

Questo modulo accede al sistema DTS (“Diagnostic Tool Set”), il quale colloquia direttamente con la ECU attraverso una apposita interfaccia hardware, che provvede all’invio di richieste e all’interpretazione delle risposte.

Fig. 4.6: struttura del sistema DTS

ist_dts = dtslib.DiagProject(nome_progetto,path_progetto) ist_dts.SelectLocation("KWP2000G", -1, 3)

ist_dts.StartBusCommunication()

ist_dts.SelectRequest('startDiagnosticSession',16) ist_dts.SendRequest()

Queste istruzioni permettono di aprire un collegamento tra il Diagnostic Tool Set e la ECU, selezionando, con il comando ist_dts.SelectLocation("KWP2000G", -1, 3), il protocollo

KWP2000 ed inviando alla ECU la richiesta di iniziare una nuova sessione diagnostica con il comando SendRequest.

4.3.1.4. Il modulo iocilib

In questo modulo (acronimo di I/O Control Interface Library) sono presenti i comandi necessari per controllare la simulazione dei guasti elettrici, o failure. Questi comandi Python sono trasmessi dal PC alla scheda FIU DS749 attraverso un collegamento seriale RS232.

fiu = iocilib.IOCI("COM1").GetFIU("DS749") fiu.NameFIUPort(8,10,"Injector 1")

(12)

Con il primo comando è inizializzata la comunicazione con la scheda FIU. Il secondo rinomina il canale numero 10 della scheda 8 come “Injector 1”. Attraverso le ultime due istruzioni, è creata una failure di circuito aperto sull’iniettore 1. Il comando “SetLatched” imposta lo stato dei circuiti di comando dei relais della scheda FIU, mentre Update esegue l’azione sui relais.

4.3.1.5. Il modulo cdautomationlib

Questo modulo è impiegato per programmare interfacce (layout) e per il controllo delle caratteristiche di ControlDesk. E’ possibile, con uno script, creare un collegamento tra uno strumento presente in un layout e lo stesso file .py, aggiungere nuovi strumenti e gestirne le diverse funzionalità (variabili a seconda del tipo di strumento). Alcuni di questi strumenti sono riportati in figura 4.8.

Fig. 4.7: struttura del modulo cdautomationlib Fig. 4.8: strumenti virtuali ist_lay = cdautomationlib.Instrumentation().Layouts.Item(add_lay) ist_led = ist_lay.Instruments.Item("LED")

ist_led.Value = 0

Nel layout individuato dalla stringa add_lay è presente uno strumento denominato “LED”. Con le prime due righe sono create una istanza del layout ed una dello strumento. Con l’ultima viene settato a zero il valore dello strumento, che corrisponde (in base alle proprietà impostate) alla visualizzazione del led con colore rosso.

(13)

4.3.1.6. Il modulo matlablib

Attraverso matlablib, è possibile accedere a Matlab per scambiare dati tra questo programma e l’interprete di Python o richiamare funzioni di Matlab, memorizzate in file .m. Ad esempio:

ist_mat = matlablib.Matlab() ist_mat.Open() a = range(10) b = range(10,20) ist_mat.PutArray("x",a) ist_mat .PutArray("y",b)

ist_mat.Execute("plot(x,y,'b');grid on;hold on;")

Le prime due istruzioni consentono di aprire una applicazione Matlab, mentre con i comandi PutArray sono inseriti nelle variabili “x” ed “y” i valori di a e b. L’ultima istruzione crea un grafico che riporta l’andamento di b in funzione di a.

4.3.1.7. I moduli excellib e wordlib

Utilizzando questi moduli, è possibile creare e redigere documenti sia Word che Excel, oltre a poter importare dati da questi ultimi.

appl = excellib.Application() appl.Show() doc = appl.AddWorkbook() doc = appl.GetWorkbook(0) doc.InsertData("APPLICAZIONE","A1",0) doc.InsertData("SOFTWARE","A2",0) doc.InsertData("CALIBRAZIONE","A3",0)

Con le prime due righe ed i comandi AddWorkbook e GetWorkbook, è creato un documento Excel ed è selezionato uno dei fogli di lavoro. Con InsertData, sono inserite nelle celle A1, A2 ed A3 le stringhe indicate. Nel prossimo esempio è impiegato il modulo wordlib per creare un file Word. Il comando TypeText permette di inserire la stringa nel documento:

appl = wordlib.Application() appl.Show()

doc = appl.NewDocument() doc = appl.GetDocument(0)

Figura

Fig. 4.1: interpretazione
Fig. 4.3: layout per il controllo delle simulazioni
Fig. 4.5: schema di collegamento tra ControlDesk e la ECU
Fig. 4.6: struttura del sistema DTS
+2

Riferimenti

Documenti correlati

In effetti la ricerca di una chiave è in media velocissima come si vede dalla tabella, ma il caso pessimo, che qui si verifica se tutte le chiavi hanno lo stesso indirizzo

In effetti la ricerca di una chiave è in media velocissima come si vede dalla tabella, ma il caso pessimo, che qui si verifica se tutte le chiavi hanno lo stesso indirizzo

In questo caso, ponendo per MUSIC M = 6 (la relazione M &gt; p + 1 è quindi rispettata, essendo p il numero di esponenziali complessi del segnale, in questo caso 2) si ottengono

Interpretando x,y,z come coordinate si dica qual è la mutua posizione dei 3 piani rappresentati dalle equazioni del sistema al variare di k reale. In tal caso il sistema è

Durante i numerosi sopralluoghi effettuati sia in occasione dei rilievi della rete che durante alcuni eventi meteorici, oltre che dalla verifica della rete con il metodo

Teorema di integrabilit`a, teorema di equivalenza, propriet`a di ad- ditivit`a rispetto all’insieme di integrazione, teorema di Fubini, insiemi sem- plici e formule di

• processo padre e processo figlio condividono la stessa entry nella tabella di sistema dei file aperti, quindi ogni operazione di uno dei due processi sul file influenza

Alla fine della sperimentazione, i risultati positivi degli alunni hanno rivelato non solo una maggiore disinvoltura nella lingua straniera, ma anche la proposta