36
Chapter 10 Chapter 10 Testing and Testing and Debugging Debugging

Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Embed Size (px)

Citation preview

Page 1: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Chapter 10Chapter 10

Testing and Debugging Testing and Debugging

Page 2: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Chapter GoalsChapter Goals

►To learn how To learn how to carry out unit teststo carry out unit tests►To understand the To understand the principles of principles of

test case selection and evaluation test case selection and evaluation ►To learn how To learn how to use logging to use logging ►To become To become familiar with the familiar with the

debuggerdebugger ►To learn To learn strategies for effective strategies for effective

debuggingdebugging

Page 3: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

The First BugThe First Bug

Page 4: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Unit TestUnit Test

Test classes in isolation, outside Test classes in isolation, outside the program in which they are the program in which they are used used

Test one class at a timeTest one class at a time Supply test inputs through Supply test inputs through test test

harnessharness Test harness = program that Test harness = program that

feeds test inputs to a class feeds test inputs to a class

Page 5: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Root ApproximatorRoot Approximator

► Example program to illustrate testingExample program to illustrate testing: : square root approximator Algorithm square root approximator Algorithm

known to the ancient Greeks (Heron) known to the ancient Greeks (Heron) ► Task:Task: to compute the square root of to compute the square root of aa ► Given:Given: a guess a guess x x (we start with (we start with x=ax=a) )

The actual square root lies between The actual square root lies between a/x a/x and and xx

Page 6: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

