Unit testing tricks: Using unit tests to validate static code
In my current project, we use Flex as the user interface framework of choice. Flex has some nice features, but it takes a long time to build changes and start up, so it takes a while to validate our changes. Yesterday, we found a problem with one our UI components, and used JUnit to hunt down the same problem all over our code.
The problem was with tables. We had a table where we had set the percentage width of each column, but the total did not add up to 100%. This table looked fine initially, but when we resized it, the column widths went berserk. The result was hilarity and frustration.
In Flex, components are defined using MXML, which is an XML language. In order to 1) find out how much we needed to adjust the column widths, 2) verify that we had made the change correctly, and 3) check all other tables for the same error, we wrote a unit test that uses dom4j to parse the XML-file, reads through all column definitions and collects the percentage width attribute. The test then verifies that the total adds up to 100%.
This way, we could take the problem one place, find everywhere else it occurred, and make sure it never happens again.
We have written similar tests to make sure that all names of resource bundle strings are defined in our properties file and to make sure that classes that are transfered from the server (written in Java) to the client (written in Flex) don’t have know serialization problems. We have started using the library metaas to parse ActionScript for some of these tests (sadly, metaas has a few bugs in it’s antrl-grammar and it is not currently maintained).
In order to make it super easy to deal with the problems, we want the test failure to contain the missing code. So, for example:
StringBuilder missingProperties = new StringBuilder();
Properties properties = new Properties();
properties.load(new FileInputStream(flexResourceBundle));
SAXReader reader = new SAXReader();
Document document = reader.read(mxmlFile);
Element columnsDeclaration = document.getDocumentRoot()
.element("columns");
for (Object columnObj : columnsDeclaration.elements()) {
Element column = (Element)columnObj;
String resourceKey = getResourceKey(column);
if (properties.getProperty(resourceKey) == null) {
missingProperties.append("\\n" + resourceKey + "=");
}
}
assertTrue("Cut, paste and edit the following into "
+ flexResourceBundle + ": " + missingProperties,
missingProperties.length() > 0);
As the turnaround time with Flex is fairly high, it takes much less time to run a JUnit test that verifies source code than it does to fire up the application and try it out. A similar approach can be used to verify other things you wish the compiler would check.