In che modo la copertura della filiale gestisce i loop?

3

So come funziona la copertura del codice in generale e so qual è la copertura della filiale. Ma non riesco a trovare una spiegazione su come la copertura delle filiali gestisce i loop.

Funziona come copertura del percorso? Dove un ciclo che viene eseguito 10 volte è un percorso diverso dallo stesso loop esatto che esegue 11 volte. O quei due casi sarebbero la stessa cosa nella copertura delle filiali?

    
posta AntonNiklasson 18.10.2015 - 14:00
fonte

1 risposta

7

La copertura delle filiali e la copertura dei percorsi sono concetti distinti.

Copertura filiali

Per misurare la copertura del ramo, cerchiamo tutti i punti in cui può avvenire la ramificazione. A ciascun punto di diramazione, entrambi i rami avrebbero dovuto essere eseguiti almeno una volta. Per esempio. in questo pseudo-codice:

A
if B:
  C
else:
  D
E
if F:
  G
I

abbiamo due punti di diramazione: if B e if F condizionali. Per ottenere una copertura completa delle filiali, ognuno di questi condizionali dovrebbe eseguire il ramo vero e falso, cioè entrambi B e F dovrebbero essere entrambi falsi e veri ciascuno. Un piano di test potrebbe essere:

Run 1:
  B = false
  F = false
  # executes A B _ D E F _ I
Run 2:
  B = true
  F = true
  # executes A B C _ E F G I

Come puoi vedere, la copertura completa delle filiali implica una copertura completa delle dichiarazioni.

Quando si ha a che fare con i loop, potrebbe essere utile "compilarlo" su una rappresentazione di livello più basso che ha solo condizionali e goto. Per esempio:.

// C99 code
A;
for (int i = 0; i < length; ++i)
  B;
C;

potrebbe essere inteso come

// Block 1
  A;
  int i = 0;

// Block 2
loop_start:
  if (!(i < length))
    goto loop_end;  // -> Block 4

// Block 3
  B;
  ++i;
  goto loop_start;

// Block 4
loop_end:
  C;

C'è solo un condizionale qui, nel blocco 2. Quindi, per ottenere una copertura completa, deve valutare una volta sia false che vere. Un piano di test potrebbe essere:

Run 1:
  length = 1
  # executes B1 B2 B3 B2 B4

Quindi la condizione del ciclo valuterà sia il vero sia il falso con questo piano di test. Ma chiaramente, questo non è un test soddisfacente: cosa succede quando il ciclo viene saltato del tutto (ad esempio con length = 0 )? Cosa succede se il corpo del loop modifica uno stato, funzionerà ancora con centinaia di iterazioni?

Copertura del percorso

Quando raggruppiamo il codice in un grafico del flusso di controllo, la copertura del percorso misura la frazione di percorsi presi da tutti i possibili percorsi. La copertura del percorso implica la copertura della filiale. Quando guardiamo al primo esempio, potremmo ottenere la copertura delle filiali con solo due casi di test. Ma per ottenere la copertura del percorso avremo bisogno di 4 casi: due per ogni percorso attraverso il primo condizionale, moltiplicato per due casi per il secondo condizionale:

Run 1:
  B = false
  F = false
  # executes A B _ D E F _ I
Run 2:
  B = false
  F = true
  # executes A B _ D E F G I
Run 3:
  B = true
  F = false
  # executes A B C _ E F _ I
Run 4:
  B = true
  F = true
  # executes A B C _ E F G I

Quando il nostro grafico del flusso di controllo include cicli, ci sono in generale infiniti percorsi possibili . In alcuni casi, il numero di iterazioni del ciclo è limitato da una costante e può essere testato, ma in generale non è questo il caso. Poiché la copertura completa del percorso è utile ma non raggiungibile, tendiamo a utilizzare altre metriche di copertura.

Quando scrivo test, tendo a ignorare la copertura completa del percorso per i loop (la copertura del percorso per i condizionali semplici è ancora molto utile). Tuttavia, più percorsi possono essere raggruppati in classi di equivalenza per i test - l'esecuzione del codice con 0, 1, 2 e "molte" iterazioni dovrebbe essere un'approssimazione decente. Un possibile piano di test:

Run 1:
  length = 0
  # executes B1 B2 B5
Run 2:
  length = 1
  # executes B1 B2 B3 B2 B5
Run 3:
  length = 2
  # executes B1 B2 B3 B2 B3 B2 B5
Run 4:
  length = 123
  # executes B1 B2 B3 B2 B3 ... B2 B3 B2 B5

Esistono anche metriche di codice formale che ci consentono di quantificare i test di loop, come Sequenza di codice lineare e salto . Tuttavia, non l'ho mai usato.

Test dei loop tramite ricorsione

Quando i loop sono espressi come ricorsione, il ciclo non è esplicito e quindi "nascosto" dalla copertura del percorso. È un problema? Tipo. Il ciclo è ancora presente nel grafico del flusso di controllo del programma nel suo complesso, ma non nel CFG della funzione ricorsiva.

Tuttavia, è molto più facile mostrare che il ciclo è corretto quando espresso in modo ricorsivo. Possiamo testare i casi di base e un caso non di base. Poiché ogni risultato non di base-base è costruito dai casi di base (che abbiamo già dimostrato essere corretto), allora si può presumere che la funzione nel suo complesso sia corretta. Questo è analogo alla tecnica proof by induction , tranne che i test non sono prove di correttezza, ma solo esempi di correttezza.

    
risposta data 18.10.2015 - 15:37
fonte

Leggi altre domande sui tag