Welcome!

Java Authors: Maureen O'Gara, Bruce Armstrong, Liz McMillan, Walter H. Pinson, III, Yakov Werde

Related Topics: Java

Java: Article

Write Right Java Faster Using Test-Driven Development

The benefits of embracing TDD

We decide to go with option 3, specifically Java regular expressions, since there's some resistance to introducing a new and uncertified framework at the client site. We start fleshing out the FeedAutoDiscoverer by making sure it returns a list of strings. We know that the regular expression must match <link> tags with a "type" attribute of "application/rss+xml." We'll also want to extract the "href" attribute from all matching tags, so we should be sure to wrap the "href" attribute value in a capturing group. Our first version of the FeedAutoDiscoverer looks similar to Figure 4.

Lucky for us, the test passes!

After congratulating ourselves on our success, we realize that the <link> attributes might appear in any order and with embedded new lines. We decide to write a second test to handle this new scenario. This test case switches the "type" and "href" attribute ordering and adds a new line between them.

Sure enough, we find that our FeedAutoDiscoverer doesn't handle this scenario; the new test fails.

We open up the FeedAutoDiscoverer and tweak the regular expression so that it'll hopefully handle the new scenario:

  1. We add an OR operator to the original expression and switch the order of the "type" and "href" attributes in the new half;
  2. We add the DOTALL flag to the expression, which allows the '.' character to match new lines.
Now the FeedAutoDetector looks like Figure 5 .

Running the test again results in failure, but it looks like the regular expression may have worked since it's the contents of the list that are wrong. Reviewing our changes shows us that we forgot to update our capture group handling. We have two capture groups in the regular expression and have to add the proper group contents depending on which half of the regular expression worked, so we change our logic.

We find that the test now passes and we're ready to move on to adding more tests for auto-discovering Atom link references, etc.

There's a lot more to do, but we're well on our way to delivering the site "Feed Finder" service. If we wanted to, we could stop here with auto-detection and start building out the downloader component and the servlet, or we could extract an interface from the FeedAutoDiscoverer and start work on fitting it into an IoC container like Spring. Whatever we decide to do, we now have two tests that we can use to sanity-check changes we make from this point forward that might impact feed auto-discovery. If these tests continue to pass as we change the system (and we should run our tests often), we'll become more confident and comfortable with handling change.

(As an aside, at this point in real life, we discovered that there was actually a spec for ATOM-based feed auto-discovery at http://philringnalda.com/rfc/draft-ietf-atompub-autodiscovery-01.html. So, we took each of the examples in the RFC and coded them up as unit tests, and made sure that our FeedAutoDiscoverer successfully discovered them.)

Conclusion
Test-driven development helped us in many ways on this project:

  1. It forced us to translate our ambiguous requirements into verifiable test criteria;
  2. The test criteria helped us focus on doing just what was needed to pass the test, and thus hopefully satisfying the requirements;
  3. We avoided the heavy front-loading of design documentation and focused on getting some working code.
While we'll ultimately write more code with this approach we'll have fewer defects in the end product. Testing early will also help us uncover requirements errors or changes that would be expensive to address in the later stages of the project.

References

More Stories By John Evans

John Evans is the founder and president of JPEvans, Inc. (www.jpevans.com), a small independent computer consulting company based in Northern Virginia just outside of Washington D.C. John has over 10 years of professional experience in software development. He has successfully developed and deployed large-scale software systems for several large multi-national corporations.

More Stories By Richard Cariens

Richard Cariens is an independent software consultant in the Washington D.C. area (www.jpevans.com). He has over 10 years of experience testing, developing, designing, and architecting Internet technology and financial systems. Rich holds an MS in computer science from George Mason University in Fairfax, Virginia.

Comments (4) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
The Cherbin 08/22/06 06:35:33 PM EDT

The best way to write right java is either
1. DONT use it at all
2. If you are forced to use it, use java to execute an external application, and write that application in another language.

JDJ News Desk 07/30/06 11:36:06 AM EDT

Testing Java code is increasingly a task taken on by developers rather than separate teams to which the programs are handed. Many Java developers are now familiar with JUnit and know the different between unit tests and integration tests. This has been driven largely by the focus on test-driven development (TDD) in extreme programming (XP) and other agile software development methodologies. While the industry-at-large has recognized the value of unit tests and has a new outlook on testing in general, for the most part, actual TDD (meaning, the tests are written first) is not usually practiced outside of hardcore agile shops.

JDJ News Desk 07/30/06 08:56:13 AM EDT

Testing Java code is increasingly a task taken on by developers rather than separate teams to which the programs are handed. Many Java developers are now familiar with JUnit and know the different between unit tests and integration tests. This has been driven largely by the focus on test-driven development (TDD) in extreme programming (XP) and other agile software development methodologies. While the industry-at-large has recognized the value of unit tests and has a new outlook on testing in general, for the most part, actual TDD (meaning, the tests are written first) is not usually practiced outside of hardcore agile shops.

Jon Log 07/26/06 05:22:53 AM EDT

Though the development in question is a trivial one, your conclusions encapsulate perfectly why TDD is a poor substitute for a proper development model:

Conclusion 1: "It forced us to translate our ambiguous requirements into verifiable test criteria"

But on whose terms ? The "us" in your statement implies that you mean the developer. This is WRONG. An ambiguity must be flattened out by the specifier and agreed on by the developer. This is the contract you have with whoever you are providing a solution for. A developer is just as likely to interpret an ambiguity incorrectly as correctly.

Conclusion 2: "The test criteria helped us focus on doing just what was needed to pass the test, and thus hopefully satisfying the requirements"

Well, "hopefully" is not good enough. The objective of the developer MUST be to make their code do what it should in relation to the requirement. By encouraging a coder to produce something that meets only the requirements of a test that they themselves have defined is obviously a corrupt concept. Focussing on the test rather than the true objective of the requirement breaks a valuable chain of responsibility that should exist at every stage of the process.

Conclusion 3: "We avoided the heavy front-loading of design documentation and focused on getting some working code."

This is the icing on the cake. Spending time thinking about and documenting a design delivers too many obvious benefits to mention. However, in relation to the anti-patterns that I believe are a core part of your conclusions, designing a solution before implementing it would force any ambiguities to be resolved at the correct time and in the correct manner (against a coherent definition that is intelligible to the business and development communities). In addition, assuming that a solution involves more that one method (which of course it generally does) it would promote the production of a more appropriate test path with the requirements taking precedence over the tests themselves.