• Non ci sono risultati.

Collaudo e Collaudo e Correzione di Errori Correzione di Errori

N/A
N/A
Protected

Academic year: 2021

Condividi "Collaudo e Collaudo e Correzione di Errori Correzione di Errori"

Copied!
80
0
0

Testo completo

(1)

Collaudo e Collaudo e Correzione di Errori Correzione di Errori

C. Horstmann

C. Horstmann

Fondamenti di programmazione e Java 2

Fondamenti di programmazione e Java 2

3^ edizione Apogeo

3^ edizione Apogeo

trad. Nicola Fanizzi

trad. Nicola Fanizzi

corso di Programmazione, CdS: Informatica TPS

corso di Programmazione, CdS: Informatica TPS

Dip. di Informatica, Università degli studi di Bari

Dip. di Informatica, Università degli studi di Bari

(2)

2 2

Obiettivi Obiettivi

 Imparare ad eseguire il collaudo di unità Imparare ad eseguire il collaudo di unità

 Capire i principi della selezione e valutazione dei Capire i principi della selezione e valutazione dei casi di test

casi di test

 Imparare ad usare il logging Imparare ad usare il logging

 Prendere familiarità con l'udo di un debugger Prendere familiarità con l'udo di un debugger

 Imparare le strategie per un debugging efficace Imparare le strategie per un debugging efficace

(3)

3 3

Collaudo di Unità Collaudo di Unità

 Unico e più importante strumento per il collaudo Unico e più importante strumento per il collaudo

 Controlla un singolo metodo o un insieme di metodi Controlla un singolo metodo o un insieme di metodi cooperanti

cooperanti

 Non si testa il programma completo che si sta Non si testa il programma completo che si sta sviluppando, bensì le singole classi isolate

sviluppando, bensì le singole classi isolate

 Per ogni test, si fornisce una semplice classe detta Per ogni test, si fornisce una semplice classe detta test harness

test harness

 La classe La classe test harness test harness procura i parametri ai metodi procura i parametri ai metodi da collaudare

da collaudare

(4)

4 4

Esempio:

Esempio:

Impostare Classi Test Harness Impostare Classi Test Harness

 Usiamo un comune algoritmo per il calcolo della Usiamo un comune algoritmo per il calcolo della radice quadrata:

radice quadrata:

 Dare un valore x che potrebbe essere abbastanza vicino Dare un valore x che potrebbe essere abbastanza vicino alla radice quadrata desiderata (x = a va bene)

alla radice quadrata desiderata (x = a va bene)

 La vera radice sta tra x e a/x La vera radice sta tra x e a/x

 Considerare il punto medio (x + a/x) / 2 come migliore Considerare il punto medio (x + a/x) / 2 come migliore approssimazione

approssimazione

 Ripetere la procedura. Fermarsi quando due Ripetere la procedura. Fermarsi quando due

approssimazioni successive sono tra loro molto vicine

approssimazioni successive sono tra loro molto vicine

(5)

5 5

Esempio:

Esempio:

Impostare Classi Test Harness Impostare Classi Test Harness

 Il metodo converge rapidamente Il metodo converge rapidamente Radice quadrata di 100:

Radice quadrata di 100:

Guess #1: 50.5 Guess #1: 50.5 Guess #2:

Guess #2:

26.24009900990099 26.24009900990099 Guess #3:

Guess #3:

15.025530119986813 15.025530119986813 Guess #4:

Guess #4:

10.840434673026925 10.840434673026925 Guess #5:

Guess #5:

10.032578510960604 10.032578510960604 Guess #6:

Guess #6:

10.000052895642693 10.000052895642693 Guess #7:

Guess #7:

10.000000000139897

10.000000000139897

(6)

6 6

RootApproximator.java RootApproximator.java

01: /**

01: /**

02: Calcola approssimazioni della radice quadrata 02: Calcola approssimazioni della radice quadrata 03: di un numero usando l'algoritmo di Erone.

03: di un numero usando l'algoritmo di Erone.

04: */

04: */

