SilverMark news
Test Mentor for VisualWorks Smalltalk V7.2 is now available.
Cincom ships SilverMark's Test Mentor on Cincom Smalltalk CD.

Agile Testing for Java Developers class teaches the best testing practices, patterns, techniques, and tools.
SilverMark's Enhanced JUnit turns your JUnit tests into load tests. Distribute your JUnit tests across multiple threads, VMs and machines.
Test your Java classes and frameworks with Test Mentor - Java Edition.
See how developers and testers can collaborate.
SilverMark and WorkSoft collaborate to run Certify tests on VisualAge Smalltalk applications.
View animated demos of SilverMark products here.
Agile Testing for Java Developers Learn how to use these tools: JUnit, Cactus, EJBUnit, HTTPUnit, Clover, Jester, MockMaker, EasyMock, JFCUnit, Jemmy, Abbot, NoUnit, JUnit-addons, JUnitPerf, Enhanced JUnit, DBUnit, SQLUnit, FIT, FITnesse, WATT, ANT, Test Mentor, and JTest.
Agile Testing for Java Developers Learn how to release better code faster and with less cost and risk through Test-driven development.
Agile Testing for Java Developers Learn how to use lightweight processes such as Extreme Programming to handle change, streamline your development and write better code, faster.
Did you know a SilverMark expert can come to your site and help you design your tests?

Point to scroll:  

 
 
 

A brief introduction to the new Java 1.4 assert facility

The Java SDK 1.4 distribution includes a new assert keyword that enables you to employ a measure of design-by-contract within your code. An assertion is a statement that contains a boolean expression that is believed to be true at the time the statement is executed. By adding statements to verify various conditions, the system corroborates your assumptions about it at runtime, increasing your confidence that it is working correctly.

Test cases are programs that exercise your Java components (classes and frameworks) during development across a variety of usage scenarios, in order to validate that they work correctly.
This article discusses how these two component validation techniques relate to each other and when to use them.

Syntax
The syntax for the assert facility is:

AssertStatement:

assert Expression1;
assert Expression1 : Expression2 ;

For example:


/**
* Look up the life expectancy of a person, given their profile
*
* @param profile, a profile describing a person
* @return expected lifetime in months
*/
public int lookupActuarial(PersonProfile profile) {
// Precondition validation
assert profile.isValid();
int answer;

**** perform lookup here ****

// Postcondition validation
assert answer > 0 && answer <= 100

return answer;
}

In the case of the new assert facility, if an assertion fails it causes a java.lang.AssertionError to be thrown.

You can place asserts in your code and then enable or disable them at a class or package level with javac command line options.
There is no facility to enable or disable them at compile time, although you can disable it programmatically using the "conditional compilation" idiom described in JLS 14.19:

static final boolean asserts = ... ; // false to eliminate asserts
if (asserts)
assert <expr> ;


About Design By Contract

Design by contract specifies that you add assertions as part of preconditions, postconditions, and class invariants.

A precondition is a condition that must be met prior to proceeding with some operation. For example, if you have a BankAccount object, a precondition to proceeding with a 'withdraw' operation is that there is enough of a balance present to satisfy the request. You should be careful that you place the precondition validation in the correct place. In this example, you would place the balance check at a point where all other error checking about an excessive withdrawal (including user notification) is presumed to have been performed.

A postcondition is a condition that must be met after some operation has been performed. For example, for checking that a calculated value is within some expected bounds.

A class invariant is a condition that must be met under all conditions. That is, it is applicable to the entire class regardless of which operations have been performed or the order. The most common example is an assertion that a queue's size is never less than zero.

Observations
Test cases apply external stimuli to your objects and validate their state. The assert facility enables you to specify constraints internally and detect them through the java.lang.AssertionError exception. These are two different but complementary approaches to testing.

Given this, one can make several observations about usage of the assert feature vs. test cases:

  • Assert statements within code help clarify internal assumptions and constraints. This certainly helps document the implementation, which leads to better understanding of the code.
  • Assert statements in classes delivered without source are not visible to the consumer.
  • Test cases help document correct usage of the objects under test. That is, they are intention revealing devices.
  • Assertions, unlike test cases, are of no use in validating input vs. expected output across a range of scenarios.
  • Assertions can have performance implications unless they are turned off
  • Unlike test cases, assertions are runtime artifacts, and can provide continuous and ongoing validation. This helps guard against difficult to test conditions such as numeric tolerance drift and thread safety issues.
  • Test cases generally can only validate what is publicly visible, whereas assertions can be used to perform validation deep within private methods.

A few recommendations for effective use of the assertion facility during component testing

Both approaches have their advantages and disadvantages. Fortunately your are not faced with an either-or decision. The best approach is to leverage the advantages that each approach offers, while avoiding potential pitfalls:

  • It is certainly reasonable to rely on assertions to perform constraint validation. During test execution violations cause java.lang.AssertionError exceptions to be thrown, which will be trapped and logged by the test framework. They will also serve as continuous runtime diagnostics.
  • You will need test cases to apply stimuli to your system, across a set of use case scenarios.
  • You should include test case based validation to ensure that objects are in expected state, given a reasonable range of input values.

    By state, we mean the state of instance variables after a particular stimulus has been applied to an object, as well as returned values. Remember that internal assertions only validate according to constraints. They are not effective for validating expected output for a given input.

  • Do not use assertions in place of method input parameter validation, except in the case where you are asserting that the validation has correctly taken place and only 'good' values are expected at a given point in the code.
    For example, consider that case where a user enters a value for a calculation. You should not use the assertion facility to validate that the user has entered data within the correct range. However it is reasonable to use the assertion facility downstream where only correct values are expected.

About the author

Michael Silverstein is a co-founder and CTO of SilverMark, Inc. and has been delivering working software since 1981.

More information about the assertion facility:
http://java.sun.com/j2se/1.4/docs/guide/lang/assert.html

More information about design by contract
http://www.eiffel.com/doc/manuals/technology/contract/

Home | Products | Services | Company | Contact | Partners | Library | Search |

Copyright © 1996-2004 SilverMark, Inc.