► Take midpoint (Take midpoint (x x + + aa//xx) / 2 as a better guess ) / 2 as a better guess Method converges rapidly. Method converges rapidly.

► Square root of 100:Square root of 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.0Guess #8: 10.0All the other guesses from this point on, return the All the other guesses from this point on, return the same valuesame value

Page 7: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

File RootApproximator.javaFile RootApproximator.java11 /** /** 22 Computes approximations to the square root Computes approximations to the square root 33 of a number, using Heron's algorithm of a number, using Heron's algorithm 44 */ */ 55 public class RootApproximator public class RootApproximator 66 { {77 /** /** 88 Constructs a root approximator for a given number Constructs a root approximator for a given number 99 @param aNumber the number from which to extract the square root @param aNumber the number from which to extract the square root 1010 (Precondition: aNumber >= 0) (Precondition: aNumber >= 0) 1111 */ */ 1212 public RootApproximator(double aNumber) public RootApproximator(double aNumber) 1313 { { a = aNumber; a = aNumber; 15 15 xold = 1; xold = 1; 1616 xnew = a; xnew = a; 1717 } }

Page 8: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

1818

1919 /** /**

2020 Compute a better guess from the current guess. Compute a better guess from the current guess.

2121 @return the next guess @return the next guess

2222 */ */

2323 public double nextGuess() public double nextGuess()

2424 { { xold = xnew; xold = xnew;

2626 if (xold != 0) if (xold != 0)

2727 xnew = (xold + a / xold) / 2; xnew = (xold + a / xold) / 2;

2828 return xnew; return xnew;

2929 } }

3030

Page 9: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

3131 /** /**

3232 Compute the root by repeatedly improving Compute the root by repeatedly improving

3333 the current guess until two successive guesses are the current guess until two successive guesses are approximately equal. approximately equal.

3434 @return the computed value for the square root @return the computed value for the square root 3535 */ */ 3636 public double getRoot() public double getRoot() 3737 { { 3838 while (!Numeric.approxEqual(xnew, xold)) while (!Numeric.approxEqual(xnew, xold)) 3939 nextGuess(); nextGuess(); 4040 return xnew; return xnew; 4141 } } 42424343 private double a; // the number whose square root is private double a; // the number whose square root is

computed computed 4444 private double xnew; // the current guess private double xnew; // the current guess 4545 private double xold; // the old guess private double xold; // the old guess 4646 } }

Page 10: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

File File RootApproximatorTest.javaRootApproximatorTest.java

11 import javax.swing.JOptionPane; import javax.swing.JOptionPane; 22 /** /** This program prints ten approximations for a square rootThis program prints ten approximations for a square root.. 33 */ */ 44 public class RootApproximatorTest public class RootApproximatorTest 55 { { 66 public static void main(String[] args) public static void main(String[] args) 77 { { 88 String input = JOptionPane.showInputDialog("Enter a number"); String input = JOptionPane.showInputDialog("Enter a number"); 99 double x = Double.parseDouble(input); double x = Double.parseDouble(input); 1010 RootApproximator r = new RootApproximator(x); RootApproximator r = new RootApproximator(x); 1111 final int MAX_TRIES = 10; final int MAX_TRIES = 10; 1212 for (int tries = 1; tries <= MAX_TRIES; tries++) for (int tries = 1; tries <= MAX_TRIES; tries++) 1313 { double y = r.nextGuess(); { double y = r.nextGuess(); 1414 System.out.println("Guess #" + tries + ": " + y); System.out.println("Guess #" + tries + ": " + y); 1515 } } 1616 System.exit(0); System.exit(0); 1717 } }1818 } }

Page 11: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

File RootApproximatorTest2File RootApproximatorTest211 import javax.swing.JOptionPane; import javax.swing.JOptionPane; 22 /** /** This program computes square roots of user-supplied inputs. This program computes square roots of user-supplied inputs. 33 */ */ 44 public class RootApproximatorTest2 public class RootApproximatorTest2 55 { public static void main(String[] args) { public static void main(String[] args) 66 { { 77 boolean done = false; boolean done = false; 88 while (!done) while (!done) 99 { String input = JOptionPane.showInputDialog("Enter a number, C to quit"); { String input = JOptionPane.showInputDialog("Enter a number, C to quit"); 1010 if (input == null) if (input == null) 1212 done = true; done = true; 1313 else else 1414 { { double x = Double.parseDouble(input); double x = Double.parseDouble(input); 1616 RootApproximator r = new RootApproximator(x); RootApproximator r = new RootApproximator(x); 17 17 double y = r.getRoot(); double y = r.getRoot(); 1818 System.out.println("square root of " + x + " = " + y); System.out.println("square root of " + x + " = " + y); 2020 } } 2121 } } 2222 System.exit(0); System.exit(0); 2323 } } 2424 } }

Page 12: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Sources of Test DataSources of Test Data

►Provided by humansProvided by humansRootApproximatorTest2RootApproximatorTest2

►Computer-generated sequenceComputer-generated sequenceRootApproximatorTest3 RootApproximatorTest3

►Random sequenceRandom sequenceRootApproximatorTest4 RootApproximatorTest4

Page 13: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

File File RootApproximatorTest3.javaRootApproximatorTest3.java11 /** /** This program computes square roots of input values This program computes square roots of input values

22 computer generated by a loop. computer generated by a loop. */ */

33 public class RootApproximatorTest3 public class RootApproximatorTest3

44 { public static void main(String[] args) { public static void main(String[] args)

55 { {

66 final double MIN = 1;final double MIN = 1;

77 final double MAX = 10; final double MAX = 10;

88 final double INCREMENT = 0.5; final double INCREMENT = 0.5;

99 for (double x = MIN; x <= MAX; x = x + INCREMENT) for (double x = MIN; x <= MAX; x = x + INCREMENT)

1010 { {

11 11 RootApproximator r = new RootApproximator(x); RootApproximator r = new RootApproximator(x);

1212 double y = r.getRoot(); double y = r.getRoot();

1313 System.out.println("square root of " + x + " = " + y); System.out.println("square root of " + x + " = " + y);

1414 } } } } } }

Page 14: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

File File RootApproximatorTest4.javaRootApproximatorTest4.java11 import java.util.Random; import java.util.Random;

22 /** /** This program computes square roots of random inputsThis program computes square roots of random inputs. . */ */

33 public class RootApproximatorTest4 public class RootApproximatorTest4

44 { public static void main(String[] args) { public static void main(String[] args)

55 { { final double SAMPLES = 100; final double SAMPLES = 100;

66 Random generator = new Random(); Random generator = new Random();

77 for (int i = 1; i <= SAMPLES; i++) for (int i = 1; i <= SAMPLES; i++)

88 { // generate random test value { // generate random test value

99 double x = 1.0E6 * generator.nextDouble(); double x = 1.0E6 * generator.nextDouble();

1010 RootApproximator r = new RootApproximator(x); RootApproximator r = new RootApproximator(x);

1111 double y = r.getRoot(); double y = r.getRoot();

1212 System.out.println("square root of " + x + " = " + y); System.out.println("square root of " + x + " = " + y);

1313 } }

1414 } }

1515 } }

Page 15: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Test CasesTest Cases Positive test case:Positive test case: expect positive expect positive

outcomeoutcomeE.g. square root of 100 E.g. square root of 100

Negative test case:Negative test case: expect negative expect negative outcomeoutcomeE.g. square root of 100 E.g. square root of 100

Boundary test case:Boundary test case: at boundary of at boundary of domaindomainFrequent cause for errorsFrequent cause for errorsE.g. square root of 0E.g. square root of 0

Page 16: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Test Case EvaluationTest Case Evaluation ManualManual

E.g. You know the result and you verify if the E.g. You know the result and you verify if the program has produced the correct resultprogram has produced the correct result

Check property of resultCheck property of resultE.g. square root squared = original valueE.g. square root squared = original value

Oracle = slower way of computing answerOracle = slower way of computing answerE.g. square root of E.g. square root of x = xx = x1/21/2

Page 17: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Regression TestingRegression Testing

► Save test cases Automate testingSave test cases Automate testing► java Program < test1.in > test1.outjava Program < test1.in > test1.out

java Program < test2.in > test2.outjava Program < test2.in > test2.outjava Program < test3.in > test3.outjava Program < test3.in > test3.out

► Repeat test whenever program changes Repeat test whenever program changes Test suite = collection of test cases Test suite = collection of test cases Cycling = bug that is fixed but Cycling = bug that is fixed but

reappears in later versionreappears in later version Regression testing = testing against Regression testing = testing against

past failurespast failures

Page 18: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Test CoverageTest Coverage

► Black-box testing:Black-box testing: test functionality test functionality without understanding internal structure without understanding internal structure

► White-box testing:White-box testing: take internal take internal structure into account when designing structure into account when designing tests tests

► Test coverage:Test coverage: the code that is actually the code that is actually executed during test cases executed during test cases

► Easy to overlook errorEasy to overlook error branches during branches during testingtesting Make sure to execute each branch in at Make sure to execute each branch in at

least one test case least one test case

Page 19: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Program TraceProgram Trace Output statements in your program for Output statements in your program for

diagnostic purposesdiagnostic purposes

if (status == SINGLE) if (status == SINGLE) { { System.out.println("status is SINGLE"); System.out.println("status is SINGLE"); ... ... } } ......

Page 20: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

LoggingLogging

1.1. Get global logger object:Get global logger object:Logger logger = Logger.getLogger("global");Logger logger = Logger.getLogger("global");

2.2. Log a messageLog a messagelogger.info("status is SINGLE");logger.info("status is SINGLE");

3.3. By default, logged messages are printed. By default, logged messages are printed. Turn them off withTurn them off withlogger.setLevel(Level.OFF); logger.setLevel(Level.OFF);

Remember to import java.util.logging.Logger Remember to import java.util.logging.Logger

Page 21: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

The DebuggerThe Debugger DebuggerDebugger = program to run your = program to run your

program, interrupt it, and inspect program, interrupt it, and inspect variables variables

Three key commands: Three key commands: Set Breakpoint Set Breakpoint Single Step Single Step Inspect Variable Inspect Variable

Two variations of Single Step Two variations of Single Step Step Over = don't enter method call Step Over = don't enter method call Step Inside = enter method callStep Inside = enter method call

Page 22: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

The Debugger Stopping at a The Debugger Stopping at a BreakpointBreakpoint

Page 23: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Inspecting VariablesInspecting Variables

Page 24: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Sample Debugging SessionSample Debugging Session Word class counts syllables in a word Word class counts syllables in a word Each group of adjacent vowels (aeiouy) is a Each group of adjacent vowels (aeiouy) is a

syllable syllable However, an e at the end of a word doesn't However, an e at the end of a word doesn't

count count If algorithm gives count of 0, increment to 1 If algorithm gives count of 0, increment to 1 Constructor removes non-letters at Constructor removes non-letters at

beginning and end beginning and end Buggy output:Buggy output: Syllables in hello: 1Syllables in hello: 1

Syllables in regal: 1Syllables in regal: 1Syllables in real: 1Syllables in real: 1

Page 25: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

File Word.javaFile Word.java11 public class Word public class Word

22 { {

33 /** /** Constructs a word by removing leading and trailingConstructs a word by removing leading and trailing

44 non-letter characters, such as punctuation marks. non-letter characters, such as punctuation marks.

55 @param s the input string @param s the input string */ */

66 public Word(String s) public Word(String s)

77 { int i = 0; { int i = 0;

88 while (i < s.length() && !Character.isLetter(s.charAt(i))) while (i < s.length() && !Character.isLetter(s.charAt(i)))

99 i++; i++;

1010 int j = s.length() - 1; int j = s.length() - 1;

1111 while (j > i && !Character.isLetter(s.charAt(j))) while (j > i && !Character.isLetter(s.charAt(j)))

1212 j--; j--;

1313 text = s.substring(i, j + 1); text = s.substring(i, j + 1);

1414 } }

1515

Page 26: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

1616 /** /** Returns the text of the word, after removal ofReturns the text of the word, after removal of

1717 the leading and trailing non-letter characters. the leading and trailing non-letter characters.

1818 @return the text of the word @return the text of the word */ */

1919 public String getText() public String getText()

2020 { return text; } { return text; }

2121

2222 /** /** Counts the syllables in the word. Counts the syllables in the word.

2323 @return the syllable count @return the syllable count */ */

2424 public int countSyllables() public int countSyllables()

2525 { int count = 0; { int count = 0;

2626 int end = text.length() - 1; int end = text.length() - 1;

2727 if (end < 0) return 0; if (end < 0) return 0; // the empty string has no // the empty string has no syllablessyllables

2828

2929 // An e at the end of the word doesn't count as a vowel // An e at the end of the word doesn't count as a vowel

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

3131 if (ch == 'e') end--; if (ch == 'e') end--;

Page 27: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

3232 boolean insideVowelGroup = false; boolean insideVowelGroup = false;

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

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

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

3636 { // ch is a vowel { // ch is a vowel

3737 if (!insideVowelGroup) if (!insideVowelGroup)

3838 { // start of new vowel group { // start of new vowel group

3939 count++; count++;

4040 insideVowelGroup = true; insideVowelGroup = true;

4141 } }

4242 } }

4343 4444 // Every word has at least one syllable // Every word has at least one syllable 4545 if (count == 0) if (count == 0) 4646 count = 1; count = 1; 4747 return count; return count; 4848 } } 4949 private String text; private String text; 5050 } }

Page 28: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

File WordTest.javaFile WordTest.java11 import java.util.StringTokenizer; import java.util.StringTokenizer;

22 import javax.swing.JOptionPane; import javax.swing.JOptionPane;

33 public class WordTest public class WordTest

44 { public static void main(String[] args) { public static void main(String[] args)

55 { {

66 String input = JOptionPane.showInputDialog("Enter a sentence"); String input = JOptionPane.showInputDialog("Enter a sentence");

77 StringTokenizer tokenizer = new StringTokenizer(input); StringTokenizer tokenizer = new StringTokenizer(input);

88 while (tokenizer.hasMoreTokens()) while (tokenizer.hasMoreTokens())

99 { {

1010 String token = tokenizer.nextToken(); String token = tokenizer.nextToken();

1111 Word w = new Word(token); Word w = new Word(token);

1212 int syllables = w.countSyllables(); int syllables = w.countSyllables();

1313 System.out.println("Syllables in " + w.getText() + ": " + System.out.println("Syllables in " + w.getText() + ": " + syllables); syllables);

1414 } }

1515 System.exit(0); System.exit(0);

1616 } } } }

Page 29: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Final Letter Test is Not Final Letter Test is Not CorrectCorrect

Set breakpoint in line 35 (first line of Set breakpoint in line 35 (first line of countSyllables) countSyllables)

Start program, supply input hello Start program, supply input hello Method checks if final letter is 'e'Method checks if final letter is 'e' Run to line 41 Run to line 41 Inspect variable ch Inspect variable ch Should contain final letter but contains Should contain final letter but contains

'l''l'

Page 30: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Debugging the countSyllables Debugging the countSyllables MethodMethod

Page 31: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

The Current Values of the Local The Current Values of the Local and Instance Variablesand Instance Variables

Page 32: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

More Problems FoundMore Problems Found

end is set to 3, not 4 end is set to 3, not 4 text contains "hell", not "hello" text contains "hell", not "hello" No wonder countSyllables returns 1 No wonder countSyllables returns 1 Culprit is elsewhere Culprit is elsewhere Can't go back in time Can't go back in time Restart and set breakpoint in Word Restart and set breakpoint in Word

constructor constructor

Page 33: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Debugging the Word Debugging the Word ConstructorConstructor

Supply "hello" input again Supply "hello" input again Break past the end of second loop in constructor Break past the end of second loop in constructor Inspect i and j Inspect i and j They are 0 and 4--makes sense since the input They are 0 and 4--makes sense since the input

consists of letters consists of letters Why is text set to "hell"? Why is text set to "hell"? Off-by-one error: Second parameter of substring Off-by-one error: Second parameter of substring

is the first position is the first position notnot to include to include text = substring(i, j);text = substring(i, j);

should beshould betext = substring(i, j + 1);text = substring(i, j + 1);

Page 34: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Debugging the Word Debugging the Word ConstructorConstructor

Page 35: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Another ErrorAnother Error Fix the error Fix the error Recompile Recompile Test again:Test again: Syllables in hello: 1Syllables in hello: 1

Syllables in regal: 1Syllables in regal: 1Syllables in real: 1Syllables in real: 1

Oh no, it's still not right Oh no, it's still not right Start debuggerStart debugger Erase all old breakpoints Erase all old breakpoints Supply input "regal"Supply input "regal"

Page 36: Chapter 10 Testing and Debugging. Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation

Debugging countSyllables Debugging countSyllables (again)(again)

Break in the beginning of countSyllables Break in the beginning of countSyllables Single-step through loop Single-step through loop First iteration ('r'): skips test for vowel First iteration ('r'): skips test for vowel Second iteration ('e'): passes test, increments count Second iteration ('e'): passes test, increments count Third iteration ('g'): skips test Third iteration ('g'): skips test Fourth iteration ('a'): passes test, but doesn't increment Fourth iteration ('a'): passes test, but doesn't increment

countcount insideVowelGroup was never reset to false insideVowelGroup was never reset to false Fix and retest: All test cases pass Fix and retest: All test cases pass Is the program now bug-free? The debugger can't answer Is the program now bug-free? The debugger can't answer

that. that.