41
Testing and Error Handling Intro to Java

Testing and Error Handling

  • Upload
    kevork

  • View
    57

  • Download
    0

Embed Size (px)

DESCRIPTION

Testing and Error Handling. Intro to Java. Testing. We test to try and make sure our programs work correctly and have no bugs If we have access to the code, we look at the structure of the code and try to make sure every case is tested. This is called “white box testing” - PowerPoint PPT Presentation

Citation preview

Page 1: Testing and Error Handling

Testing and Error Handling

Intro to Java

Page 2: Testing and Error Handling

Testing• We test to try and make sure our programs work correctly and have

no bugs• If we have access to the code, we look at the structure of the code

and try to make sure every case is tested. This is called “white box testing”• Otherwise, we test the code seeing if it does its job and if what it does

matches the Javadocs. This is called “black box testing”

Page 3: Testing and Error Handling

Testing Examplepublic class TestExample{

private int[] array = new int[4];private int size = 0;

// adds a number to the array, // resizes if necessarypublic void add(int num){

if (this.size == this.array.length)this.resize();

this.array[size++] = num;}

private void resize(){

int[] temp = new int[this.array.length * 2];for (int i = 0; i < this.array.length; i++)

temp[i] = this.array[i];this.array = temp;

}}

White box testing: we can see the code (we can only directly call the add() method). What would you test?

Add a number, make sure it’s there

Add at least 5 numbers to make sure the array resizes

Page 4: Testing and Error Handling

Testing Examplepublic class TestExample{

private int[] array = new int[4];private int size = 0;

// adds a number to the array, // resizes if necessarypublic void add(int num){

if (this.size == this.array.length)this.resize();

this.array[size++] = num;}

private void resize(){

int[] temp = new int[this.array.length * 2];for (int i = 0; i < this.array.length; i++)

temp[i] = this.array[i];this.array = temp;

}}

Black box testing. We can only see the add() method exists and the JavadocsWhat would you test?

Add a number, make sure it’s there

Add a bunch of numbers and make sure they are all there

We don’t know what value the array first resizes, so we have to add a bunch to hope we hit the case when it does resize

Page 5: Testing and Error Handling

Boundary Cases• You should always test the boundary cases, the ones that are on the

border

• Test -2, -1, 4, 5, 6 – numbers that are edge cases• Always test valid and invalid numbers

if (-2 < a && a <= 5)…

Page 6: Testing and Error Handling

More Testing• Regression testing: if you update/add code, make sure what worked

before still works• Unit testing: individually test each method with its own mini driver

program. Typically used with white box testing• Good practice to write code and unit tests at the same time

Page 7: Testing and Error Handling

Testing Data• Where does the data come from?• You can make up values that you think the problem should have

trouble with (invalid cases)• You can write programs to randomly generate a lot of data. This is

helpful for blackbox testing.• Example: you write a program that adds 1,000,000 random Pokemon to a

trainer and make sure that it doesn’t crash

Page 8: Testing and Error Handling

Error Handling• How do we handle errors in programming?• What is an error?• NullPointerException, FileNotFoundException, IllegalArgumentException, etc.

• Display error message with System.err.println()• Quit the program with System.exit(1)• Both of these are really ugly – can we do better?

Page 9: Testing and Error Handling

Exception Handling• What is an Exception?• An Object which contains information about the error that just

happened

• You’ve seen a lot of these. You can even subclass them to create your own!• How does this help us? First, let’s talk about the Call Stack

Exception e1 = new Exception();Exception e2 = new NullPointerException();Exception e3 = new InputMismatchException();

Page 10: Testing and Error Handling

Call Stack• The Call Stack in Java shows you the path through the program the

computer took to reach where it is• Keep a stack (like a stack of plates) of all of the methods you call.• Once you enter a new method, you put that on top of the stack.• If you exit a method, remove it from the stack

Page 11: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

Page 12: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

main

Page 13: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

main

Page 14: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

main

methodA

Page 15: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

main

methodA

Page 16: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

main

methodA

methodB

Page 17: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

main

methodA

methodB

Page 18: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

main

methodA

Page 19: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

