This is a difficult problem. Many of the "methods" in a web application take a HTTP request as input and produce HTML output with the side effect of using the database and updating some kind of session state somewhere. This is a worst-case scenario for unit testing.
HTML is tough because you really want to isolate the data that comes specifically from a given method as opposed to the boiler-plate and layout scaffolding which is common to every page. That boiler plate could change to a new color scheme or something else independent of the logic of your application that could potentially break all your tests. The database is particularly difficult because a good deal of data often needs to be set up before you can meaningfully test anything but the login screen.
I think the best approach is to use many different kinds of testing and divide and conquer.
- For small applications, a manual regression test plan is a good place to start.
- When you make components that are truly independent, write JUnit tests for them.
- If you are using servlets, you should be able to provide a fake HTTP request or fake parameters and get the output from the servlet directly. Well formatted XHTML will parse fairly easily with regular expressions. You can use unit-testing techniques against pre-loaded data in the database.
- Set up integration tests with your unit test tools (someone is going to flame me for this). Make a test that builds up a set of test data in the database using the screens of the system (as in the point above) more or less like a user of the system would. All your tests will depend on the core test suite which sets up the data for the other tests. When your regression test gets too big, this is a great alternative to manual testing.
- You may be able to use an in-memory database with a tool like Hibernate instead of setting up a complete clone of your production database and masking the data.
- Use something like Selenium to test from a browser.
- Set your master servlet up to page you whenever an exception is thrown, and remove all catch statements from your code (except those that actually do something meaningful with the exception, like recover from it). This isn't testing, but it encourages very good testing.
- I often find that the most useful testing occurs when the tester explains how the system works to an absolute beginner. We find the most meaningful bugs when building little video help segments for new features. But I can do good testing when I explain and demonstrate the details of how the system works to an interested imaginary friend.
I think if you used a tiered approach to building your application with lots of independent layers, you'd have a much easier time testing. You may need a large team of programmers to get anything done with specialists for the database, the "back end" service layer on top of the database, the business logic layer, and the view layer. In that scenario, you can use traditional unit-testing techniques with the business logic and to some extent the other layers, but the view will always be a bear.
Edit: I've been thinking about this. For as long as I can remember MVC being applied to web applications, there has been a debate about what that means. For the record, I think Ruby/Rails got it most right - that Model really means Data Model. I like this interpretation because it is most compatible with making a service layer in your application. I recently read Steve Yegge's Platform Rant that was really eye-opening for me. Make the service your data model and eat your own dog food. That way someone else can make your creation into something you never imagined. The reason I bring it up here (besides the fact that I can't stop thinking about it) is that having divisions in your code makes it easier to test.
Look, I'm not in the layers-make-everything-better camp. I have to produce, and produce lots of features without a lot of help for a living. I'm just saying that if your project is mature enough that you aren't changing the database so much any more, consider turning your ORM nightmare into a service layer for Steve Yegge's reasons, but also because the additional interface should make your testing much easier and more effective.
It is absolutely common practice to have multiple test methods in a class.
JUnit methods are usually invoked via reflection by collecting all methods in a class (or, as you say, in an entire suite), not by a human application programmer choosing methods from a well-defined API. Therefore, there is no point in keeping each individual test class short or readable; people aren't supposed to understand a class that holds unit tests as a cohesive unit in the same the way that a class of production code should be cohesive. Having one class per test just puts unnecessary strain on your file system (dealing with thousands of files in a directory is often non-linearly expensive).
Best Answer
If your application is doing XML operations and has JUnit tests then the only real dependency there is the dependency to
junit.jar
. Your application should not need any Eclipse specific libraries on the classpath.You sound as if you do not have a complete understanding of what the classpath is and how it relates to the compilation and execution of Java code. I highly recommend that you learn how to develop a simple application with a text editor and the command line.
As far as submitting your code, you can compile and package your code into a JAR file, and submit this along with
junit.jar
and a simple batch file or shell script that will execute the Java virtual machine to run your program.Another way would be to compile your program, unpackage junit.jar, and package it all together into an Executable Jar file. All of your classpath dependencies will be self contained within the one file and on most operating systems it can be launched as a typical executable.