Important Practical Tips for JUnit Users

Test driven development, automated testing, open source unit testing frameworks, mocking test data, etc. etc. have been buzzing around us for past few years. Most of the Java developers must have used JUnit to write unit test cases at least once. Below are some of the points that I found important while writing JUnit test cases in application development. You can call these as tips, best practices, or whatever you like.

  1. Externalize Data: Move test data out of test classes. You can have helper classes to support, or you can code data loading mechanism in set up methods. Test data can be externalized to text files, xml files, excel files, and database tables or any other fancy way you think.
  2. Setup at the Beginning and Destroy at the End: Load required test data at the beginning of test suite execution. You can delay test data loading as late as to the setup method of individual test classes. Also, it is good to remove the test data when it is no more needed.
  3. Unit Testing should Target Development Database: Database getting used for JUnit test cases should be development database instead of any other (higher) environment databases. JUnit test suites are run during build process, hence instead of going to test/acceptance test environments, target development database. You can pollute it without fear.
  4. Assert Success and Failure Scenarios Both: Test step execution will lead to some desired or even any un-desired results. Assert using JUnit provided assertion techniques, and decide success or failure of test.
  5. Test Coverage should be enough: Ideally you should have 100% test coverage for all classes. But practically, you can exclude data classes (having only getters and setters) or write a test generator utility that reduces effort getting spent on these classes. For important functional classes, the test coverage should be more than 90%, and overall test coverage can fall to 80%. It can be more stringent than this depending on accuracy level required. But usually 80% of testing is enough to make system satisfactorily stable for further (integration/system) testing.
  6. Use JUnit for Unit testing and not for System testing: Usual mistake that is observed is you tend to test application layers using JUnit. i.e. Servlet test case also tests integration till database. This is not unit testing. This leads to un-necessary coupling, and makes test cases un-maintainable in future.
  7. Enough Logging: Logging helps to monitor progress of test execution, and also helps to debug in case of any failure. Add enough debug statements (may be using the same logging framework as that of the main code).
  8. Automate Test Suite Execution: Using build tools like Ant or Maven, you can automate the test execution. You may need to write small amount of code for this but it saves a lot of pain later. One command and all tests are run. This also does not make developers feel burden of test execution every time.
  9. Reduce Memory Footprint: Loading too much data is common cause of large memory footprint. Load only required data. Large memory footprint slows down the test execution. You can also look at nullifying heavy classes in finally blocks or in exception blocks.
  10. Coupling Amongst Test Classes should be Minimized: Unit nature of test classes should be preserved. Many times we end up reusing test classes leading to un-maintainable test suites due to highly coupled test classes.
  11. Generate Summary Report: At the end of test run, generate a good summary report that can help to know exact status of unit test run. Coverage monitoring tools usually provide good reports, you can use those. It is also possible to dig these reports to finer levels.
  12. Update Test Cases Along with Main Code Changes: There is always a fear of test suite becoming outdated. Development team continues to work in pressure modifying the main classes to meet timelines, leaving test suites mapping to old versions of main classes. To make test run succeed, you comment outdated test cases or assert them falsely. Both are not good for the very purpose of having unit test cases automated. Hence it is good habit to have test cases updated as a part of build.
  13. Package Test Cases and Main Classes Separately: Having both main and test packages separately makes it easy to maintain test cases. Also it helps in build tool handling. In short, this is cleaner approach.
  14. Try to Clean up Database after Test Run: If you are committing anything in database during test run, then try to bring the database to original state. Sometimes it is ok to leave DB like that, because any way you are using development database.
  15. Include Test Cases in Application Build: Make test case execution part of build command, this will make it mandatory for everybody to run the test cases and keep those updated regularly. If required you can give feature of skipping the test run.
  • Share/Bookmark
JUnit, Tech Notes

If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.

Leave Comment

(required)

(required)