main

methodA

Page 20: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

main

Page 21: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

main

Page 22: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

main

methodC

Page 23: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

main

Page 24: Testing and Error Handling

Stack Examplepublic static void main(String[] args) {

System.out.println(“starting”);methodA();methodC();

}

private static void methodA() {System.out.println(“Starting A”);methodB();System.out.println(“done A”);

}

private static void methodB() {System.out.println(“Starting B”);System.out.println(“Done B);

}

private static void methodC() {System.out.println(“Starting and ending C”);

}

Call Stack

Page 25: Testing and Error Handling

Call Stack

• How do you read this? Bottom up• The main method called methodA on line 12• methodA called methodB on line 17• methodB called methodC on line 22• methodC had an error on line 27

Page 26: Testing and Error Handling

Back to Exceptions• So how do you actually create an exception?• Since it’s an Object, you use the new keyword• The keyword for exceptions is throw

public double mySqrt(double num){

if (num < 0)throw new IllegalArgumentException(“The value of num

must be non-negative”);return Math.sqrt(num);

} If this happens, the method stops executing right here and returns to the method that called it

This is the Java way to say “Something went wrong. I don’t know how to deal with it, make someone else fix it”

Page 27: Testing and Error Handling

Try Blocks• Now what? We handle exceptions with what’s called a try block

try{

Scanner scanner = new Scanner(new FileReader(“file.txt”));

// do something here}catch (IOException e){

e.printStackTrace();}

Inside the try, you put the code that might “throw” (or cause) an exception

Now you don’t have to write “throws IOException” at the top!

You can think of the code saying:“Do this code.

If this exception is caused,

stop executing, and execute this code instead.”

We are declaring an IOException object called e here. Java will assign the value of e for us. Since e is as object, we can call methods on it.

Somewhere in the constructor for FileReader defined by Java, they wrote “throw new IOException()”

Page 28: Testing and Error Handling

Throwing Exceptions• If a method could potentially throw an Exception, you have two

choices:• Handle it with a try-catch block• Declare that the method which calls it could also throw that same exception

public static void main(String[] args){ try { System.out.println(mySqrt(-4)); } catch (IllegalArgumentException e) { System.out.println(“Oops!”); }}

Potentially throws an IllegalArgumentException

public static void main(String[] args) throws IllegalArgumentException{ System.out.println(mySqrt(-4));}

Here, your program ends gracefully Here, your program crashes!

Page 29: Testing and Error Handling

Examplepublic static void main(String[] args) throws IOException { Scanner kb = new Scanner(System.in); char choice; do {

choice = kb.next().charAt(0);switch (choice) { choice ‘a’:

Scanner scanner = new Scanner(new FileReader(kb.nextLine())); // do something with the scanner

break;}

} while (choice != ‘q’);}

Before

If the file does not exist, this is going to cause a FileNotFoundException

Program would crash!

Page 30: Testing and Error Handling

Examplepublic static void main(String[] args) { Scanner kb = new Scanner(System.in); char choice; do {

choice = kb.next().charAt(0);switch (choice) { choice ‘a’:

try { Scanner scanner = new Scanner(new FileReader(kb.nextLine())); // do something with the scanner} catch (FileNotFoundException e) {

System.out.println(“File could not be found”);}break;

} } while (choice != ‘q’);}

AfterIf the file does not exist, a FileNotFoundException is thrown, but it is “caught” with our catch block

The scanner code stops execution, it displays “File could not be found” and continues. It does NOT crash

Page 31: Testing and Error Handling

Exceptions and the Call Stack• What actually happens when we throw an Exception?

Call Stack

main

createDatabase

createTable

readInputFile

readInputFile tries to read a file. If it handles the exception (it uses a try-catch block), then we don’t have to do anything else. If it does not handle the exception, it must declare that it “throws IOException”

