Debugging code is a topic that people do not find particularly interesting, but it is vital to the software development cycle. Detecting bugs early saves money. It is estimated that software bugs missed at requirements definition stage can cost 5 times more to fix during design, 10 times more to fix during coding, 20 times more to fix during unit testing and 200 times more to fix after the software has been delivered. The first defense against bugs are assertions. Assertions contain Boolean statements that confirm the state of the program at a point in the source code.
With the release of J2SE 1.4 Assertions were introduced into the Java language.
Here is a code example to show assertions in use. The line assert s!=null;
is an example of an assertion. We are asserting the state of s
at this point in the program code. We are assuming that it is not equal to null
. Now assume that the //code here...
line represents a
set of statements that are called that could potentially affect s
. The assertion that we make just checks that s!=null
. Now it is not
really that useful here, but assume that the //code here
could have the negative effect of causing s
to be set to null
. The assertion
statement checks that this is not the case.
public class AssertionTest { public static void main(String[] args) { String s; s = new String("Hello World!"); //code here... //e.g. s=null; assert s!=null; //System.out.println(s); //Call something important and pass s } }
In this program if s
does equal null
then an exception will occur of the form:
Exception in thread "main" java.lang.AssertionError at AssertionTest.main(AssertionTest.java:11)
This will only occur if we have 'turned on' assertions in the virtual machine. We can do this by passing the flag
-ea
at the command line e.g. java -ea AssertionTest, where AssertionTest is
the name of our class. We can also do this by adding -ea
to the VM Arguments in the Run Configuration
of our Eclipse IDE.
In this section of code we can assume that s
exists and can be used safely after we perform the
assertion, but importantly it will also help us quickly identify errors in our code.
It is worth mentioning that assertions exist in C++ also, but we do it by calling a standard function
void assert(int expression)
which only works if we have #define NDEBUG
present
at the start of our program. Once testing is complete in C++, all we have to do is remove the line
#define NDEBUG
from our code; in Java, we simply remove the -ea
flag from our call
to the Virtual Machine. In both cases, assertions do not affect the performance of our release level code.
There are some additional functionality with assertions in Java. For example, we can display a message when an assertion exception occurs.
public static void main(String[] args) { ... assert s!=null : "The String S is Null"; ... }
which results in the following exception when the assertion evaluates to false (i.e. s is null):
Exception in thread "main" java.lang.AssertionError: The String S is Null at AssertionTest.main(AssertionTest.java:11)
So, assertions allow for conditional testing of our code, where importantly, we can turn off the checks once we have ensured that the code is working correctly. Assertions can therefore play a valuable role in debugging and designing code, while keeping testing in mind.
© 2006
Dr. Derek Molloy
(DCU).