05: public class RootApproximator 05: public class RootApproximator 06: {

06: {

07: /**

07: /**

08: Costruisce l'approssimazione della radice 08: Costruisce l'approssimazione della radice per un dato numero.

per un dato numero.

09: @param aNumber numero per il quale estrarre 09: @param aNumber numero per il quale estrarre la radice quadrata

la radice quadrata

10: (Precondizione: aNumber >= 0) 10: (Precondizione: aNumber >= 0) 11: */

11: */

12: public RootApproximator(double aNumber) 12: public RootApproximator(double aNumber) 13: {

13: {

14: a = aNumber;

14: a = aNumber;

15: xold = 1;

15: xold = 1;

16: xnew = a;

16: xnew = a;

(7)

7 7

RootApproximator.java RootApproximator.java

18: 18:

19: /**

19: /**

20: Calcola una approssimazione migliore della corrente.

20: Calcola una approssimazione migliore della corrente.

21: @return the next guess 21: @return the next guess 22: */

22: */

23: public double nextGuess() 23: public double nextGuess() 24: {

24: {

25: xold = xnew;

25: xold = xnew;

26: if (xold != 0) 26: if (xold != 0)

27: xnew = (xold + a / xold) / 2;

27: xnew = (xold + a / xold) / 2;

28: return xnew;

28: return xnew;

29: }

29: }

30: 30:

(8)

8 8

RootApproximator.java RootApproximator.java

31: /**

31: /**

32: Calcola la radice migliorando l'approssimazione 32: Calcola la radice migliorando l'approssimazione 33: finchè due successivi risultati risultano

33: finchè due successivi risultati risultano approssimativamente uguali.

approssimativamente uguali.

34: @return il valore della radice quadrata calcolato 34: @return il valore della radice quadrata calcolato 35: */

35: */

36: public double getRoot() 36: public double getRoot() 37: {

37: {

38: assert a >= 0;

38: assert a >= 0;

39: while (!Numeric.approxEqual(xnew, xold)) 39: while (!Numeric.approxEqual(xnew, xold)) 40: nextGuess();

40: nextGuess();

41: return xnew;

41: return xnew;

42: } 42: } 43:

43:

44: private double a; // il numero di cui si deve 44: private double a; // il numero di cui si deve calcolare la radice

calcolare la radice

45: private double xnew; // approssimazione corrente 45: private double xnew; // approssimazione corrente 46: private double xold; // approssimazione precedente 46: private double xold; // approssimazione precedente 47: }

47: }

(9)

9 9

Numeric.java Numeric.java

01: /**

01: /**

02: A class for useful numeric methods.

02: A class for useful numeric methods.

03: */

03: */

04: public class Numeric 04: public class Numeric 05: {

05: { 06: /**

06: /**

07: Tests whether two floating-point numbers are.

07: Tests whether two floating-point numbers are.

08: equal, except for a roundoff error 08: equal, except for a roundoff error 09: @param x a floating-point number 09: @param x a floating-point number 10: @param y a floating-point number 10: @param y a floating-point number

11: @return true if x and y are approximately equal 11: @return true if x and y are approximately equal 12: */

12: */

13: public static boolean approxEqual(double x, double y) 13: public static boolean approxEqual(double x, double y) 14: {

14: {

15: final double EPSILON = 1E-12;

15: final double EPSILON = 1E-12;

16: return Math.abs(x - y) <= EPSILON;

16: return Math.abs(x - y) <= EPSILON;

17: }

17: }

18: }

18: }

(10)

10 10

RootApproximatorTester RootApproximatorTester .java .java

01: import java.util.Scanner;

01: import java.util.Scanner;

02: 02:

03: /**

03: /**

04: This program prints ten approximations for a square 04: This program prints ten approximations for a square root.

root.

05: */

05: */

06: public class RootApproximatorTester 06: public class RootApproximatorTester 07: {

07: {

08: public static void main(String[] args) 08: public static void main(String[] args) 09: {

09: {

10: System.out.print("Enter a number: ");

10: System.out.print("Enter a number: ");

11: Scanner in = new Scanner(System.in);

11: Scanner in = new Scanner(System.in);

12: double x = in.nextDouble();

12: double x = in.nextDouble();

13: RootApproximator r = new RootApproximator(x);

13: RootApproximator r = new RootApproximator(x);

14: final int MAX_TRIES = 10;

14: final int MAX_TRIES = 10;

(11)

11 11

RootApproximatorTester RootApproximatorTester .java .java

15: for (int tries = 1; tries <= MAX_TRIES; tries++) 15: for (int tries = 1; tries <= MAX_TRIES; tries++) 16: {

16: {

17: double y = r.nextGuess();

17: double y = r.nextGuess();

18: System.out.println("Guess #" + tries + ": " + y);

18: System.out.println("Guess #" + tries + ": " + y);

19: } 19: }

20: System.out.println("Square root: " + r.getRoot());

20: System.out.println("Square root: " + r.getRoot());

21: }

21: }

22: }

22: }

(12)

12 12

Collaudare il Programma Collaudare il Programma

 Output Output

Enter a number: 100 Enter a number: 100 Guess #1: 50.5

Guess #1: 50.5

Guess #2: 26.24009900990099 Guess #2: 26.24009900990099 Guess #3: 15.025530119986813 Guess #3: 15.025530119986813 Guess #4: 10.840434673026925 Guess #4: 10.840434673026925 Guess #5: 10.032578510960604 Guess #5: 10.032578510960604 Guess #6: 10.000052895642693 Guess #6: 10.000052895642693 Guess #7: 10.000000000139897 Guess #7: 10.000000000139897 Guess #8: 10.0

Guess #8: 10.0

Guess #9: 10.0

Guess #9: 10.0

Guess #10: 10.0

Guess #10: 10.0

Square root: 10.0

Square root: 10.0

(13)

13 13

Collaudare il Programma Collaudare il Programma

 La classe La classe RootApproximator RootApproximator funziona funziona correttamente per tutti gli input ?

correttamente per tutti gli input ?

 Serve collaudarla su tanti altri valori Serve collaudarla su tanti altri valori

 Continuare a ri-collaudare con altri valori non è una Continuare a ri-collaudare con altri valori non è una buona idea; i collaudi non sono ripetibili

buona idea; i collaudi non sono ripetibili

 Se un problema viene corretto e si deve collaudare di Se un problema viene corretto e si deve collaudare di nuovo, si dovrebbero ricordare tutti gli input precedenti nuovo, si dovrebbero ricordare tutti gli input precedenti

Soluzione Soluzione : scrivere : scrivere test harness test harness che facilitano la che facilitano la ripetizione del collaudo delle unità

ripetizione del collaudo delle unità

(14)

14 14

Fornire l'Input per il Collaudo Fornire l'Input per il Collaudo

 Ci sono vari meccanismi per fornire casi di test Ci sono vari meccanismi per fornire casi di test

 Un meccanismo è quello di cablare (scrivere direttamente Un meccanismo è quello di cablare (scrivere direttamente nel codice) gli inputs di test nel test harness

nel codice) gli inputs di test nel test harness

Si esegue semplicemente il test harness ogni volta che si Si esegue semplicemente il test harness ogni volta che si corregge un bug nella classe collaudata

corregge un bug nella classe collaudata

Alternativa Alternativa : si tengono gli input di test su file appositi : si tengono gli input di test su file appositi

(15)

15 15

RootApproximatorHarness1 RootApproximatorHarness1

.java .java

01: /**

01: /**

02: Programma che calcola le radici quadrate di valori di 02: Programma che calcola le radici quadrate di valori di input selezionati

input selezionati 03: */

03: */

04: public class RootApproximatorHarness1 04: public class RootApproximatorHarness1 05: {

05: {

06: public static void main(String[] args) 06: public static void main(String[] args) 07: {

07: {

08: double[] testInputs = { 100, 4, 2, 1, 0.25, 0.01 };

08: double[] testInputs = { 100, 4, 2, 1, 0.25, 0.01 };

09: for (double x : testInputs) 09: for (double x : testInputs) 10: {

10: {

11: RootApproximator r = new RootApproximator(x);

11: RootApproximator r = new RootApproximator(x);

12: double y = r.getRoot();

12: double y = r.getRoot();

13: System.out.println("square root of " + x 13: System.out.println("square root of " + x 14: + " = " + y);

14: + " = " + y);

15: }

15: }

16: }

16: }

17: }

17: }

(16)

16 16

RootApproximatorHarness1 RootApproximatorHarness1

.java .java

 Output Output

square root of 100.0 = 10.0 square root of 100.0 = 10.0 square root of 4.0 = 2.0

square root of 4.0 = 2.0

square root of 2.0 = 1.414213562373095 square root of 2.0 = 1.414213562373095 square root of 1.0 = 1.0

square root of 1.0 = 1.0

square root of 0.25 = 0.5

square root of 0.25 = 0.5

square root of 0.01 = 0.1

square root of 0.01 = 0.1

(17)

17 17

Fornire l'Input per il Collaudo Fornire l'Input per il Collaudo

 Si possono anche generare casi di test in maniera Si possono anche generare casi di test in maniera automatica

automatica

 Se sono possibili pochi input Se sono possibili pochi input

allora basta far girare il test per intero allora basta far girare il test per intero

ciclando su un numero (rappresentativo) di casi

ciclando su un numero (rappresentativo) di casi

(18)

18 18

RootApproximatorHarness2 RootApproximatorHarness2

.java .java

01: /**

01: /**

02: Programma che calcola le radici quadrate 02: Programma che calcola le radici quadrate

03: di valori in input forniti attraverso un ciclo.

03: di valori in input forniti attraverso un ciclo.

04: */

04: */

05: public class RootApproximatorHarness2 05: public class RootApproximatorHarness2 06: {

06: {

07: public static void main(String[] args) 07: public static void main(String[] args) 08: {

08: {

09: final double MIN = 1;

09: final double MIN = 1;

10: final double MAX = 10;

10: final double MAX = 10;

11: final double INCREMENT = 0.5;

11: final double INCREMENT = 0.5;

12: for (double x = MIN; x <= MAX; x = x + INCREMENT) 12: for (double x = MIN; x <= MAX; x = x + INCREMENT) 13: {

13: {

14: RootApproximator r = new RootApproximator(x);

14: RootApproximator r = new RootApproximator(x);

15: double y = r.getRoot();

15: double y = r.getRoot();

16: System.out.println("square root of " + x 16: System.out.println("square root of " + x 17: + " = " + y);

17: + " = " + y);

18: }

18: }

19: }

19: }

20: }

20: }

(19)

19 19

RootApproximatorHarness2 RootApproximatorHarness2

.java .java

 Output Output

square root of 1.0 = 1.0 square root of 1.0 = 1.0

square root of 1.5 = 1.224744871391589 square root of 1.5 = 1.224744871391589 square root of 2.0 = 1.414213562373095 square root of 2.0 = 1.414213562373095 . . .

. . .

square root of 9.0 = 3.0 square root of 9.0 = 3.0

square root of 9.5 = 3.0822070014844885

square root of 9.5 = 3.0822070014844885

square root of 10.0 = 3.162277660168379

square root of 10.0 = 3.162277660168379

(20)

20 20

Fornire l'Input per il Collaudo Fornire l'Input per il Collaudo

 Test precedenti hanno ristreto il campo ad un limitato Test precedenti hanno ristreto il campo ad un limitato sotto-insieme di valori

sotto-insieme di valori

Alternativa Alternativa : generazione causale di casi di test : generazione causale di casi di test

(21)

21 21

RootApproximatorHarness3 RootApproximatorHarness3

.java .java

01: import java.util.Random;

01: import java.util.Random;

02: 02:

03: /**

03: /**

04: Il programma calcola la radice quadrata di numeri 04: Il programma calcola la radice quadrata di numeri casuali

casuali 05: */

05: */

06: public class RootApproximatorHarness3 06: public class RootApproximatorHarness3 07: {

07: {

08: public static void main(String[] args) 08: public static void main(String[] args) 09: {

09: {

10: final double SAMPLES = 100;

10: final double SAMPLES = 100;

11: Random generator = new Random();

11: Random generator = new Random();

12: for (int i = 1; i <= SAMPLES; i++) 12: for (int i = 1; i <= SAMPLES; i++) 13: {

13: {

14: // Genera un valore casuale di test

14: // Genera un valore casuale di test

15: 15:

(22)

22 22

RootApproximatorHarness3 RootApproximatorHarness3

.java .java

16: double x = 1000 * generator.nextDouble();

16: double x = 1000 * generator.nextDouble();

17: RootApproximator r = new RootApproximator(x);

17: RootApproximator r = new RootApproximator(x);

18: double y = r.getRoot();

18: double y = r.getRoot();

19: System.out.println("square root of " + x 19: System.out.println("square root of " + x 20: + " = " + y);

20: + " = " + y);

21: }

21: }

22: }

22: }

23: }

23: }

(23)

23 23

RootApproximatorHarness3 RootApproximatorHarness3

.java .java

 Output Output

square root of 810.4079626570873 = 28.467665212607223 square root of 810.4079626570873 = 28.467665212607223 square root of 480.50291114306344 = 21.9203766195534 square root of 480.50291114306344 = 21.9203766195534 square root of 643.5463246844379 = 25.36821485017103 square root of 643.5463246844379 = 25.36821485017103 square root of 506.5708496713842 = 22.507128863348704 square root of 506.5708496713842 = 22.507128863348704 square root of 539.6401504334708 = 23.230156057019308 square root of 539.6401504334708 = 23.230156057019308 square root of 795.0220214851004 = 28.196134867834285 square root of 795.0220214851004 = 28.196134867834285 . . .

. . .

(24)

24 24

Fornire l'Input per il Collaudo Fornire l'Input per il Collaudo

 Selezionare buoni casi di test è un'abilità nel Selezionare buoni casi di test è un'abilità nel debuggare i programmi

debuggare i programmi

 Testare tutte le caratteristiche dei metodi che si Testare tutte le caratteristiche dei metodi che si stanno collaudando

stanno collaudando

 Testare i casi tipici Testare i casi tipici

100, 1/4, 0.01, 2, 10E12, per 100, 1/4, 0.01, 2, 10E12, per

SquareRootApproximator SquareRootApproximator

 Testare i casi limite: Testare i casi limite:

casi che sono ai confini del dominio di input casi che sono ai confini del dominio di input

0 per

0 per SquareRootApproximator SquareRootApproximator

(25)

25 25

Fornire l'Input per il Collaudo Fornire l'Input per il Collaudo

 I programmatori spesso fanno errori trattando I programmatori spesso fanno errori trattando condizioni limite:

condizioni limite:

 divisione per zero, estrarre caratteri da stringhe vuote, e divisione per zero, estrarre caratteri da stringhe vuote, e accedere riferimenti nulli

accedere riferimenti nulli

 Racogliere casi di test negativi: gli input che ci si Racogliere casi di test negativi: gli input che ci si aspetta che il programma rigetti

aspetta che il programma rigetti

 Esempio: la radice di -2. Esempio: la radice di -2.

 Il test è superato se l'harness termina con Il test è superato se l'harness termina con l'asserzione del fallimento

l'asserzione del fallimento

(se il controllo delle asserzioni è abilitato)

(se il controllo delle asserzioni è abilitato)

(26)

26 26

Lettura di Input di test da File Lettura di Input di test da File

 Più elegante mettere i valori di test in un file Più elegante mettere i valori di test in un file

 Ridirezione dell'Input: Ridirezione dell'Input:

 Alcune IDE non supportano la ridirezione dell'input. Alcune IDE non supportano la ridirezione dell'input.

Allora si usa la shell (console con riga di comando) Allora si usa la shell (console con riga di comando)

 Ridirezione dell'output: Ridirezione dell'output:

java Program < data.txt java Program < data.txt

java Program > output.txt

java Program > output.txt

(27)

27 27

RootApproximatorHarness4 RootApproximatorHarness4

.java .java

01: import java.util.Scanner;

01: import java.util.Scanner;

02: 02:

03: /**

03: /**

04: Il programma calcola la radice quadrata di input 04: Il programma calcola la radice quadrata di input 05: forniti attraverso System.in.

05: forniti attraverso System.in.

06: */

06: */

07: public class RootApproximatorHarness4 07: public class RootApproximatorHarness4 08: {

08: {

09: public static void main(String[] args) 09: public static void main(String[] args) 10: {

10: {

11: Scanner in = new Scanner(System.in);

11: Scanner in = new Scanner(System.in);

12: boolean done = false;

12: boolean done = false;

13: while (in.hasNextDouble()) 13: while (in.hasNextDouble()) 14: {

14: {

15: double x = in.nextDouble();

15: double x = in.nextDouble();

16: RootApproximator r = new RootApproximator(x);

16: RootApproximator r = new RootApproximator(x);

17: double y = r.getRoot();

17: double y = r.getRoot();

18:

18:

19: System.out.println("square root of " + x 19: System.out.println("square root of " + x 20: + " = " + y);

20: + " = " + y);

(28)

28 28

Lettura di Input di test da File Lettura di Input di test da File

 File File test.in test.in : :

facendo girare il programma:

facendo girare il programma:

1 100 1 100 2 4 2 4 3 2 3 2 4 1 4 1

5 0.25 5 0.25 6 0.01 6 0.01

java RootApproximatorHarness4 < test.in > test.out

java RootApproximatorHarness4 < test.in > test.out

(29)

29 29

Lettura di Input di test da File Lettura di Input di test da File

 File File test.out test.out : :

1 square root of 100.0 = 10.0 1 square root of 100.0 = 10.0 2 square root of 4.0 = 2.0

2 square root of 4.0 = 2.0

3 square root of 2.0 = 1.414213562373095 3 square root of 2.0 = 1.414213562373095 4 square root of 1.0 = 1.0

4 square root of 1.0 = 1.0

5 square root of 0.25 = 0.5

5 square root of 0.25 = 0.5

6 square root of 0.01 = 0.1

6 square root of 0.01 = 0.1

(30)

30 30

Valutazione dei Casi di Test Valutazione dei Casi di Test

 Come saper se il l'output è corretto ? Come saper se il l'output è corretto ?

 Calcola re valori corretti a mano Calcola re valori corretti a mano

 es. per un programma di pagamenti, es. per un programma di pagamenti, calcolare le tasse manualmente

calcolare le tasse manualmente

 Fornire input di test per i quali si sa la risposta Fornire input di test per i quali si sa la risposta

 es. la radice di 4 è 2 e la radice di 100 è 10 es. la radice di 4 è 2 e la radice di 100 è 10

(31)

31 31

Valutazione dei Casi di Test Valutazione dei Casi di Test

 Verificare che i valori di output soddisfi cete proprietà Verificare che i valori di output soddisfi cete proprietà

 es. radice quadrata elevata al quadrato = valore originario es. radice quadrata elevata al quadrato = valore originario

 Usare un Oracolo: un metodo lento ma affidabile per Usare un Oracolo: un metodo lento ma affidabile per calcolare un risulktato per esigenze di collaudo

calcolare un risulktato per esigenze di collaudo

 es. usare es. usare Math.pow Math.pow per calcolare più lentamernte x per calcolare più lentamernte x

1/21/2

(equivalente alla radice quadrata di x)

(equivalente alla radice quadrata di x)

(32)

32 32

RootApproximatorHarness5 RootApproximatorHarness5

.java .java

01: import java.util.Random;

01: import java.util.Random;

02: 02:

03: /**

03: /**

04: Il programma verifica il calcolo dei valori della radice 04: Il programma verifica il calcolo dei valori della radice 05: quadrata controllando una proprietà delle radici quad.

05: quadrata controllando una proprietà delle radici quad.

06: */

06: */

07: public class RootApproximatorHarness5 07: public class RootApproximatorHarness5 08: {

08: {

09: public static void main(String[] args) 09: public static void main(String[] args) 10: {

10: {

11: final double SAMPLES = 100;

11: final double SAMPLES = 100;

12: int passcount = 0;

12: int passcount = 0;

13: int failcount = 0;

13: int failcount = 0;

14: Random generator = new Random();

14: Random generator = new Random();

15: for (int i = 1; i <= SAMPLES; i++) 15: for (int i = 1; i <= SAMPLES; i++) 16: {

16: {

(33)

33 33

RootApproximatorHarness5 RootApproximatorHarness5

.java .java

17: // Generare valori di test casuali 17: // Generare valori di test casuali 18: 18:

19: double x = 1000 * generator.nextDouble();

19: double x = 1000 * generator.nextDouble();

20: RootApproximator r = new RootApproximator(x);

20: RootApproximator r = new RootApproximator(x);

21: double y = r.getRoot();

21: double y = r.getRoot();

22: 22:

23: // controlla che il valore di test soddisfi la 23: // controlla che il valore di test soddisfi la proprietà del quadrato

proprietà del quadrato 24: 24:

25: if (Numeric.approxEqual(y * y, x)) 25: if (Numeric.approxEqual(y * y, x)) 26: {

26: {

27: System.out.print("Test passed: ");

27: System.out.print("Test passed: ");

28: passcount++;

28: passcount++;

29: } 29: } 30: else 30: else 31: { 31: {

32: System.out.print("Test failed: ");

32: System.out.print("Test failed: ");

33: failcount++;

33: failcount++;

34: }

34: }

(34)

34 34

RootApproximatorHarness5 RootApproximatorHarness5

.java .java

35: 35:

36: System.out.println("x = " + x 36: System.out.println("x = " + x

37: + ", root squared = " + y * y);

37: + ", root squared = " + y * y);

38: } 38: }

39: System.out.println("Pass: " + passcount);

39: System.out.println("Pass: " + passcount);

40: System.out.println("Fail: " + failcount);

40: System.out.println("Fail: " + failcount);

41: }

41: }

42: }

42: }

(35)

35 35

RootApproximatorHarness5 RootApproximatorHarness5

.java .java

 Output Output

Test passed: x = 913.6505141736327, root squared = 913.6505141736328 Test passed: x = 913.6505141736327, root squared = 913.6505141736328 Test passed: x = 810.4959723987972, root squared = 810.4959723987972 Test passed: x = 810.4959723987972, root squared = 810.4959723987972 Test passed: x = 503.84630929985883, root squared = 503.8463092998589 Test passed: x = 503.84630929985883, root squared = 503.8463092998589 Test passed: x = 115.4885096006315, root squared = 115.48850960063153 Test passed: x = 115.4885096006315, root squared = 115.48850960063153 Test passed: x = 384.973238438713, root squared = 384.973238438713 Test passed: x = 384.973238438713, root squared = 384.973238438713 . . .

. . .

Pass: 100 Pass: 100 Fail: 0 Fail: 0

(36)

36 36

RootApproximatorHarness6 RootApproximatorHarness6

.java .java

01: import java.util.Random;

01: import java.util.Random;

02: 02:

03: /**

03: /**

04: Il programma verifica il calcolo dei valori della radice 04: Il programma verifica il calcolo dei valori della radice 05: quadrata mediante un oracolo.

05: quadrata mediante un oracolo.

06: */

06: */

07: public class RootApproximatorHarness6 07: public class RootApproximatorHarness6 08: {

08: {

09: public static void main(String[] args) 09: public static void main(String[] args) 10: {

10: {

11: final double SAMPLES = 100;

11: final double SAMPLES = 100;

12: int passcount = 0;

12: int passcount = 0;

13: int failcount = 0;

13: int failcount = 0;

14: Random generator = new Random();

14: Random generator = new Random();

15: for (int i = 1; i <= SAMPLES; i++) 15: for (int i = 1; i <= SAMPLES; i++) 16: {

16: {

17: // Generare valori di test casuali

17: // Generare valori di test casuali

18: 18:

(37)

37 37

RootApproximatorHarness6 RootApproximatorHarness6

.java .java

19: double x = 1000 * generator.nextDouble();

19: double x = 1000 * generator.nextDouble();

20: RootApproximator r = new RootApproximator(x);

20: RootApproximator r = new RootApproximator(x);

21: double y = r.getRoot();

21: double y = r.getRoot();

22: 22:

23: double oracleValue = Math.pow(x, 0.5);

23: double oracleValue = Math.pow(x, 0.5);

24: 24:

25: // controllare che il valore di test eguagli 25: // controllare che il valore di test eguagli 26: 26: // approssimativamente quello dell'oracolo // approssimativamente quello dell'oracolo

27: if (Numeric.approxEqual(y, oracleValue)) 27: if (Numeric.approxEqual(y, oracleValue)) 28: {

28: {

29: System.out.print("Test passed: ");

29: System.out.print("Test passed: ");

30: passcount++;

30: passcount++;

31: } 31: } 32: else 32: else 33: { 33: {

34: System.out.print("Test failed: ");

34: System.out.print("Test failed: ");

35: failcount++;

35: failcount++;

36: }

36: }

(38)

38 38

RootApproximatorHarness6 RootApproximatorHarness6

.java .java

37: System.out.println("square root = " + y 37: System.out.println("square root = " + y 38: + ", oracle = " + oracleValue);

38: + ", oracle = " + oracleValue);

39: } 39: }

40: System.out.println("Pass: " + passcount);

40: System.out.println("Pass: " + passcount);

41: System.out.println("Fail: " + failcount);

41: System.out.println("Fail: " + failcount);

42: }

42: }

43: }

43: }

(39)

39 39

RootApproximatorHarness6 RootApproximatorHarness6

.java .java

 Output Output

Test passed: square root = 718.3849112194539, oracle = 718.3849112194538 Test passed: square root = 718.3849112194539, oracle = 718.3849112194538 Test passed: square root = 641.2739466673618, oracle = 641.2739466673619 Test passed: square root = 641.2739466673618, oracle = 641.2739466673619 Test passed: square root = 896.3559528159169, oracle = 896.3559528159169 Test passed: square root = 896.3559528159169, oracle = 896.3559528159169 Test passed: square root = 591.4264541724909, oracle = 591.4264541724909 Test passed: square root = 591.4264541724909, oracle = 591.4264541724909 Test passed: square root = 721.029957736384, oracle = 721.029957736384 Test passed: square root = 721.029957736384, oracle = 721.029957736384 . . .

. . .

Pass: 100 Pass: 100 Fail: 0 Fail: 0

(40)

40 40

Regression Testing Regression Testing

 Conservare i casi di test Conservare i casi di test

 Usare i test memorizzati in versioni successive Usare i test memorizzati in versioni successive

 Una suite di test è un insieme di test per il collaudo Una suite di test è un insieme di test per il collaudo ripetuto

ripetuto

 Ciclico = bug che è corretto ma riappare in Ciclico = bug che è corretto ma riappare in successive versioni

successive versioni

 Regression testing: ripetizione di test precedenti per Regression testing: ripetizione di test precedenti per assicurare che punti deboli noti in versioni precedenti assicurare che punti deboli noti in versioni precedenti

non appaiano in nuove versioni

non appaiano in nuove versioni

(41)

41 41

Copertura del Test Copertura del Test

Test a scatola nera Test a scatola nera : funzionalità di collaudo che non : funzionalità di collaudo che non prende in considerazione la struttura interna

prende in considerazione la struttura interna dell'implementazione.

dell'implementazione.

Test a scatola bianca Test a scatola bianca : prendere in considerazione : prendere in considerazione la struttura intern nel progettare i test

la struttura intern nel progettare i test

Copertura Copertura : misura di quante parti di un programma : misura di quante parti di un programma siano state collaudate

siano state collaudate

 Assicurarsi che ogni parte del programma sia Assicurarsi che ogni parte del programma sia interessata al meno una volta da un caso di test interessata al meno una volta da un caso di test

 es. assicurarsi di eseguire ogni diramazione in almeno un es. assicurarsi di eseguire ogni diramazione in almeno un

(42)

42 42

Copertura del Test Copertura del Test

Suggerimento Suggerimento : scrivere casi di test prima di finire di : scrivere casi di test prima di finire di scrivere il programma

scrivere il programma

→ dà l'idea di quello che dovrebbe fare

→ dà l'idea di quello che dovrebbe fare

 I programmi moderni possono essere ardui da I programmi moderni possono essere ardui da testare

testare

 Interfacce grafiche (uso del mouse) Interfacce grafiche (uso del mouse)

 Connessioni di rete (ritardi e cadute) Connessioni di rete (ritardi e cadute)

 Ci sono strumenti pr l'automazione del test in tali situazioni Ci sono strumenti pr l'automazione del test in tali situazioni

 Principi di base del regression testing della copertura Principi di base del regression testing della copertura completa sono ancora validi

completa sono ancora validi

(43)

43 43

Colludare Unità con JUnit Colludare Unità con JUnit

 http://junit.org http://junit.org

 Inglobato in IDE come BlueJ e Eclipse Inglobato in IDE come BlueJ e Eclipse

Filosofia Filosofia : ogni volta che si implementa una classe si : ogni volta che si implementa una classe si implementi anche una classe di test

implementi anche una classe di test

(44)

44 44

Colludare Unità con JUnit

Colludare Unità con JUnit

(45)

45 45

Trace di un Programma Trace di un Programma

 Messaggi che mostrano il flusso dell'esecuzione Messaggi che mostrano il flusso dell'esecuzione

if (status == SINGLE) if (status == SINGLE) { {

System.out.println("status is SINGLE");

System.out.println("status is SINGLE");

. . . . . . } }

. . .

. . .

(46)

46 46

Trace di un Programma Trace di un Programma

Svantaggio Svantaggio : serve rimuoverli a collaudo terminato, : serve rimuoverli a collaudo terminato, rimettere quando si trova un altro errore

rimettere quando si trova un altro errore

Soluzione Soluzione : usare la classe : usare la classe Logger Logger disabilitare i disabilitare i

messaggi di trace senza rimuoverli dal programma

messaggi di trace senza rimuoverli dal programma

(47)

47 47

Logging Logging

 I messaggi di log possono essere disattivati quando I messaggi di log possono essere disattivati quando il collaudo è completato

il collaudo è completato

 Si usa l'ggetto globale Si usa l'ggetto globale Logger.global Logger.global

 Registrare (log) un messaggio: Registrare (log) un messaggio:

Logger.global.info("status is SINGLE");

Logger.global.info("status is SINGLE");

(48)

48 48

Logging Logging

 Per default, i messaggi registrati sono stampati. Per default, i messaggi registrati sono stampati.

Li si disabilita con:

Li si disabilita con:

 Il logging può diventare assillante Il logging può diventare assillante (meglio nè troppo nè troppo poco) (meglio nè troppo nè troppo poco)

 Alcuni programmatori al logging preferiscono il Alcuni programmatori al logging preferiscono il debugging (prossima sezione)

debugging (prossima sezione)

Logger.global.setLevel(Level.OFF);

Logger.global.setLevel(Level.OFF);

(49)

49 49

Logging Logging

 Quando si traccia il flusso d'esecuzione, gli eventi Quando si traccia il flusso d'esecuzione, gli eventi più importanti sono l'entrata e l'uscita dai metodi più importanti sono l'entrata e l'uscita dai metodi

 All'inizio di un metodo, stampa dei parametri: All'inizio di un metodo, stampa dei parametri:

public TaxReturn(double anIncome, int aStatus) public TaxReturn(double anIncome, int aStatus) { {

Logger.global.info("Parameters: anIncome = " + anIncome Logger.global.info("Parameters: anIncome = " + anIncome + " aStatus = " + aStatus);

+ " aStatus = " + aStatus);

. . .

. . .

} }

(50)

50 50

Logging Logging

 Alla fine di un metodo, si stampa il valore di ritorno: Alla fine di un metodo, si stampa il valore di ritorno:

public double getTax() public double getTax() { {

. . . . . .

Logger.global.info("Return value = " + tax);

Logger.global.info("Return value = " + tax);

return tax;

return tax;

} }

(51)

51 51

Usare un Debugger Usare un Debugger

 Debugger = applicazione che fa girare un Debugger = applicazione che fa girare un

programma e ne analizza il comportamento in fase programma e ne analizza il comportamento in fase

d'esecuzione d'esecuzione

 Un debugger permette di fermare e far ripartire il Un debugger permette di fermare e far ripartire il proprio programma, osservare il contenuto delle proprio programma, osservare il contenuto delle

variabili ed eseguirlo passo passo variabili ed eseguirlo passo passo

 Più grandi sono i programmi, più sono difficili da Più grandi sono i programmi, più sono difficili da debuggare semplicemente mediante logging

debuggare semplicemente mediante logging

(52)

52 52

Usare un Debugger Usare un Debugger

 I debugger possono essere una parte della propria I debugger possono essere una parte della propria IDE (Eclipse, BlueJ) o programmi separati (JSwat) IDE (Eclipse, BlueJ) o programmi separati (JSwat)

 Tre concetti-chiave: Tre concetti-chiave:

 Breakpoint Breakpoint

 Esecuzione istruzione per istruzione Esecuzione istruzione per istruzione

 Osservazione delle variabili Osservazione delle variabili

(53)

53 53

Debugger Fermo Debugger Fermo ad un Breakpoint ad un Breakpoint

Figure 3:

(54)

54 54

Controllare le Variabili Controllare le Variabili

Figure 4:

(55)

55 55

Debugging Debugging

 L'esecuzione è sospesa ogni volta che si raggiunge L'esecuzione è sospesa ogni volta che si raggiunge breakpoint

breakpoint

 In un debugger, un programma gira a piena velocità In un debugger, un programma gira a piena velocità fino a quando non si raggiunge un breakpoint

fino a quando non si raggiunge un breakpoint

 Quando l'esecuzione si interrompe, si può: Quando l'esecuzione si interrompe, si può:

 Controllare il contenuto delle variabili Controllare il contenuto delle variabili

 Far eseguire il programma una riga alla volta Far eseguire il programma una riga alla volta

 oppure, continuare a farlo girare a piena velocità fino al oppure, continuare a farlo girare a piena velocità fino al prossimo breakpoint

prossimo breakpoint

(56)

56 56

Debugging Debugging

 Quando il programma termina, anche il debugger si Quando il programma termina, anche il debugger si ferma

ferma

 I breakpoint rimangono attivi fino alla loro rimozione I breakpoint rimangono attivi fino alla loro rimozione

 Due comandi per l'esecuzione di un singolo passo: Due comandi per l'esecuzione di un singolo passo:

 Step Over: salta le chiamate dei metodi Step Over: salta le chiamate dei metodi

 Step Into: entra nei metodi chiamati Step Into: entra nei metodi chiamati

(57)

57 57

Single-Step Example Single-Step Example

 Riga corrente: Riga corrente:

 Quando si saltano le chiamate di metodi, si passa Quando si saltano le chiamate di metodi, si passa alla riga successiva:

alla riga successiva:

String input = in.next();

String input = in.next();

Word w = new Word(input);

Word w = new Word(input);

int syllables = w.countSyllables();

int syllables = w.countSyllables();

System.out.println("Syllables in " + input + ": " + syllables);

System.out.println("Syllables in " + input + ": " + syllables);

String input = in.next();

String input = in.next();

Word w = new Word(input);

Word w = new Word(input);

int syllables = w.countSyllables();

int syllables = w.countSyllables();

System.out.println("Syllables in " + input + ": " + syllables);

System.out.println("Syllables in " + input + ": " + syllables);

(58)

58 58

Esempio di Single-Step Esempio di Single-Step

 Invece, entrando nelle chiamate, si passa alla prima Invece, entrando nelle chiamate, si passa alla prima riga di codice del metodo

riga di codice del metodo countSyllables countSyllables : :

public int countSyllables() public int countSyllables() { {

int count = 0; int count = 0;

int end = text.length() - 1;

int end = text.length() - 1;

. . .

. . .

} }

(59)

59 59

Sessione d'Esempio Sessione d'Esempio

di Debugging di Debugging

 Word Word : classe oper contare le silabe i una parola : classe oper contare le silabe i una parola

 Ogni grupo di vocali adiacenti (a, e, i, o, u, y) conta Ogni grupo di vocali adiacenti (a, e, i, o, u, y) conta come una sillaba

come una sillaba

 Però, una e a fine parola non conta come sillaba Però, una e a fine parola non conta come sillaba

 Se l'algoritmo restituisce 0, si incrementi ad 1 Se l'algoritmo restituisce 0, si incrementi ad 1

 Il costruttore rimuove i caratteri non-lettera all'inizio Il costruttore rimuove i caratteri non-lettera all'inizio ed alla fine

ed alla fine

(60)

60 60

Word.java Word.java

01: /**

01: /**

02: Questa classe descrive una parola in un documento.

02: Questa classe descrive una parola in un documento.

03: */

03: */

04: public class Word 04: public class Word 05: {

05: {

06: /**

06: /**

07: Construisce una parola togliendo i caratteri non 07: Construisce una parola togliendo i caratteri non 08: alfabetici ad inizio e fine, come la punteggiatura 08: alfabetici ad inizio e fine, come la punteggiatura 09: @param s la stringa in input

09: @param s la stringa in input 10: */

10: */

11: public Word(String s) 11: public Word(String s) 12: {

12: {

13: int i = 0;

13: int i = 0;

14: while (i < s.length() &&

14: while (i < s.length() &&

!Character.isLetter(s.charAt(i))) !Character.isLetter(s.charAt(i))) 15: i++;

15: i++;

16: int j = s.length() - 1;

16: int j = s.length() - 1;

17: while (j > i && !Character.isLetter(s.charAt(j))) 17: while (j > i && !Character.isLetter(s.charAt(j))) 18: j--;

18: j--;

19: text = s.substring(i, j);

19: text = s.substring(i, j);

20: }

20: }

(61)

61 61

Word.java Word.java

21: 21:

22: /**

22: /**

23: Restituisce il testo della parola rimossi 23: Restituisce il testo della parola rimossi 24: i caratteri non alfabetici iniziali e finali.

24: i caratteri non alfabetici iniziali e finali.

25: @return il testo della parola 25: @return il testo della parola 26: */

26: */

27: public String getText() 27: public String getText() 28: {

28: {

29: return text;

29: return text;

30: } 30: } 31: 31:

32: /**

32: /**

33: Counta le sillabe nella parola.

33: Counta le sillabe nella parola.

34: @return il conto delle sillabe 34: @return il conto delle sillabe 35: */

35: */

(62)

62 62

Word.java Word.java

36: public int countSyllables() 36: public int countSyllables() 37: {

37: {

38: int count = 0;

38: int count = 0;

39: int end = text.length() - 1;

39: int end = text.length() - 1;

40: if (end < 0) return 0;

40: if (end < 0) return 0;

// la stringa vuota non ha sillabe // la stringa vuota non ha sillabe 41: 41:

42: // Una e alla fine della parola non conta come vocale 42: // Una e alla fine della parola non conta come vocale 43: char ch = Character.toLowerCase(text.charAt(end));

43: char ch = Character.toLowerCase(text.charAt(end));

44: if (ch == 'e') end--;

44: if (ch == 'e') end--;

45: 45:

46: boolean insideVowelGroup = false;

46: boolean insideVowelGroup = false;

47: for (int i = 0; i <= end; i++) 47: for (int i = 0; i <= end; i++) 48: {

48: {

49: ch = Character.toLowerCase(text.charAt(i));

49: ch = Character.toLowerCase(text.charAt(i));

50: String vowels = "aeiouy";

50: String vowels = "aeiouy";

51: if (vowels.indexOf(ch) >= 0) 51: if (vowels.indexOf(ch) >= 0) 52: {

52: {

(63)

63 63

Word.java Word.java

53: // ch is a vowel 53: // ch is a vowel

54: if (!insideVowelGroup) 54: if (!insideVowelGroup) 55: {

55: {

56: // Inizio di un nuovo gruppo di vocali 56: // Inizio di un nuovo gruppo di vocali 57: count++;

57: count++;

58: insideVowelGroup = true;

58: insideVowelGroup = true;

59: } 59: } 60: } 60: } 61: } 61: } 62: 62:

63: // ogni parola ha minimo una sillaba 63: // ogni parola ha minimo una sillaba 64: if (count == 0)

64: if (count == 0) 65: count = 1;

65: count = 1;

66: 66:

67: return count;

67: return count;

68: } 68: } 69: 69:

70: private String text;

70: private String text;

71: }

71: }

(64)

64 64

WordTester.java WordTester.java

01: import java.util.Scanner;

01: import java.util.Scanner;

02: 02:

03: /**

03: /**

04: Questo programma testa il metodo countSyllables della 04: Questo programma testa il metodo countSyllables della classe Word

classe Word 05: */

05: */

06: public class WordTester 06: public class WordTester 07: {

07: {

08: public static void main(String[] args) 08: public static void main(String[] args) 09: {

09: {

10: Scanner in = new Scanner(System.in);

10: Scanner in = new Scanner(System.in);

11: 11:

12: System.out.println("Enter a sentence ending in a 12: System.out.println("Enter a sentence ending in a

// period."); // period.");

13: 13:

14: String input;

14: String input;

15: do

15: do

16: {

16: {

(65)

65 65

WordTester.java WordTester.java

17: input = in.next();

17: input = in.next();

18: Word w = new Word(input);

18: Word w = new Word(input);

19: int syllables = w.countSyllables();

19: int syllables = w.countSyllables();

20: System.out.println("Syllables in " + input + ": "

20: System.out.println("Syllables in " + input + ": "

21: + syllables);

21: + syllables);

22: } 22: }

23: while (!input.endsWith("."));

23: while (!input.endsWith("."));

24: }

24: }

25: }

25: }

(66)

66 66

Debuggare il Programma Debuggare il Programma

 output non corretto ( output non corretto ( buggy buggy ) ) (per l'input

(per l'input "hello yellow peach" "hello yellow peach" ): ):

 Porre un breakpoint sulla prima riga di Porre un breakpoint sulla prima riga di countSyllables

countSyllables della classe della classe Word Word

 Far partire il programma, fornire l'input. Far partire il programma, fornire l'input.

Il programma si ferma al breakpoint Il programma si ferma al breakpoint

 Il metodo controlla se la lettera finale è una ' Il metodo controlla se la lettera finale è una ' e e ' '

Syllables in hello: 1

Syllables in hello: 1

Syllables in yellow: 1

Syllables in yellow: 1

Syllables in peach: 1

Syllables in peach: 1

(67)

67 67

Debuggare il Programma Debuggare il Programma

Figure 5:

Debugging the CountSyllables Method

(68)

68 68

Debuggare il Programma Debuggare il Programma

 Controllare se funziona: Controllare se funziona:

eseguire fino alla riga dove si fa il controllo ed eseguire fino alla riga dove si fa il controllo ed

osservare la variabile

osservare la variabile ch ch

 Dovrebbe contenere la lettera finale ma contiene una Dovrebbe contenere la lettera finale ma contiene una

' ' l l ' '

(69)

69 69

Trovare Altri Problemi Trovare Altri Problemi

Figure 6:

(70)

70 70

Trovare Altri Problemi Trovare Altri Problemi

 end end viene posta a viene posta a 3 3 , non a , non a 4 4

text text contiene " contiene " hell hell ", non " ", non " hello hello " "

 No c'è da sorprendersi se No c'è da sorprendersi se countSyllables countSyllables restituisce

restituisce 1 1

 Il colpevole è altrove Il colpevole è altrove

 Non riesce a tornare in tempo Non riesce a tornare in tempo

 Far partire di nuovo ponendo un breakpoint nel Far partire di nuovo ponendo un breakpoint nel costruttore di

costruttore di Word Word

(71)

71 71

Debuggare Debuggare il Costruttore di

il Costruttore di Word Word

 Fornire l'input " Fornire l'input " hello hello " di nuovo " di nuovo

 Fermare subito dopo la fine del secondo loop nel Fermare subito dopo la fine del secondo loop nel costruttore

costruttore

 Controllare le variabili Controllare le variabili i i e e j j

 I valori sono I valori sono 0 0 e e 4 4

giusto dato che l'input consiste di lettere giusto dato che l'input consiste di lettere

 Perchè il testo viene impostato ad " Perchè il testo viene impostato ad " hell hell "? "?

(72)

72 72

Debuggare Debuggare il Costruttore di Word il Costruttore di Word

 Errore di fuori-di-uno: il secondo parametro della Errore di fuori-di-uno: il secondo parametro della sotto-stringa è la prima posizione da non includere sotto-stringa è la prima posizione da non includere

 text = substring(i, j); text = substring(i, j);

dovrebbe essere dovrebbe essere

text = substring(i, j+1);

text = substring(i, j+1);

(73)

73 73

Debuggare Debuggare il Costruttore di Word il Costruttore di Word

Figure 7:

Debugging the Word

(74)

74 74

Un Altro Errore Un Altro Errore

 Correggere l'errore Correggere l'errore

 Ricompilare Ricompilare

 Testare di nuovo: Testare di nuovo:

 Oh no, non va ancora bene Oh no, non va ancora bene

Syllables in hello: 1 Syllables in hello: 1

Syllables in yellow: 1 Syllables in yellow: 1

Syllables in peach: 1

Syllables in peach: 1

(75)

75 75

Un Altro Errore Un Altro Errore

 Far partire il debugger Far partire il debugger

 Cancellare i vecchi breakpoint e impostare un Cancellare i vecchi breakpoint e impostare un breakpoint sul metodo

breakpoint sul metodo countSyllables countSyllables

 Fornire l'input " Fornire l'input " hello hello " "

(76)

76 76

Debuggare (ancora) Debuggare (ancora) CountSyllables CountSyllables

 Fermare all'inizio di Fermare all'inizio di countSyllables countSyllables . . Quindi, eseguire il ciclo passo passo:

Quindi, eseguire il ciclo passo passo:

boolean insideVowelGroup = false;

boolean insideVowelGroup = false;

for (int i = 0; i <= end; i++) for (int i = 0; i <= end; i++) { {

ch = Character.toLowerCase(text.charAt(i));

ch = Character.toLowerCase(text.charAt(i));

if ("aeiouy".indexOf(ch) >= 0) if ("aeiouy".indexOf(ch) >= 0) { {

// ch è una vocale // ch è una vocale

if (!insideVowelGroup) if (!insideVowelGroup)

{ {

// Inizio di un nuovo gruppo di vocali // Inizio di un nuovo gruppo di vocali

count++;

count++;

insideVowelGroup = true;

insideVowelGroup = true;

} } } }

} }

Riferimenti

Documenti correlati

[r]

Come detto, da questo file dipende la configurazione relativa al test da effettuare, ecco che allora sarà da questo file che l’applicazione leggerà i valori da impostare relativi ai

 Può essere difficile individuare errore che dipendono dai moduli di più basso livello, perché verranno sviluppati per ultimi e gli stub passano dati non significativi ai

Il capitolo Neiye 内业 (quarto secolo a.e.v.) del Guanzi 管子 è una raccolta di versi sulla natura del dao e sui metodi di coltivazione interiore che collega le pratiche

Il trattamento delle acque reflue può avvalersi a livello tecnologico di di- verse soluzioni con il fine di purifi- care miscele a base acquosa conte- nenti sostanze organiche, sali

In ogni caso non può essere dichiarata conformità all’informazione contenuta in queste slide.. In ogni caso questa nota di copyright e il suo richiamo in calce ad ogni slide non devono

Fermo restando quanto sopra specificato, in particolare si dovrà controllare che le deformazioni sotto i carichi di prova, in termini di abbassamenti, rotazioni ecc, siano

Contestualmente alla denuncia prevista dall’articolo 65, il direttore dei lavori è tenuto a presentare presso lo sportello unico l’atto di nomina del collaudatore