With TDD, you start with user stories and you write acceptance tests for those stories. To implement the functionality for the stories, you write unit tests first, then just enough code to make the unit tests pass, and then you refactor. You repeat the test-code-refactor cycle until the acceptance tests pass.
If your development team is not already using TDD, the first step is to provide adequate training on the concepts and patterns of TDD. One option is to hire an Agile coach or pair junior developers with experienced practitioners of TDD. Next, you need to use the frameworks and tools that will facilitate adoption, keep your developers productive, and provide transparency into the process. The following are tools and frameworks (all are free and open-source) that we find useful:
- Build tool: Maven 2
- Continuous integration: Hudson
- A tool for configuring, starting, stopping Java containers and deploying applications for continuous integration and functional tests: Cargo
- Unit testing frameworks: JUnit 4.4, EasyMock, and JSFUnit (for JSF applications)
- Enforcing coding standards: Checkstyle
- Detecting bugs, overcomplicated expressions, and suboptimal/dead/duplicate code: PMD and FindBugs
- Code review: Jupiter
- Test coverage: Cobertura
- Web Services functional and load testing: SoapUI
- User interface testing: Selenium and Umangite
- Integration testing: Fit, DBUnit, DbFit, and ORMUnit
- XML unit testing: XMLUnit and Tennison Test
- Load and performance testing: JMeter
- Profiling and monitoring: JConsole
- Analyzing code dependencies: JDepend
- Source code documentation: Doxygen
- Project tracking and planning: XPlanner
By enforcing Java best practices, tools like Checkstyle, PMD, and FindBugs are very helpful for developing high quality code.
Unit and integration tests should be fast, repeatable, and automated. That's why you need to deploy a build tool and a continuous integration server from the start. All the tools listed above should be executed as part of your continuous integration process. You should use a dedicated integration build machine.
DBUnit helps make your system tests repeatable by using XML to insert a specific data set into the database before each test run. Cargo can configure and starts the web container or application server (AS), deploy your application's WAR or EAR file, and then shutdown the container after each test run.
Keep in mind that test coverage reports such as those provided by Cobertura should be used mainly to isolate code that has not been appropriately tested in order to take corrective measures. These reports shall not be used solely to aim at a magical high coverage percentage. Applications that are built on an inversion of control (IoC) container such as Spring are more amenable to unit testing.
For web applications with a user interface (UI) layer such as Struts or JSF, make sure that you exercise the UI functionalities on real web browsers (IE, Firefox, etc.) with a tool like Selenium. Fit and Fitness (the wiki-based version of Fit) are effective tools for integration testing your application's business logic. By integrating Selenium, TestNG, Spring, and Cargo, the Umangite framework makes it easy to write web tests.
If you intend to service-enable the same application, then SoapUI will help with both integration and load testing of the web services over HTTP. The nice thing about SoapUI is that in addition to XML Schema validation, it allows you to specify response assertions by using XPath 2.0, XQuery, and Groovy scripts.
Sun JDK tools such as jConsole, jmap, and jhat can help with profiling and diagnosing memory leak issues. The JMeter Proxy makes load and performance tests easy my allowing you to record a test case.
Are agile practices applicable to XML development (XML Schema modeling, XSLT, XQuery, and XSL FO programming)? You bet. More on that on my previous blog entitled Extreme XML Programming.