public void readInputFile(String filename) throws IOException{ Scanner scanner = new Scanner( new FileReader(filename));

// read in and do something with the data}

public void readInputFile(String filename){ try { Scanner scanner = new Scanner( new FileReader(filename)); // read in and do something with the data } catch (IOException e) { // deal with the exception here }} We’re saying watch out, we might run

into this problem and I don’t want to deal with it.

We’re saying I know this issue might happen and I’m going to take care of it if it does.

This won’t compile unless you do one of these two options.

Page 32: Testing and Error Handling

Exceptions and the Call Stack• Let’s say readInputFile didn’t handle the exception• That means createTable must either handle it with a try-catch block

OR it can make someone else handle it

Call Stack

main

createDatabase

createTable

readInputFile throws IOExceptionpublic void createTable() throws IOException{ String filename = “file.txt”; readInputFile(filename);}

Since readInputFile could throw an IOException, we must handle it or say that createTable could also throw the exception

Let’s just say that createTable also does not handle it

Page 33: Testing and Error Handling

Exceptions and the Call Stack• The error keeps getting thrown up the Call Stack until someone deals with it• If we keep throwing it and it’s not handled in main, then the program

crashes

Call Stack

main

createDatabase

createTable throws IOException

readInputFile throws IOException We don’t want the program to crash, so we’re going to handle the Exception in createDatabase

public void createDatabase(){ try { createTable(); } catch (IOException e) { System.out.println(“Error”); }}

Now if the IOException is thrown in readInputFile, the code stops executing in readInputFile and createTable, and it goes to the catch block here

Not being able to find the file in readInputFile will now be unable to make our program crash.

Page 34: Testing and Error Handling

Creating Our Own Exceptions• What if you need to have an error that isn’t really the same as any of

the built in Java ones?• We can create our own! Just extend the Exception Object

• We can now say “throw new EvenNumberRequiredException()”

public class EvenNumberRequiredException extends Exception{

public EvenNumberRequiredException(){

super(“An even number is required”);}

}

Page 35: Testing and Error Handling

What about Multiple Exceptions• Some methods could potentially throw more than one Exception• So create more than 1 catch block• You can only go into 1 catch block, then you keep executing code

try{ crazyMethod();}catch (IOException e){ // do something}catch (NullPointerExecption e){ // do something}…

Page 36: Testing and Error Handling

What about Multiple Exceptions• What happens with inheritance here?• If you look at the Exception hierarchy:

Exception

IOException

FileNotFoundException

Is a

Is a

try{ crazyMethod();}catch (IOException e){ // do something}catch (FileNotFoundException e){ // do something}…

A FileNotFoundExcetpion is an IOException, so whichcatch block get executed?

Always the first one! Here, the FileNotFound catch block will NEVER be executed

Page 37: Testing and Error Handling

What about Multiple Exceptions• What happens with inheritance here?• If you look at the Exception hierarchy:

Exception

IOException

FileNotFoundException

Is a

Is a

try{ crazyMethod();}catch (FileNotFoundException e){ // do something}catch (IOException e){ // do something}…Now if a FileNotFoundException is thrown, it will execute

the FileNotFound catch block and skip the IOException block.

Page 38: Testing and Error Handling

What about Multiple Exceptions• If you want to catch every possible Exception with 1 catch block, catch Exception

try { badMethod();}catch (Exception e){ // do something}

Page 39: Testing and Error Handling

Checked versus Unchecked• Checked exceptions must be handled or declared that they are

thrown• IOException, FileNotFoundException, etc.

• Unchecked exceptions can be handled, but you don’t need to declare that they are thrown• NullPointerException, ArrayIndexOutOfBoundsException, etc.• Unchecked exceptions all extend RuntimeException

Page 40: Testing and Error Handling

Finally Block• A finally block will be executed after the try no matter how the try block is exited PrintWriter writer = null;

String filename = kb.nextLine();try { writer = new PrintWriter(new FileWriter(filename)); // write something to the file} catch (IOException e) { System.err.println(“Problem writing to “ + filename);}finally{ if (writer != null)

writer.close();}

Page 41: Testing and Error Handling

Summary• Exceptions are a way of error handling in Java• If a method could cause an exception, it must either handle it with a

try-catch block or it has to declare that it throws that exception• If it declares it will throw the exception, every method which calls it

must handle it or throw it. This repeats (recursively!) until main. If main throws it, the program crashes.