Presentation is loading. Please wait.

Presentation is loading. Please wait.

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.

Similar presentations


Presentation on theme: "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."— Presentation transcript:

1 Chapter 10 Testing and Debugging

2 Chapter Goals ► To learn how to carry out unit tests ► To understand the principles of test case selection and evaluation ► To learn how to use logging ► To become familiar with the debugger ► To learn strategies for effective debugging

3 The First Bug

4 Unit Test  Test classes in isolation, outside the program in which they are used  Test one class at a time  Supply test inputs through test harness  Test harness = program that feeds test inputs to a class

5 Root Approximator ► Example program to illustrate testing: square root approximator Algorithm known to the ancient Greeks (Heron) ► Task: to compute the square root of a ► Given: a guess x (we start with x=a)  The actual square root lies between a/x and x

6 ► Take midpoint (x + a/x) / 2 as a better guess Method converges rapidly. ► Square root of 100: Guess #1: 50.5 Guess #2: 26.24009900990099 Guess #3: 15.025530119986813 Guess #4: 10.840434673026925 Guess #5: 10.032578510960604 Guess #6: 10.000052895642693 Guess #7: 10.000000000139897 Guess #8: 10.0 All the other guesses from this point on, return the same value

7 File RootApproximator.java 1 /** 2 Computes approximations to the square root 3 of a number, using Heron's algorithm 4 */ 5 public class RootApproximator 6 { 7 /** 8 Constructs a root approximator for a given number 9 @param aNumber the number from which to extract the square root 10 (Precondition: aNumber >= 0) 11 */ 12 public RootApproximator(double aNumber) 13 {a = aNumber; 15 xold = 1; 16 xnew = a; 17 }

8 18 19 /** 20 Compute a better guess from the current guess. 21 @return the next guess 22 */ 23 public double nextGuess() 24 { xold = xnew; 26 if (xold != 0) 27 xnew = (xold + a / xold) / 2; 28 return xnew; 29 } 30

9 31 /** 32 Compute the root by repeatedly improving 33 the current guess until two successive guesses are approximately equal. 34 @return the computed value for the square root 35 */ 36 public double getRoot() 37 { 38 while (!Numeric.approxEqual(xnew, xold)) 39 nextGuess(); 40 return xnew; 41 } 42 43 private double a; // the number whose square root is computed 44 private double xnew; // the current guess 45 private double xold; // the old guess 46 }

10 File RootApproximatorTest.java 1 import javax.swing.JOptionPane; 2 /** This program prints ten approximations for a square root. 3 */ 4 public class RootApproximatorTest 5 { 6 public static void main(String[] args) 7 { 8 String input = JOptionPane.showInputDialog("Enter a number"); 9 double x = Double.parseDouble(input); 10 RootApproximator r = new RootApproximator(x); 11 final int MAX_TRIES = 10; 12 for (int tries = 1; tries <= MAX_TRIES; tries++) 13{ double y = r.nextGuess(); 14 System.out.println("Guess #" + tries + ": " + y); 15 } 16 System.exit(0); 17 } 18 }

11 Unit Test with BlueJ

12 File RootApproximatorTest2 1 import javax.swing.JOptionPane; 2 /** This program computes square roots of user-supplied inputs. 3 */ 4 public class RootApproximatorTest2 5 { public static void main(String[] args) 6 { 7 boolean done = false; 8 while (!done) 9 { String input = JOptionPane.showInputDialog("Enter a number, C to quit"); 10 if (input == null) 12 done = true; 13 else 14 { double x = Double.parseDouble(input); 16 RootApproximator r = new RootApproximator(x); 17 double y = r.getRoot(); 18 System.out.println("square root of " + x + " = " + y); 20 } 21 } 22 System.exit(0); 23 } 24 }

13 Sources of Test Data ► Provided by humans RootApproximatorTest2 ► Computer-generated sequence RootApproximatorTest3 ► Random sequence RootApproximatorTest4

14 File RootApproximatorTest3.java 1 /** This program computes square roots of input values 2 computer generated by a loop. */ 3 public class RootApproximatorTest3 4 { public static void main(String[] args) 5 { 6 final double MIN = 1; 7final double MAX = 10; 8 final double INCREMENT = 0.5; 9 for (double x = MIN; x <= MAX; x = x + INCREMENT) 10 { 11 RootApproximator r = new RootApproximator(x); 12 double y = r.getRoot(); 13 System.out.println("square root of " + x + " = " + y); 14 } } }

15 File RootApproximatorTest4.java 1 import java.util.Random; 2 /** This program computes square roots of random inputs. */ 3 public class RootApproximatorTest4 4 { public static void main(String[] args) 5 { final double SAMPLES = 100; 6 Random generator = new Random(); 7 for (int i = 1; i <= SAMPLES; i++) 8 { // generate random test value 9 double x = 1.0E6 * generator.nextDouble(); 10 RootApproximator r = new RootApproximator(x); 11 double y = r.getRoot(); 12 System.out.println("square root of " + x + " = " + y); 13 } 14 } 15 }

16 Test Cases  Positive test case: expect positive outcome E.g. square root of 100  Negative test case: expect negative outcome E.g. square root of 100  Boundary test case: at boundary of domain Frequent cause for errors E.g. square root of 0

17 Test Case Evaluation  Manual E.g. You know the result and you verify if the program has produced the correct result  Check property of result E.g. square root squared = original value  Oracle = slower way of computing answer E.g. square root of x = x 1/2

18 Regression Testing ► Save test cases Automate testing ► java Program test1.out java Program test2.out java Program test3.out ► Repeat test whenever program changes  Test suite = collection of test cases  Cycling = bug that is fixed but reappears in later version  Regression testing = testing against past failures

19 Test Coverage ► Black-box testing: test functionality without understanding internal structure ► White-box testing: take internal structure into account when designing tests ► Test coverage: the code that is actually executed during test cases ► Easy to overlook error branches during testing  Make sure to execute each branch in at least one test case

20 Program Trace  Output statements in your program for diagnostic purposes if (status == SINGLE) { System.out.println("status is SINGLE");... }...

21 Logging 1.Get global logger object: Logger logger = Logger.getLogger("global"); 2.Log a message logger.info("status is SINGLE"); 3.By default, logged messages are printed. Turn them off with logger.setLevel(Level.OFF);  Remember to import java.util.logging.Logger

22 The Debugger  Debugger = program to run your program, interrupt it, and inspect variables  Three key commands:  Set Breakpoint  Single Step  Inspect Variable  Two variations of Single Step  Step Over = don't enter method call  Step Inside = enter method call

23 The Debugger Stopping at a Breakpoint

24 Inspecting Variables

25 Sample Debugging Session  Word class counts syllables in a word  Each group of adjacent vowels (aeiouy) is a syllable  However, an e at the end of a word doesn't count  If algorithm gives count of 0, increment to 1  Constructor removes non-letters at beginning and end  Buggy output:  Syllables in hello: 1 Syllables in regal: 1 Syllables in real: 1

26 File Word.java 1 public class Word 2 { 3 /** Constructs a word by removing leading and trailing 4 non-letter characters, such as punctuation marks. 5 @param s the input string */ 6 public Word(String s) 7 { int i = 0; 8 while (i < s.length() && !Character.isLetter(s.charAt(i))) 9 i++; 10 int j = s.length() - 1; 11 while (j > i && !Character.isLetter(s.charAt(j))) 12 j--; 13 text = s.substring(i, j + 1); 14 } 15

27 16 /** Returns the text of the word, after removal of 17 the leading and trailing non-letter characters. 18 @return the text of the word */ 19 public String getText() 20 { return text; } 21 22 /** Counts the syllables in the word. 23 @return the syllable count */ 24 public int countSyllables() 25 { int count = 0; 26 int end = text.length() - 1; 27 if (end < 0) return 0; // the empty string has no syllables 28 29 // An e at the end of the word doesn't count as a vowel 30 char ch = Character.toLowerCase(text.charAt(end)); 31 if (ch == 'e') end--;

28 32 boolean insideVowelGroup = false; 33 for (int i = 0; i <= end; i++) 34 { ch = Character.toLowerCase(text.charAt(i)); 35 if ("aeiouy".indexOf(ch) >= 0) 36 { // ch is a vowel 37 if (!insideVowelGroup) 38 { // start of new vowel group 39 count++; 40 insideVowelGroup = true; 41 } 42 } 43 44 // Every word has at least one syllable 45 if (count == 0) 46 count = 1; 47 return count; 48 } 49 private String text; 50 }

29 File WordTest.java 1 import java.util.StringTokenizer; 2 import javax.swing.JOptionPane; 3 public class WordTest 4 { public static void main(String[] args) 5 { 6 String input = JOptionPane.showInputDialog("Enter a sentence"); 7 StringTokenizer tokenizer = new StringTokenizer(input); 8 while (tokenizer.hasMoreTokens()) 9 { 10 String token = tokenizer.nextToken(); 11 Word w = new Word(token); 12 int syllables = w.countSyllables(); 13 System.out.println("Syllables in " + w.getText() + ": " + syllables); 14 } 15 System.exit(0); 16 } }

30 Final Letter Test is Not Correct  Set breakpoint in line 35 (first line of countSyllables)  Start program, supply input hello  Method checks if final letter is 'e'  Run to line 41  Inspect variable ch  Should contain final letter but contains 'l'

31 Debugging the countSyllables Method

32 The Current Values of the Local and Instance Variables

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

34 Debugging the Word Constructor  Supply "hello" input again  Break past the end of second loop in constructor  Inspect i and j  They are 0 and 4--makes sense since the input consists of letters  Why is text set to "hell"?  Off-by-one error: Second parameter of substring is the first position not to include  text = substring(i, j); should be text = substring(i, j + 1);

35 Debugging the Word Constructor

36 Another Error  Fix the error  Recompile  Test again:  Syllables in hello: 1 Syllables in regal: 1 Syllables in real: 1  Oh no, it's still not right  Start debugger  Erase all old breakpoints  Supply input "regal"

37 Debugging countSyllables (again)  Break in the beginning of countSyllables  Single-step through loop  First iteration ('r'): skips test for vowel  Second iteration ('e'): passes test, increments count  Third iteration ('g'): skips test  Fourth iteration ('a'): passes test, but doesn't increment count  insideVowelGroup was never reset to false  Fix and retest: All test cases pass  Is the program now bug-free? The debugger can't answer that.


Download ppt "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."

Similar presentations


Ads by Google