Tuesday, July 14, 2009

Testing Web Applications

How many times have you been on a project and seen changes to code cause the application to blow up, and yet the Unit Tests all succeeded? To avoid this situation I use HtmlUnit, an open source project distributed under the Apache License.

HtmlUnit emulates a browser that is visiting your web application. Coupled with JUnit, it allows you to write tests that click through the application just as QA does. It ensures that the functionality you put into your pages exists and works properly.

With HtmlUnit and Junit I am able to test most functionality in the web tier : page flow, form population and submission, javascript, popups, dialogs, and AJAX calls. I even created a suite of convenience methods to work with my Trinidad components.

The one shortcoming has been the ability to test Flex animations. These were always a black box to my test suites. However, Gorilla Logic has now released FlexMonkey, which is also based on HtmlUnit, and allows you to test the flex animations from an easy to use test suite.

I use these tests as both integration and unit tests. I ensure the application can be "clicked through"; that all pages appear at the correct time, and that interactions in the page all function correctly. I also test various scenarios that will occur in the application, and ensure that the application responds correctly based on the processing of the data passed in.

I no longer worry about the application blowing up in meetings or demos:

IT'S BEEN TESTED!!

Hibernate Search by Date

On the project I am on now, we use Dates as a basis for monetary calculations. The Dates are simply based on the day, month and year, disregarding hours, minutes and seconds. We store our dates after base-lining them - stripping out the H:M:S. This is achieved with Calendar utilities:

static Date baseLineDate(Date myDate) {
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(myDate);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}

Determining if a Date is before, after, or equal to another is straightforward thereafter- just use the Calendar before() and after() methods.

If you look in the database, the dates are stored as 01-Jan-2009. It would be tempting to simply run a Hibernate query that tests equality. You could simply generate a base-lined date and ask Hibernate to return the objects that have this Date. And it works.

However... Databases are part of the seedier side of the software town. Lurking there is data imported from other systems and/or updated by rogue administrators. The best way to handle all possible situations correctly is to use the Hibernate Criteria's between() method:


getCurrentSession().createCriteria( MyItem.class )
.add(Expression.between("myDateField", base-lined-Date, end-lined-Date))
.list();

Where the base-lined-Date has been base-lined as above, and the end-lined-Date corresponds to a Date that is the last millisecond of the day:

static Date EndLineDate(Date d){
if(d==null)return null;
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(d);
cal.set(Calendar.HOUR, 11);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.HOUR_OF_DAY,23);
cal.set(Calendar.MILLISECOND, 999);
return cal.getTime();
}

This solution pulls in all objects that have a certain Date defined by Day, Month and Year only.