I was asked to comment on Testing in general terms and what approach can fit most projects. What follows is my response, from a Java Test Driven perspective. I probably need clarification and some better words around this topic, but this is a start.
Think about the behavior you need to test. Make java interfaces to support the behavior as it will help with testing.
This can be top-down or bottom-up and which doesn’t matter, use the approach that best suits you and the goals and values of the project team.
If the behavior is UI based and you are thinking top-down then your most likely needing to start with an integration test. A tool like Salenium is good for this, although HtmlUnit/HttpUnit are also good.
A UI integration test can sometimes be confused with an interaction test since people think of ‘interacting’ with the UI. If the components that the UI integrate with are mocked out then I’d be inclined to call it an interaction test. There is no hard and fast rule and just make sure your team shares the same definition of terms as you.
If your testing the behavior of a single page and just the fixed parts of this page then you could see the test as a unit test. There is a fine and blurry line in this case. Unit test tools like junit, HtmlUnit/HttpUnit/jsunit in combination with jetty are good here.
When making a unit test for the behavior of a UI it is best to use Fixtures with your tests to encapsulate the UI in java classes, since our tooling supports classes best and changes to the UI can be localized into Fixtures and minimize change impact on other tests. I recently changed a core Fixture to use HtmlUnit instead of HttpUnit and in about 15 minutes all the tests ran again with the new underlying library.
When testing a single class in isolation then all the classes that the class under test interacts with should be mocked out. Tools like jmock and easymock are good here. This would be called an interaction test since the use of mocks will require specifying the expected interactions the class under test has with the mocked classes.
Sometimes you can’t test a class without using mocks and in this case the test is an interaction test even though no unit tests exist. When you make additional test cases with concrete components, these form integration tests, since your integrating one class with an actual implementation of another.
If a concrete class is ‘cheap’ to create and use then you don’t really need to mock it but it’s still a good practice to use it via a java interface.
When running tests the units should be tested first then the integration tests since these will rely on the tested units. This isn’t a strict rule and your approach depends on the continuous integration setup and should be organized to break the build quickly to make the test loop small and fast. Unit tests typically run quicker than integration and interaction tests.
At some point in the lifecycle of the tests all the parts should come together to represent the solution as it would be in production or as close as is possible and tested end to end. This can be slow and in some projects these tests are run as a separate ’slow-build’ since it’s not common for this build to break since it depends on the faster build which would have tested the units and integrated parts already.
There is no one-size-fits-all approach and each project should determine which approach and set of tools to use and stick with them until they are found not to support the goals and values of the project team.