An Exception Is a Defect Report, Not a Crash
An environment goes down mid-run, a data file has a blank cell, an API returns 503 — these aren't rare, they're Tuesday. An exception is Java's controlled report when one happens, and a stack trace is that report's best evidence.
Every program in this book so far has been an optimist. The file is always there. The number always parses. The element is always on the page. The status code is always what you expected.
Your working life says otherwise. A test environment goes down mid-run. A data file has a blank cell in row 47. An API returns 503 instead of 200. These are not rare events — they are Tuesday. So the real question for a test engineer is not "how do I stop things going wrong?" You cannot. The question is: when something goes wrong, does my suite report a useful defect, or does it collapse in a heap and tell me nothing?
An exception is Java's way of saying "I cannot continue with this instruction, and I refuse to guess." It is not a crash in the old sense of a program dying at random. It is a controlled report — an object carrying a type, a message, and the exact path the program took to get there. Watch one interrupt a loop. This program parses three rows of test data, and the middle row is bad:
public class X1 {
public static void main(String[] args) {
String[] rows = {"12", "abc", "45"};
for (int i = 0; i < rows.length; i++) {
int value = Integer.parseInt(rows[i]);
System.out.println("Parsed: " + value);
}
System.out.println("Done");
}
}
Parsed: 12
Exception in thread "main" java.lang.NumberFormatException: For input string: "abc"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:662)
at java.base/java.lang.Integer.parseInt(Integer.java:778)
at X1.main(X1.java:5)
Look at what happened, and what did not. Row 1 parsed. Row 2 threw. Row 3 never
ran, and neither did the final Done — the exception ended the program on the
spot. One bad cell in one row killed the entire run, and the two good rows after it
were never checked. For a suite of three hundred rows that is a catastrophic
result, because you learn about exactly one problem and nothing else.
Reading a stack trace in three moves
That block of text is a stack trace, and it is a defect report with the best
evidence you will ever get. The first line gives the type and the message — a
NumberFormatException, and the reason: the input string was "abc". The indented
lines below are the call path, most recent first. And the line that matters most is
usually the last one, at X1.main(X1.java:5), because that is the first line in
your code rather than in Java's own libraries. When you read a stack trace, scan
down to the deepest line that names your own file. That is where to look.
One term worth separating from exceptions while you're here: an Error signals
something wrong at the level of the machine, such as running out of memory — you
are not expected to catch those. An Exception is a condition your program can
reasonably be expected to deal with. In practice you work with exceptions and let
errors end the run.
Right now, a single bad row kills every row after it. The next question is how to
stop that from happening — and it starts with two words: try and catch.