diff options
Diffstat (limited to 'junit4/doc/faq')
-rw-r--r-- | junit4/doc/faq/faq.htm | 2380 |
1 files changed, 2380 insertions, 0 deletions
diff --git a/junit4/doc/faq/faq.htm b/junit4/doc/faq/faq.htm new file mode 100644 index 0000000..783557e --- /dev/null +++ b/junit4/doc/faq/faq.htm @@ -0,0 +1,2380 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"/> + <title>JUnit FAQ</title> + + <style type="text/css"> + + body { + font-style: normal; + font-weight: normal; + margin-left: 10pt; + margin-right: 10pt; + } + + a { + text-decoration: none; + } + + a:hover { + text-decoration: underline; + } + + .header { + color: black; + font-size: 125%; + font-weight: bold; + background: #33ff33; + padding-top: 2px; + padding-bottom: 2px; + padding-left: 5px; + margin-top: 25px; + } + + .code { + background: white; + border-left: 5px solid #33ff33; + } + + .code-red { + background: white; + border-left: 5px solid #cc0000; + } + + </style> + +</head> + +<body> + +<h1> + <font color="#33ff33">J</font><font color="#cc0000">U</font>nit FAQ +</h1> +<hr size="1"/> + + +<!-- + + Summary + +--> +<p> +<i> +JUnit is a simple, open source framework to write and run repeatable +tests. It is an instance of the xUnit architecture for unit testing +frameworks. +</i> +</p> +<hr size="1"/> +<p> +Edited by <a href="mailto:mike@clarkware.com">Mike Clark</a> +(<a href="http://www.clarkware.com">http://clarkware.com</a>) +</p> +<p> +Last modified on February 20, 2006 +</p> + +<hr/> + +<!-- + + Table of Contents + +--> + +<div class="header"> +Table of Contents +</div> +<ol> + <li> + <p> + <b><a href="#faqinfo">FAQ Info</a></b> + </p> + <ol> + <li><a href="#faqinfo_1">Who is responsible for this FAQ?</a></li> + <li><a href="#faqinfo_2">How can I contribute to this FAQ?</a></li> + <li><a href="#faqinfo_3">Where do I get the latest version of + this FAQ?</a></li> + </ol> + </li> + <li> + <p> + <b><a href="#overview">Overview</a></b> + </p> + <ol> + <li><a href="#overview_1">What is JUnit?</a></li> + <li><a href="#overview_2">Where is the JUnit home page?</a></li> + <li><a href="#overview_3">Where are the JUnit mailing lists and + forums?</a></li> + <li><a href="#overview_4">Where is the JUnit documentation?</a></li> + <li><a href="#overview_5">Where can I find articles on JUnit?</a></li> + <li><a href="#overview_6">What's the latest news on JUnit?</a></li> + <li><a href="#overview_7">How is JUnit licensed?</a></li> + <li><a href="#overview_8">What awards has JUnit won?</a></li> + </ol> + </li> + <li> + <p> + <b><a href="#started">Getting Started</a></b> + </p> + <ol> + <li><a href="#started_1">Where do I download JUnit?</a></li> + <li><a href="#started_2">How do I install JUnit?</a></li> + <li><a href="#started_3">How do I uninstall JUnit?</a></li> + <li><a href="#started_4">How do I ask questions?</a></li> + <li><a href="#started_5">How do I submit bugs, patches, or + feature requests?</a></li> + </ol> + </li> + <li> + <p> + <b><a href="#tests">Writing Tests</a></b> + </p> + <ol> + <li><a href="#tests_1">How do I write and run a simple test?</a></li> + <li><a href="#tests_2">How do I use a test fixture?</a></li> + <li><a href="#tests_4">How do I test a method that doesn't + return anything?</a></li> + <li><a href="#tests_5">Under what conditions should I test get() + and set() methods?</a></li> + <li><a href="#tests_6">Under what conditions should I not test + get() and set() methods?</a></li> + <li><a href="#tests_7">How do I write a test that passes when an + expected exception is thrown?</a></li> + <li><a href="#tests_8">How do I write a test that fails when an + unexpected exception is thrown?</a></li> + <li><a href="#tests_10">How do I test protected methods?</a></li> + <li><a href="#tests_11">How do I test private methods?</a></li> + <li><a href="#tests_12">Why does JUnit only report the first + failure in a single test?</a></li> + <li><a href="#tests_13">In Java 1.4, 'assert' is a + keyword. Won't this conflict with JUnit's assert() + method?</a></li> + <li><a href="#tests_14">How do I test things that must be run in + a J2EE container (e.g. servlets, EJBs)?</a></li> + <li><a href="#tests_15">Do I need to write a test class for + every class I need to test?</a></li> + <li><a href="#tests_16">Is there a basic template I can use to + create a test?</a></li> + <li><a href="#tests_17">How do I write a test for an abstract + class?</a></li> + <li><a href="#tests_18">When are tests garbage collected?</a></li> + </ol> + </li> + <li> + <p> + <b><a href="#organize">Organizing Tests</a></b> + </p> + <ol> + <li><a href="#organize_1">Where should I put my test files?</a></li> + <li><a href="#organize_3">How can I run setUp() and tearDown() + code once for all of my tests?</a></li> + </ol> + </li> + <li> + <p> + <b><a href="#running">Running Tests</a></b> + </p> + <ol> + <li><a href="#running_1">What CLASSPATH settings are needed to + run JUnit?</a></li> + <li><a href="#running_2">Why do I get a NoClassDefFoundError + when trying to test JUnit or run the samples?</a> + </li> + <li><a href="#running_4">How do I run JUnit from my command window?</a> + </li> + <li><a href="#running_5">How do I run JUnit using Ant?</a> + </li> + <li><a href="#running_6">How do I use Ant to create HTML test reports?</a> + </li> + <li><a href="#running_7">How do I pass command-line arguments to a test execution?</a> + </li> + <li><a href="#running_9">Why do I get a LinkageError when using + XML interfaces in my test class?</a> + </li> + <li><a href="#running_11">Why do I get the warning "AssertionFailedError: No + tests found in XXX" when I run my test?</a> + </li> + <li><a href="#running_12">Why do I see "Unknown Source" in the stack trace of + a test failure, rather than the source file's line number?</a> + </li> + <li><a href="#running_15">How do I organize all test classes in a TestSuite + automatically and not use or manage a TestSuite explicitly?</a> + </li> + </ol> + </li> + <li> + <p> + <b><a href="#best">Best Practices</a></b> + </p> + <ol> + <li><a href="#best_1">When should tests be written?</a></li> + <li><a href="#best_2">Do I have to write a test for + everything?</a></li> + <li><a href="#best_3">How simple is 'too simple to break'?</a></li> + <li><a href="#best_4">How often should I run my tests?</a></li> + <li><a href="#best_5">What do I do when a defect is reported?</a></li> + <li><a href="#best_6">Why not just use System.out.println()?</a></li> + <li><a href="#best_7">Why not just use a debugger?</a></li> + </ol> + </li> + <li> + <p> + <b><a href="#misc">Miscellaneous</a></b> + </p> + <ol> + <li><a href="#misc_1">How do I integrate JUnit with my IDE?</a></li> + <li><a href="#misc_2">How do I launch a debugger when a test + fails?</a></li> + <li><a href="#misc_3">Where can I find unit testing frameworks + similar to JUnit for other languages?</a></li> + </ol> + </li> + </ol> + +<!-- + + FAQ Info + +--> +<div class="header"> +<a name="faqinfo">FAQ Info</a> +</div> +<ol> + <li> + <p> + <b><a name="faqinfo_1">Who is responsible for this FAQ?</a></b> + </p> + <p> + The current version of this FAQ is maintained + by <a href="mailto:mike@clarkware.com">Mike Clark</a>. + </p> + <p> + Most of the wisdom contained in this FAQ comes from the + collective insights and hard-won experiences of the many good + folks who participate on the JUnit mailing list and the JUnit + community at large. + </p> + <p> + If you see your genius represented anywhere in this FAQ without + due credit to you, please send me an email and I'll make things + right. + </p> + </li> + <li> + <p> + <b><a name="faqinfo_2">How can I contribute to this FAQ?</a></b> + </p> + <p> + Your contributions to this FAQ are greatly appreciated! The + JUnit community thanks you in advance. + </p> + <p> + To contribute to this FAQ, simply write a JUnit-related question + and answer, then send the unformatted text + to <a href="mailto:mike@clarkware.com">Mike Clark</a>. + Corrections to this FAQ are always appreciated, as well. + </p> + <p> + No reasonable contribution will be denied. Your name will + always appear along with any contribution you make. + </p> + </li> + <li> + <p> + <b><a name="faqinfo_3">Where do I get the latest version of this + FAQ?</a></b> + </p> + <p> + The master copy of this FAQ is available + at <a + href="http://junit.sourceforge.net/doc/faq/faq.htm">http://junit.sourceforge.net/doc/faq/faq.htm</a>. + </p> + <p> + The JUnit distribution also includes this FAQ in + the <code>doc</code> directory. + </p> + </li> + +</ol> + + +<!-- + + Overview + +--> +<div class="header"> +<a name="overview">Overview</a> +</div> +<ol> + <li> + <p> + <b><a name="overview_1">What is JUnit?</a></b> + </p> + <p> + JUnit is a simple, open source framework to write and run + repeatable tests. It is an instance of the xUnit architecture + for unit testing frameworks. JUnit features include: + </p> + <ul> + <li>Assertions for testing expected results</li> + <li>Test fixtures for sharing common test data</li> + <li>Test runners for running tests</li> + </ul> + <p> + JUnit was originally written by Erich Gamma and Kent Beck. + </p> + </li> + <li> + <p> + <b><a name="overview_2">Where is the JUnit home page?</a></b> + </p> + <p> + The official JUnit home page is <a + href="http://junit.org">http://junit.org</a>. + </p> + </li> + <li> + <p> + <b><a name="overview_3">Where are the JUnit mailing lists and + forums?</a></b> + </p> + <p> + There are 3 mailing lists dedicated to everything JUnit: + </p> + <ul> + <li> + <a href="http://groups.yahoo.com/group/junit/">JUnit user + list</a>. (Search it for answers to frequently asked + questions not included here.) + </li> + <li> + <a + href="http://lists.sourceforge.net/lists/listinfo/junit-announce">JUnit + announcements</a> + </li> + <li> + <a + href="http://lists.sourceforge.net/lists/listinfo/junit-devel">JUnit + developer list</a> + </li> + </ul> + </li> + <li> + <p> + <b><a name="overview_4">Where is the JUnit + documentation?</a></b> + </p> + <p> + The following documents are included in the JUnit distribution + in the <code>doc</code> directory: + </p> + <ul> + <li> + <a + href="http://junit.sourceforge.net/doc/testinfected/testing.htm">JUnit + Test Infected: Programmers Love Writing Tests</a> + </li> + <li> + <a + href="http://junit.sourceforge.net/doc/cookbook/cookbook.htm">JUnit + Cookbook</a> + </li> + <li> + <a + href="http://junit.sourceforge.net/doc/cookstour/cookstour.htm">JUnit + - A Cook's Tour</a> + </li> + <li> + <a href="http://junit.sourceforge.net/doc/faq/faq.htm">JUnit + FAQ</a> + </li> + </ul> + </li> + <li> + <p> + <b><a name="overview_5">Where can I find articles on + JUnit?</a></b> + </p> + <p> + The JUnit home page maintains a list + of <a href="http://www.junit.org/news/article/index.htm">JUnit + articles</a>. + </p> + </li> + <li> + <p> + <b><a name="overview_6">What's the latest news on JUnit?</a></b> + </p> + <p> + The JUnit home page publishes + the <a href="http://www.junit.org/news/index.htm">latest JUnit + news</a>. + </p> + </li> + <li> + <p> + <b><a name="overview_7">How is JUnit licensed?</a></b> + </p> + <p> + JUnit is <a href="http://www.opensource.org/">Open Source + Software</a>, released + under <a + href="http://oss.software.ibm.com/developerworks/oss/license-cpl.html">IBM's + Common Public License Version 0.5</a> and hosted + on <a + href="http://sourceforge.net/projects/junit/">SourceForge</a>. + </p> + </li> + <li> + <p> + <b><a name="overview_8">What awards has JUnit won?</a></b> + </p> + <ul> + <li> + <p> <a + href="http://www.javaworld.com/javaworld/jw-03-2002/jw-0326-awards.html">2002 + JavaWorld Editors' Choice Awards (ECA)</a> + </p> + <p> + Best Java Performance Monitoring/Testing Tool + </p> + </li> + <li> + <p> + <a + href="http://www.javaworld.com/javaworld/jw-06-2001/j1-01-awards.html">2001 + JavaWorld Editors' Choice Awards (ECA)</a> + </p> + <p> + Best Java Performance Monitoring/Testing Tool + </p> + </li> + </ul> + </li> +</ol> + + +<!-- + + Getting Started + +--> +<div class="header"> +<a name="started">Getting Started</a> +</div> +<ol> + <li> + <p> + <b><a name="started_1">Where do I download JUnit?</a></b> + </p> + <p> + The latest version of JUnit is available + on <a + href="http://sourceforge.net/project/showfiles.php?group_id=15278">SourceForge</a>. + </p> + </li> + <li> + <p> + <b><a name="started_2">How do I install JUnit?</a></b> + </p> + <ol> + <li> + <p> + First, <a + href="http://sourceforge.net/project/showfiles.php?group_id=15278">download</a> + the + latest version of JUnit, referred to below + as <code>junit.zip</code>. + </p> + </li> + <li> + <p> + Then install JUnit on your platform of choice: + </p> + <p> + <u>Windows</u> + </p> + <p> + To install JUnit on Windows, follow these steps: + </p> + <ol> + <li> + <p> + Unzip the <code>junit.zip</code> distribution file to + a directory referred to as <code>%JUNIT_HOME%</code>. + </p> + </li> + <li>Add JUnit to the classpath: + <p> + <code>set CLASSPATH=%CLASSPATH%;%JUNIT_HOME%\junit.jar</code> + </p> + </li> + </ol> + <p> + <u>Unix (bash)</u> + </p> + <p> + To install JUnit on Unix, follow these steps: + </p> + <ol> + <li> + <p> + Unzip the <code>junit.zip</code> distribution file to + a directory referred to as <code>$JUNIT_HOME</code>. + </p> + </li> + <li> + <p> + Add JUnit to the classpath: + </p> + <p> + <code>export CLASSPATH=$CLASSPATH:$JUNIT_HOME/junit.jar</code> + </p> + </li> + </ol> + </li> + <li> + <p> + <i>(Optional)</i> Unzip + the <code>$JUNIT_HOME/src.jar</code> file. + </p> + </li> + <li> + <p> + Test the installation by running the sample tests + distributed with JUnit. Note that the sample tests are + located in the installation directory directly, not + the <code>junit.jar</code> file. Therefore, make sure that + the JUnit installation directory is on your CLASSPATH. Then + simply type: + </p> + <div> + <blockquote><code> + java org.junit.runner.JUnitCore org.junit.tests.AllTests + </code></blockquote> + </div> + <p> + All the tests should pass with an "OK" message. + </p> + <p> + <i> + If the tests don't pass, verify + that <code>junit.jar</code> is in the CLASSPATH. + </i> + </p> + </li> + <li> + <p> + Finally, <a href="#overview_4">read</a> the documentation. + </p> + </li> + </ol> + </li> + <li> + <p> + <b><a name="started_3">How do I uninstall JUnit?</a></b> + </p> + <ol> + <li> + <p> + Delete the directory structure where you unzipped the JUnit + distribution. + </p> + </li> + <li> + <p> + Remove <code>junit.jar</code> from the CLASSPATH. + </p> + </li> + </ol> + <p> + JUnit does not modify the registry so simply removing all the + files will fully uninstall it. + </p> + </li> + <li> + <p> + <b><a name="started_4">How do I ask questions?</a></b> + </p> + <p> + Questions that are not answered in + the <a + href="http://junit.sourceforge.net/doc/faq/faq.htm">FAQ</a> or + in the <a href="#overview_4">documentation</a> should be posted + to + the <a + href="http://www.jguru.com/forums/home.jsp?topic=JUnit">jGuru + discussion forum</a> or the <a + href="http://groups.yahoo.com/group/junit/">JUnit user mailing + list</a>. + </p> + <p> + Please stick to technical issues on the discussion forum and + mailing lists. Keep in mind that these are public, so + do <b>not</b> include any confidental information in your + questions! + </p> + <p> + You should also + read <a + href="http://www.catb.org/~esr/faqs/smart-questions.html">"How + to ask questions the smart way"</a> by Eric Raymond before + participating in the discussion forum and mailing lists. + </p> + <p> + <i> + NOTE: <br/> Please do NOT submit bugs, patches, or feature + requests to the discussion forum or mailing lists. <br/> + Refer instead to <a href="#started_5">"How do I submit bugs, + patches, or feature requests?"</a>. + </i> + </p> + </li> + <li> + <p> + <b><a name="started_5">How do I submit bugs, patches, or + feature requests?</a></b> + </p> + <p> + JUnit celebrates programmers testing their own software. In this + spirit, bugs, patches, and feature requests that include JUnit + tests have a better chance of being addressed than those + without. + </p> + <p> + JUnit is hosted + on <a + href="http://sourceforge.net/projects/junit">SourceForge</a>. + Please use the tools provided by SourceForge for your + submissions. + </p> + </li> +</ol> + + +<!-- + + Writing Tests + +--> +<div class="header"> +<a name="tests">Writing Tests</a> +</div> +<ol> + <li> + <p> + <b><a name="tests_1"></a>How do I write and run a simple test?</b> + </p> + <ol> + <li> + <p> + Create a class: + </p> + <div class="code"> + <pre><code> + + package junitfaq; + + import org.junit.*; + import static org.junit.Assert.*; + + import java.util.*; + + public class SimpleTest { + </code></pre> + </div> + </li> + <li> + <p> + Write a test method (annotated with <code>@Test</code>) that + asserts expected results on the object under test: + </p> + <div class="code"> + <pre><code> + + @Test + public void testEmptyCollection() { + Collection collection = new ArrayList(); + assertTrue(collection.isEmpty()); + } + </code></pre> + </div> + </li> + <li> + <p> + If you are running your JUnit 4 tests with a JUnit 3.x runner, + write a <code>suite()</code> method that uses the + <code>JUnit4TestAdapter</code> class to create a suite + containing all of your test methods: + </p> + <div class="code"> + <pre><code> + + public static junit.framework.Test suite() { + return new junit.framework.JUnit4TestAdapter(SimpleTest.class); + } + </code></pre> + </div> + </li> + <li> + <p> + Although writing a <code>main()</code> method to run the + test is much less important with the advent of IDE runners, + it's still possible: + </p> + <div class="code"> + <pre><code> + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main("junitfaq.SimpleTest"); + } + } + </code></pre> + </div> + </li> + <li> + <p> + Run the test: + </p> + <ul> + <li> + <p> + To run the test from the console, type: + </p> + <div> + <blockquote><code> +java org.junit.runner.JUnitCore junitfaq.SimpleTest + </code></blockquote> + </div> + </li> + <li> + <p> + To run the test with the test runner used + in <code>main()</code>, type: + </p> + <div> + <blockquote><code> +java junitfaq.SimpleTest + </code></blockquote> + </div> + </li> + </ul> + <p> + The passing test results in the following textual output: + </p> + <div> + <blockquote> + <pre><code> + . +Time: 0 + +OK (1 tests) + </code></pre> + </blockquote> + </div> + </li> + </ol> + </li> + <li> + <p> + <b><a name="tests_2"></a>How do I use a test fixture?</b> + </p> + <p> + <i>(Submitted by: Jeff Nielsen)</i> + </p> + <p> + A test fixture is useful if you have two or more tests for a + common set of objects. Using a test fixture avoids duplicating + the code necessary to initialize (and cleanup) the common + objects. + </p> + <p> + Tests can use the objects (variables) in a test fixture, with + each test invoking different methods on objects in the fixture + and asserting different expected results. Each test runs in its + own test fixture to isolate tests from the changes made by other + tests. That is, <em>tests don't share the state of objects in + the test fixture</em>. Because the tests are isolated, they can + be run in any order. + </p> + <p> + To create a test fixture, declare instance variables for the + common objects. Initialize these objects in a <code>public + void</code> method annotated with <code>@Before</code>. The + JUnit framework automatically invokes any <code>@Before</code> + methods before each test is run. + </p> + <p> + The following example shows a test fixture with a common + <code>Collection</code> object. + </p> + <div class="code"> + <pre><code> + package junitfaq; + + import org.junit.*; + import static org.junit.Assert.*; + import java.util.*; + + public class SimpleTest { + + private Collection<Object> collection; + + @Before + public void setUp() { + collection = new ArrayList<Object>(); + } + + @Test + public void testEmptyCollection() { + assertTrue(collection.isEmpty()); + } + + + @Test + public void testOneItemCollection() { + collection.add("itemA"); + assertEquals(1, collection.size()); + } + } + </code></pre> + </div> + + <p> + Given this test, the methods might execute in the following + order: + </p> + <blockquote> + <pre><code>setUp() +testEmptyCollection() +setUp() +testOneItemCollection()</code></pre> + </blockquote> + <p> + The ordering of test-method invocations is not guaranteed, so + <code>testOneItemCollection()</code> might be executed before + <code>testEmptyCollection()</code>. But it doesn't matter, + because each method gets its own instance of the + <code>collection</code>. + </p> + + <p> + Although JUnit provides a new instance of the fixture objects + for each test method, if you allocate any <em>external</em> + resources in a <code>@Before</code> method, you should release + them after the test runs by annotating a method with + <code>@After</code>. The JUnit framework automatically invokes + any <code>@After</code> methods after each test is run. For + example: + </p> + + <div class="code"> + <pre><code> + package junitfaq; + + import org.junit.*; + import static org.junit.Assert.*; + import java.io.*; + + public class OutputTest { + + private File output; + + @Before + public void createOutputFile() { + output = new File(...); + } + + @After + public void deleteOutputFile() { + output.delete(); + } + + @Test + public void testSomethingWithFile() { + ... + } + } + </code></pre> + </div> + <p> + With this test, the methods will execute in the following order: + </p> + <div> + <blockquote> + <pre><code> +createOutputFile() +testSomethingWithFile() +deleteOutputFile() + </code></pre> + </blockquote> + </div> + + </li> + <li> + <p> + <b><a name="tests_4"></a>How do I test a method that doesn't + return anything?</b> + </p> + <p> + <i>(Submitted by: Dave Astels)</i> + </p> + <p> + Often if a method doesn't return a value, it will have some side + effect. Actually, if it doesn't return a value AND doesn't have + a side effect, it isn't doing anything. + </p> + <p> + There may be a way to verify that the side effect actually + occurred as expected. For example, consider + the <code>add()</code> method in the Collection classes. There + are ways of verifying that the side effect happened (i.e. the + object was added). You can check the size and assert that it is + what is expected: + </p> + <div class="code"> + <pre><code> + + @Test + public void testCollectionAdd() { + Collection collection = new ArrayList(); + assertEquals(0, collection.size()); + collection.add("itemA"); + assertEquals(1, collection.size()); + collection.add("itemB"); + assertEquals(2, collection.size()); + } + </code></pre> + </div> + <p> + Another approach is to make use of <a + href="http://www.mockobjects.com">MockObjects</a>. + </p> + <p> + A related issue is to design for testing. For example, if you + have a method that is meant to output to a file, don't pass in a + filename, or even a <code>FileWriter</code>. Instead, pass in + a <code>Writer</code>. That way you can pass in + a <code>StringWriter</code> to capture the output for testing + purposes. Then you can add a method + (e.g. <code>writeToFileNamed(String filename)</code>) to + encapsulate the <code>FileWriter</code> creation. + </p> + </li> + <li> + <p> + <b><a name="tests_5"></a>Under what conditions should I test + get() and set() methods?</b> + </p> + <p> + Unit tests are intended to alleviate fear that something might + break. If you think a <code>get()</code> or <code>set()</code> + method could reasonably break, or has in fact contributed to a + defect, then by all means write a test. + </p> + <p> + In short, test until you're confident. What you choose to test + is subjective, based on your experiences and confidence level. + Remember to be practical and maximize your testing investment. + </p> + <p> + Refer also to <a href="#best_3">"How simple is 'too simple to + break'?"</a>. + </p> + </li> + <li> + <p> + <b><a name="tests_6"></a>Under what conditions should I not test + get() and set() methods?</b> + </p> + <p> + <i>(Submitted by: J. B. Rainsberger)</i> + </p> + <p> + Most of the time, get/set methods just can't break, and if they + can't break, then why test them? While it is usually better to + test more, there is a definite curve of diminishing returns on + test effort versus "code coverage". Remember the maxim: "Test + until fear turns to boredom." + </p> + <p> + Assume that the <code>getX()</code> method only does "return x;" + and that the <code>setX()</code> method only does "this.x = + x;". If you write this test: + </p> + <div> + <blockquote><pre> +@Test +public void testGetSetX() { + setX(23); + assertEquals(23, getX()); +} + </pre></blockquote> + </div> + <p> + then you are testing the equivalent of the following: + </p> + <div> + <blockquote><pre> +@Test +public void testGetSetX() { + x = 23; + assertEquals(23, x); +} +</pre></blockquote> + </div> + <p> + or, if you prefer, + </p> + <div> + <blockquote><pre> +@Test +public void testGetSetX() { + assertEquals(23, 23); +} +</pre></blockquote> + </div> + <p> + At this point, you are testing the Java compiler, or possibly + the interpreter, and not your component or application. There is + generally no need for you to do Java's testing for them. + </p> + <p> + If you are concerned about whether a property has already been + set at the point you wish to call <code>getX()</code>, then you + want to test the constructor, and not the <code>getX()</code> + method. This kind of test is especially useful if you have + multiple constructors: + </p> + <div> + <blockquote><pre> +@Test +public void testCreate() { + assertEquals(23, new MyClass(23).getX()); +} + </pre></blockquote> + </div> + </li> + <li> + <p> + <b><a name="tests_7"></a>How do I write a test that passes when + an expected exception is thrown?</b> + </p> + <p> + Add the optional <code>expected</code> attribute to + the <code>@Test</code> annotation. The following is an example + test that passes when the + expected <code>IndexOutOfBoundsException</code> is raised: + </p> + <div class="code"> + <pre><code> + + @Test(expected=IndexOutOfBoundsException.class) + public void testIndexOutOfBoundsException() { + ArrayList emptyList = new ArrayList(); + Object o = emptyList.get(0); + } + </code></pre> + </div> + </li> + <li> + <p> + <b><a name="tests_8"></a>How do I write a test that fails when + an unexpected exception is thrown?</b> + </p> + <p> + Declare the exception in the <code>throws</code> clause of the + test method and don't catch the exception within the test + method. Uncaught exceptions will cause the test to fail with an + error. + </p> + <p> + The following is an example test that fails when + the <code>IndexOutOfBoundsException</code> is raised: + </p> + <div class="code-red"> + <pre><code> + + @Test + public void testIndexOutOfBoundsExceptionNotRaised() + throws IndexOutOfBoundsException { + + ArrayList emptyList = new ArrayList(); + Object o = emptyList.get(0); + } + </code></pre> + </div> + </li> + <li> + <p> + <b><a name="tests_10"></a>How do I test protected methods?</b> + </p> + <p> + Place your tests in the same package as the classes under test. + </p> + <p> + Refer to <a href="#organize_1">"Where should I put my test + files?"</a> for examples of how to organize tests for protected + method access. + </p> + </li> + <li> + <p> + <b><a name="tests_11"></a>How do I test private methods?</b> + </p> + <p> + Testing private methods may be an indication that those methods + should be moved into another class to promote reusability. + </p> + <p> + But if you must... + </p> + <p> + If you are using JDK 1.3 or higher, you can use reflection to + subvert the access control mechanism with the aid of + the <a + href="http://sourceforge.net/projects/privaccessor/">PrivilegedAccessor</a>. + For details on how to use it, + read <a + href="http://www.onjava.com/pub/a/onjava/2003/11/12/reflection.html">this + article</a>. + </p> + </li> + <li> + <p> + <b><a name="tests_12"></a>Why does JUnit only report the first + failure in a single test?</b> + </p> + <p> + <i>(Submitted by: J. B. Rainsberger)</i> + </p> + <p> + Reporting multiple failures in a single test is generally a sign + that the test does too much, compared to what a unit test ought + to do. Usually this means either that the test is really a + functional/acceptance/customer test or, if it is a unit test, + then it is too big a unit test. + </p> + <p> + JUnit is designed to work best with a number of small tests. It + executes each test within a separate instance of the test + class. It reports failure on each test. Shared setup code is + most natural when sharing between tests. This is a design + decision that permeates JUnit, and when you decide to report + multiple failures per test, you begin to fight against + JUnit. This is not recommended. + </p> + <p> + Long tests are a design smell and indicate the likelihood of a + design problem. Kent Beck is fond of saying in this case that + "there is an opportunity to learn something about your design." + We would like to see a pattern language develop around these + problems, but it has not yet been written down. + </p> + <p> + Finally, note that a single test with multiple assertions is + isomorphic to a test case with multiple tests: + </p> + <p> + One test method, three assertions: + </p> + <div> + <blockquote><pre><code> +public class MyTestCase { + @Test + public void testSomething() { + // Set up for the test, manipulating local variables + assertTrue(condition1); + assertTrue(condition2); + assertTrue(condition3); + } +} + </code></pre></blockquote> + </div> + <p> + Three test methods, one assertion each: + </p> + <div> + <blockquote><pre><code> +public class MyTestCase { + // Local variables become instance variables + + @Before + public void setUp() { + // Set up for the test, manipulating instance variables + } + + @Test + public void testCondition1() { + assertTrue(condition1); + } + + @Test + public void testCondition2() { + assertTrue(condition2); + } + + @Test + public void testCondition3() { + assertTrue(condition3); + } +} + </code></pre></blockquote> + </div> + <p> + The resulting tests use JUnit's natural execution and reporting + mechanism and, failure in one test does not affect the execution + of the other tests. You generally want exactly one test to fail + for any given bug, if you can manage it. + </p> + </li> + <li> + <p> + <b><a name="tests_13"></a>In Java 1.4, <code>assert</code> is a + keyword. Won't this conflict + with JUnit's <code>assert()</code> method?</b> + </p> + <p> + JUnit 3.7 deprecated <code>assert()</code> and replaced it + with <code>assertTrue()</code>, which works exactly the same + way. + </p> + <p> + JUnit 4 is compatible with the <code>assert</code> keyword. If + you run with the <code>-ea</code> JVM switch, assertions that + fail will be reported by JUnit. + </p> + </li> + <li> + <p> + <b><a name="tests_14"></a>How do I test things that must be run + in a J2EE container (e.g. servlets, EJBs)?</b> + </p> + <p> + Refactoring J2EE components to delegate functionality to other + objects that don't have to be run in a J2EE container will + improve the design and testability of the software. + </p> + <p> + <a href="http://jakarta.apache.org/cactus/index.html">Cactus</a> + is an open source JUnit extension that can be used to test J2EE + components in their natural environment. + </p> + </li> + <li> + <p> + <b><a name="tests_15"></a>Do I need to write + a test class for every class I need to + test?</b> + </p> + <p> + <i>(Submitted by: J. B. Rainsberger)</i> + </p> + <p> + No. It is a convention to start with one test + class per class under test, but it is not necessary. + </p> + <p> + Test classes only provide a way to organize tests, nothing more. + Generally you will start with one test class per class under + test, but then you may find that a small group of tests belong + together with their own common test fixture.[1] In this case, + you may move those tests to a new test class. This is a simple + object-oriented refactoring: separating responsibilities of an + object that does too much. + </p> + <p> + Another point to consider is that the <code>TestSuite</code> is + the smallest execution unit in JUnit: you cannot execute + anything smaller than a TestSuite at one time without changing + source code. In this case, you probably do not want to put tests + in the same test class unless they somehow "belong together". + If you have two groups of tests that you think you'd like to + execute separately from one another, it is wise to place them in + separate test classes. + </p> + <p> + <i> + [1] A test fixture is a common set of test data and + collaborating objects shared by many tests. Generally they are + implemented as instance variables in the test class. + </i> + </p> + </li> + <li> + <p> + <b><a name="tests_16"></a>Is there a basic template I can use to + create a test?</b> + </p> + <p> + <i>(Submitted by: Eric Armstrong)</i> + </p> + <p> + The following templates are a good starting point. Copy/paste + and edit these templates to suit your coding style. + </p> + <p> + SampleTest is a basic test template: + </p> + <div> + <blockquote><pre><code> +import org.junit.*; +import static org.junit.Assert.*; + +public class SampleTest { + + private java.util.List emptyList; + + /** + * Sets up the test fixture. + * (Called before every test case method.) + */ + @Before + public void setUp() { + emptyList = new java.util.ArrayList(); + } + + /** + * Tears down the test fixture. + * (Called after every test case method.) + */ + @After + public void tearDown() { + emptyList = null; + } + + @Test + public void testSomeBehavior() { + assertEquals("Empty list should have 0 elements", 0, emptyList.size()); + } + + @Test(expected=IndexOutOfBoundsException.class) + public void testForException() { + Object o = emptyList.get(0); + } +} + </code></pre></blockquote> + </div> + </li> + <li> + <p> + <b><a name="tests_17"></a>How do I write a test for an abstract + class?</b> + </p> + <p> + Refer to <a + href="http://c2.com/cgi/wiki?AbstractTestCases">http://c2.com/cgi/wiki?AbstractTestCases</a>. + </p> + </li> + <li> + <p> + <b><a name="tests_18"></a>When are tests garbage collected?</b> + </p> + <p> + <i>(Submitted by: Timothy Wall and Kent Beck)</i> + </p> + <p> + By design, the tree of Test instances is built in one pass, then + the tests are executed in a second pass. The test runner holds + strong references to all Test instances for the duration of the + test execution. This means that for a very long test run with + many Test instances, none of the tests may be garbage collected + until the end of the entire test run. + </p> + <p> + Therefore, if you allocate external or limited resources in a + test, you are responsible for freeing those resources. + Explicitly setting an object to <code>null</code> in + the <code>tearDown()</code> method, for example, allows it to be + garbage collected before the end of the entire test run. + </p> + </li> +</ol> + + +<!-- + + Organizing Tests + +--> +<div class="header"> +<a name="organize">Organizing Tests</a> +</div> +<ol> + <li> + <p> + <b><a name="organize_1"></a>Where should I put my test files?</b> + </p> + <p> + You can place your tests in the same package and directory as + the classes under test. + </p> + <p> + For example: + </p> + <div> + <blockquote><pre> +src + com + xyz + SomeClass.java + SomeClassTest.java + </pre></blockquote> + </div> + <p> + While adequate for small projects, many developers feel that + this approach clutters the source directory, and makes it hard + to package up client deliverables without also including + unwanted test code, or writing unnecessarily complex packaging + tasks. + </p> + <p> + An arguably better way is to place the tests in a separate + parallel directory structure with package alignment. + </p> + <p> + For example: + </p> + <div> + <blockquote><pre> +src + com + xyz + SomeClass.java +test + com + xyz + SomeClassTest.java + </pre></blockquote> + </div> + <p> + These approaches allow the tests to access to all the public and + package visible methods of the classes under test. + </p> + <p> + Some developers have argued in favor of putting the tests in a + sub-package of the classes under test (e.g. com.xyz.test). The + author of this FAQ sees no clear advantage to adopting this + approach and believes that said developers also put their curly + braces on the wrong line. :-) + </p> + </li> + <li> + <p> + <b><a name="organize_3"></a>How can I run setUp() and tearDown() + code once for all of my tests?</b> + </p> + <p> + The desire to do this is usually a symptom of excessive coupling + in your design. If two or more tests must share the same test + fixture state, then the tests may be trying to tell you that the + classes under test have some undesirable dependencies. + </p> + <p> + Refactoring the design to further decouple the classes under + test and eliminate code duplication is usually a better + investment than setting up a shared test fixture. + </p> + <p> + But if you must... + </p> + <p> + You can add a <code>@BeforeClass</code> annotation to a method + to be run before all the tests in a class, and + a <code>@AfterClass</code> annotation to a method to be run + after all the tests in a class. Here's an example: + </p> + <div class="code"> + <pre><code> + + package junitfaq; + + import org.junit.*; + import static org.junit.Assert.*; + import java.util.*; + + public class SimpleTest { + + private Collection collection; + + @BeforeClass + public static void oneTimeSetUp() { + // one-time initialization code + } + + @AfterClass + public static void oneTimeTearDown() { + // one-time cleanup code + } + + @Before + public void setUp() { + collection = new ArrayList(); + } + + @After + public void tearDown() { + collection.clear(); + } + + @Test + public void testEmptyCollection() { + assertTrue(collection.isEmpty()); + } + + @Test + public void testOneItemCollection() { + collection.add("itemA"); + assertEquals(1, collection.size()); + } + } + </code></pre> + </div> + <p> + Given this test, the methods will execute in the following + order: + </p> + <div> + <blockquote> + <pre><code> +oneTimeSetUp() +setUp() +testEmptyCollection() +tearDown() +setUp() +testOneItemCollection() +tearDown() +oneTimeTearDown() + </code></pre> + </blockquote> + </div> + + </li> +</ol> + + +<!-- + + Running Tests + +--> +<div class="header"> +<a name="running">Running Tests</a> +</div> +<ol> + <li> + <p> + <b><a name="running_1"></a>What CLASSPATH settings are needed to + run JUnit?</b> + </p> + <p> + <i>(Submitted by: Eric Armstrong)</i> + </p> + <p> + To run your JUnit tests, you'll need the following elemements in + your CLASSPATH: + </p> + <ul> + <li>JUnit class files</li> + <li>Your class files, including your JUnit test classes</li> + <li>Libraries your class files depend on</li> + </ul> + <p> + If attempting to run your tests results in + a <code>NoClassDefFoundError</code>, then something is missing + from your CLASSPATH. + </p> + <p> + <u>Windows Example:</u> + </p> + <p> + <code>set + CLASSPATH=%JUNIT_HOME%\junit.jar;c:\myproject\classes;c:\myproject\lib\something.jar</code> + </p> + <p> + <u>Unix (bash) Example:</u> + </p> + <p> + <code>export CLASSPATH=$JUNIT_HOME/junit.jar:/myproject/classes:/myproject/lib/something.jar</code> + </p> + </li> + <li> + <p> + <b><a name="running_2"></a>Why do I get + a <code>NoClassDefFoundError</code> when trying to test JUnit + or run the samples?</b> + </p> + <p> + <i>(Submitted by: J.B. Rainsberger and Jason Rogers)</i> + </p> + <p> + Most likely your CLASSPATH doesn't include the JUnit + installation directory. + </p> + <p> + Refer to <a href="#running_1">"What CLASSPATH settings are + needed to run JUnit?"</a> for more guidance. + </p> + <p> + Also consider running <a + href="http://www.clarkware.com/software/WhichJUnit.zip">WhichJunit</a> + to print the absolute location of the JUnit class files required + to run and test JUnit and its samples. + </p> + <p> + If the CLASSPATH seems mysterious, read <a + href="http://java.sun.com/j2se/1.4/docs/tooldocs/findingclasses.html">this</a>! + </p> + </li> + <li> + <p> + <b><a name="running_4"></a>How do I run JUnit from my command window?</b> + </p> + <p> + <i>(Submitted by: Eric Armstrong)</i> + </p> + <ol> + <li> + <p> + <a href="#running_1">Set your CLASSPATH</a> + </p> + </li> + <li> + <p> + Invoke the runner: + </p> + <p> + <code> + java org.junit.runner.JUnitCore <test class name> + </code> + </p> + </li> + </ol> + </li> + <li> + <p> + <b><a name="running_5"></a>How do I run JUnit using Ant?</b> + </p> + <p> + <i>(Submitted by: Eric Armstrong)</i> + </p> + <ol> + <li> + <p> + Define any necessary Ant properties: + </p> + <div> + <pre><code> +<property name="src" value="./src" /> +<property name="lib" value="./lib" /> +<property name="classes" value="./classes" /> +<property name="test.class.name" value="com.xyz.MyTestSuite" /> + </code></pre> + </div> + </li> + <li> + <p> + Set up the CLASSPATH to be used by JUnit: + </p> + <div> + <pre><code> +<path id="test.classpath"> + <pathelement location="${classes}" /> + <pathelement location="/path/to/junit.jar" /> + <fileset dir="${lib}"> + <include name="**/*.jar"/> + </fileset> +</path> + </code></pre> + </div> + </li> + <li> + <p> + Define the Ant task for running JUnit: + </p> + <div> + <pre><code> +<target name="test"> + <junit fork="yes" haltonfailure="yes"> + <test name="${test.class.name}" /> + <formatter type="plain" usefile="false" /> + <classpath refid="test.classpath" /> + </junit> +</target> + </code></pre> + </div> + </li> + <li> + <p> + Run the test: + </p> + <div> + <code> + ant test + </code> + </div> + </li> + </ol> + <p> + Refer to the <a + href="http://jakarta.apache.org/ant/manual/OptionalTasks/junit.html">JUnit + Ant Task</a> for more information. + </p> + </li> + <li> + <p> + <b><a name="running_6"></a>How do I use Ant to create HTML test + reports?</b> + </p> + <p> + <i>(Submitted by: Eric Armstrong and Steffen Gemkow)</i> + </p> + <ol> + <li> + <p> + Ensure that Ant's <code>optional.jar</code> file is either + in your CLASSPATH or exists in + your <code>$ANT_HOME/lib</code> directory. + </p> + </li> + <li> + <p> + Add an ANT property for the directory containing the HTML reports: + </p> + <div> + <code> +<property name="test.reports" value="./reports" /> + </code> + </div> + </li> + <li> + <p> + Define the Ant task for running JUnit and generating reports: + </p> + <div> + <pre><code> +<target name="test-html"> + <junit fork="yes" printsummary="no" haltonfailure="no"> + <batchtest fork="yes" todir="${test.reports}" > + <fileset dir="${classes}"> + <include name="**/*Test.class" /> + </fileset> + </batchtest> + <formatter type="xml" /> + <classpath refid="test.classpath" /> + </junit> + + <junitreport todir="${test.reports}"> + <fileset dir="${test.reports}"> + <include name="TEST-*.xml" /> + </fileset> + <report todir="${test.reports}" /> + </junitreport> +</target> + </code></pre> + </div> + </li> + <li> + <p> + Run the test: + </p> + <div> + <code> + ant test-html + </code> + </div> + </li> + </ol> + <p> + Refer to the + <a href="http://jakarta.apache.org/ant/manual/OptionalTasks/junit.html">JUnit Ant Task</a> + for more information. + </p> + </li> + <li> + <p> + <b><a name="running_7"></a>How do I pass command-line arguments + to a test execution?</b> + </p> + <p> + Use the <tt>-D</tt> JVM command-line options, as in: + </p> + <div> + <blockquote><code> +-DparameterName=parameterValue + </code></blockquote> + </div> + <p> + If the number of parameters on the command line gets unweildy, + pass in the location of a property file that defines a set of + parameters. Alternatively, the <a + href="http://junit-addons.sf.net">JUnit-addons package</a> + contains the <tt>XMLPropertyManager</tt> + and <tt>PropertyManager</tt> classes that allow you to define a + property file (or XML file) containing test parameters. + </p> + </li> + <li> + <p> + <b><a name="running_9"></a>Why do I get + a <code>LinkageError</code> when using + XML interfaces in my test?</b> + </p> + <p> + <i>(Submitted by: Scott Stirling)</i> + </p> + <p> + The workaround as of JUnit 3.7 is to + add <code>org.w3c.dom.*</code> and <code>org.xml.sax.*</code> to + your <code>excluded.properties</code>. + </p> + <p> + It's just a matter of time before this fix becomes incorporated + into the released version of + JUnit's <code>excluded.properties</code>, since JAXP is a + standard part of JDK 1.4. It will be just like + excluding <code>org.omg.*</code>. By the way, if you download + the JUnit source from its Sourceforge CVS, you will find that + these patterns have already been added to the default + excluded.properties and so has a pattern for JINI. In fact, here + is the current version in CVS, which demonstrates how to add + exclusions to the list too: + </p> + <div> + <blockquote><pre> +# +# The list of excluded package paths for the TestCaseClassLoader +# +excluded.0=sun.* +excluded.1=com.sun.* +excluded.2=org.omg.* +excluded.3=javax.* +excluded.4=sunw.* +excluded.5=java.* +excluded.6=org.w3c.dom.* +excluded.7=org.xml.sax.* +excluded.8=net.jini.* + </pre></blockquote> + </div> + <p> + This is the most common case where the + default <code>excluded.properties</code> list needs + modification. The cause of the <code>LinkageError</code> is + related to using JAXP in your test cases. By JAXP I mean the + whole set of <code>javax.xml.*</code> classes and the + supporting <code>org.w3c.dom.*</code> + and <code>org.xml.sax.*</code> classes. + </p> + <p> + As stated above, the JUnit GUI TestRunners' classloader relies + on the <code>excluded.properties</code> for classes it should + delegate to the system classloader. JAXP is an unusual case + because it is a standard Java extension library dependent on + classes whose package names (<code>org.w3c.dom.*</code> + and <code>org.xml.sax.*</code>) do not begin with a standard + Java or Sun prefix. This is similar to the relationship + between <code>javax.rmi.*</code> and the <code>org.omg.*</code> + classes, which have been excluded by default in + JUnit'ss <code>excluded.properties</code> for a while. + </p> + <p> + What can happen, and frequently does when using the JUnit Swing + or AWT UI with test cases that reference, use or depend on JAXP + classes, such as Log4J, Apache SOAP, Axis, Cocoon, etc., is that + the JUnit class loader (properly) + delegates <code>javax.xml.*</code> classes it "sees" + to the system loader. But then the system loader, in the process + of initializing and loading that JAXP class, links and loads up + a bunch of <code>org.w3c.dom</code>/<code>org.xml.sax</code> + classes. When it does so, the JUnit custom classloader is not + involved at all because the system classloader never delegates + "down" or checks with custom classloaders to see if a + class is already loaded. At any point after this, if the JUnit + loader is asked to load + an <code>org.w3c.dom</code>/<code>org.xml.sax</code> class that + it's never seen before, it will try to load it because the + class' name doesn't match any of the patterns in the default + exclude list. That's when a <code>LinkageError</code> + occurs. This is really a flaw in the JUnit classloader design, + but there is the workaround given above. + </p> + <p> + Java 2 JVMs keep classes (remember, classes and objects, though + related, are different entities to the JVM - I'm talking + about classes here, not object instances) in namespaces, + identifying them by their fully qualified classname plus the + instance of their defining (not initiating) loader. The JVM will + attempt to assign all unloaded classes referenced by an already + defined and loaded class to that class's defining loader. The + JVM's classresolver routine (implemented as a C function in the + JVM source code) keeps track of all these class loading events + and "sees" if another classloader (such as the JUnit + custom loader) attempts to define a class that has already been + defined by the system loader. According to the rules of Java 2 + loader constraints, in case a class has already been defined by + the system loader, any attempts to load a class should first be + delegated to the system loader. A "proper" way for + JUnit to handle this feature would be to load classes from a + repository other than the CLASSPATH that the system classloader + knows nothing about. And then the JUnit custom classloader could + follow the standard Java 2 delegation model, which is to always + delegate class loading to the system loader, and only attempt to + load if that fails. Since they both load from the CLASSPATH in + the current model, if the JUnit loader delegated like it's + supposed to, it would never get to load any classes since the + system loader would always find them. + </p> + <p> + You could try to hack around this in the JUnit source by + catching the <code>LinkageError</code> in + TestCaseClassLoader's <code>loadClass()</code> method and then + making a recovery call to <code>findSystemClass()</code> -- + thereby delegating to the system loader after the violation has + been caught. But this hack only works some of the time, because + now you can have the reverse problem where the JUnit loader will + load a host of <code>org.w3c.dom</code>/<code>org.xml.sax</code> + classes, and then the system loader violates the loader + contraints at some point when it tries to do exactly what I + described above with JAXP because it doesn't ever delegate to + its logical child (the JUnit loader). Inevitably, if your test + cases use many JAXP and related XML classes, one or the other + classloader will end up violating the constraints whatever you + do. + </p> + </li> + <li> + <p> + <b><a name="running_11"></a>Why do I get the warning + "AssertionFailedError: No + tests found in XXX" when I run my test?</b> + </p> + <p> + Make sure you have more or more method annotated with <code>@Test</code>. + </p> + <p> + For example: + </p> + <div> + <blockquote><pre> +@Test +public void testSomething() { +} + </pre></blockquote> + </div> + </li> + <li> + <p> + <b><a name="running_12"></a>Why do I see "Unknown Source" in the + stack trace of +a test failure, rather than the source file's line number?</b> + </p> + <p> + The debug option for the Java compiler must be enabled in order + to see source file and line number information in a stack trace. + </p> + <p> + When invoking the Java compiler from the command line, use + the <code>-g</code> option to generate all debugging info. + </p> + <p> + When invoking the Java compiler from an + <a href="http://jakarta.apache.org/ant/index.html">Ant</a> task, use the + <code>debug="on"</code> attribute. For example: + </p> + <div> + <blockquote><code> +<javac srcdir="${src}" destdir="${build}" debug="on" /> + </code></blockquote> + </div> + <p> + When using older JVMs pre-Hotspot (JDK 1.1 and most/all 1.2), + run JUnit with the <code>-DJAVA_COMPILER=none</code> JMV command + line argument to prevent runtime JIT compilation from obscuring + line number info. + </p> + <p> + Compiling the test source with debug enabled will show the line + where the assertion failed. Compiling the non-test source with + debug enabled will show the line where an exception was raised + in the class under test. + </p> + </li> + <li> + <p> + <b><a name="running_15"></a>How do I organize all test classes + in a TestSuite automatically and not use or manage a TestSuite + explicitly?</b> + </p> + <p> + <i>(Submitted by: Bill de hora)</i> + </p> + <p> + There are a number of ways to do this: + </p> + <ol> + <li> + <p> + In Ant, use the <code>junit</code> task and + the <code>batchtest</code> element: + </p> + <div> + <pre><code> +<junit printsummary="yes" haltonfailure="yes"> + ... + <batchtest fork="yes"> + <fileset dir="${src.dir}"> + <include name="**/*Test.java" /> + <include name="**/Test*.java" /> + </fileset> + </batchtest> +</junit> + </code></pre> + </div> + <p> + Idiomatic naming patterns for unit tests + are <code>Test*.java</code> and <code>*Test.java</code>. + Documentation and examples are at <a + href="http://ant.apache.org/manual/OptionalTasks/junit.html">http://ant.apache.org/manual/OptionalTasks/junit.html</a>. + </p> + </li> + <li> + <p> + Use the <code>DirectorySuiteBuilder</code> + and <code>ArchiveSuiteBuilder</code> (for jar/zip files) + classes provided by JUnit-addons project: + </p> + <div> + <blockquote><pre> +DirectorySuiteBuilder builder = new DirectorySuiteBuilder(); +builder.setSuffix("Test"); +Test suite = builer.suite("/home/project/myproject/tests"); + </pre></blockquote> + </div> + <p> + Documentation and examples are at <a + href="http://junit-addons.sourceforge.net/">http://junit-addons.sourceforge.net</a>. + </p> + </li> + <li> + <p> + Write your own custom suite builder. + </p> + <p> + Have your test classes implement an interface and write a + treewalker to load each class in a directory, inspect the + class, and add any classes that implement the interface to a + TestSuite. + </p> + <p> + You might only want to do this if you are <b>very</b> + uncomfortable with using a naming convention for test + classes. Aside from being slow for larger suites, ultimately + it's arguable whether it's more effort to follow a naming + convention that have test classes implement an interface! + </p> + <p> + An example of this approach is at + <a href="http://www.javaworld.com/javaworld/jw-12-2000/jw-1221-junit_p.html">http://www.javaworld.com/javaworld/jw-12-2000/jw-1221-junit_p.html</a>. + </p> + </li> + </ol> + </li> +</ol> + +<!-- + + Best Practices + +--> +<div class="header"> +<a name="best">Best Practices</a> +</div> +<ol> + <li> + <p> + <b><a name="best_1"></a>When should tests be written?</b> + </p> + <p> + Tests should be written before the code. Test-first programming + is practiced by only writing new code when an automated test is + failing. + </p> + <p> + Good tests tell you how to best design the system for its + intended use. They effectively communicate in an executable + format how to use the software. They also prevent tendencies to + over-build the system based on speculation. When all the tests + pass, you know you're done! + </p> + <p> + Whenever a customer test fails or a bug is reported, first write + the necessary unit test(s) to expose the bug(s), <em>then</em> + fix them. This makes it almost impossible for that particular + bug to resurface later. + </p> + <p> + Test-driven development is a lot more fun than writing tests + after the code seems to be working. Give it a try! + </p> + </li> + <li> + <p> + <b><a name="best_2"></a>Do I have to write a test for + everything?</b> + </p> + <p> + No, just test everything that could reasonably break. + </p> + <p> + Be practical and maximize your testing investment. Remember + that investments in testing are equal investments in design. If + defects aren't being reported and your design responds well to + change, then you're probably testing enough. If you're spending + a lot of time fixing defects and your design is difficult to + grow, you should write more tests. + </p> + <p> + If something is difficult to test, it's usually an opportunity + for a design improvement. Look to improve the design so that + it's easier to test, and by doing so a better design will + usually emerge. + </p> + </li> + <li> + <p> + <b><a name="best_3"></a>How simple is 'too simple to break'?</b> + </p> + <p> + <i>(Submitted by: J. B. Rainsberger)</i> + </p> + <p> + The general philosophy is this: if it can't break <em>on its + own</em>, it's too simple to break. + </p> + <p> + First example is the <code>getX()</code> method. Suppose + the <code>getX()</code> method only answers the value of an + instance variable. In that case, <code>getX()</code> cannot + break unless either the compiler or the interpreter is also + broken. For that reason, don't test <code>getX()</code>; there + is no benefit. The same is true of the <code>setX()</code> + method, although if your <code>setX()</code> method does any + parameter validation or has any side effects, you likely need to + test it. + </p> + <p> + Next example: suppose you have written a method that does + nothing but forward parameters into a method called on another + object. That method is too simple to break. + </p> + <div> + <blockquote><pre> +public void myMethod(final int a, final String b) { + myCollaborator.anotherMethod(a, b); +} + </pre></blockquote> + </div> + <p> + <code>myMethod</code> cannot possibly break because it does nothing: it + forwards its input to another object and that's all. + </p> + <p> + The only precondition for this method is "myCollaborator != + null", but that is generally the responsibility of the + constructor, and not of myMethod. If you are concerned, add a + test to verify that myCollaborator is always set to something + non-null by every constructor. + </p> + <p> + The only way myMethod could break would be + if <code>myCollaborator.anotherMethod()</code> were broken. In + that case, test <code>myCollaborator</code>, and not the current + class. + </p> + <p> + It is true that adding tests for even these simple methods + guards against the possibility that someone refactors and makes + the methods "not-so-simple" anymore. In that case, though, the + refactorer needs to be aware that the method is now complex + enough to break, and should write tests for it -- and preferably + before the refactoring. + </p> + <p> + Another example: suppose you have a JSP and, like a good + programmer, you have removed all business logic from it. All it + does is provide a layout for a number of JavaBeans and never + does anything that could change the value of any object. That + JSP is too simple to break, and since JSPs are notoriously + annoying to test, you should strive to make all your JSPs too + simple to break. + </p> + <p> + Here's the way testing goes: + </p> + <div> + <blockquote><pre> +becomeTimidAndTestEverything +while writingTheSameThingOverAndOverAgain + becomeMoreAggressive + writeFewerTests + writeTestsForMoreInterestingCases + if getBurnedByStupidDefect + feelStupid + becomeTimidAndTestEverything + end +end + </pre></blockquote> + </div> + <p> + The loop, as you can see, never terminates. + </p> + </li> + <li> + <p> + <b><a name="best_4"></a>How often should I run my tests?</b> + </p> + <p> + Run all your unit tests as often as possible, ideally every time + the code is changed. Make sure all your unit tests always run + at 100%. Frequent testing gives you confidence that your + changes didn't break anything and generally lowers the stress of + programming in the dark. + </p> + <p> + For larger systems, you may just run specific test suites that + are relevant to the code you're working on. + </p> + <p> + Run all your acceptance, integration, stress, and unit tests at + least once per day (or night). + </p> + <p> + If you're using Eclipse, be sure to check out David Saff's + <a href="http://pag.csail.mit.edu/continuoustesting/">continuous + testing plug-in</a>. + </p> + </li> + <li> + <p> + <b><a name="best_5"></a>What do I do when a defect is reported?</b> + </p> + <p> + Test-driven development generally lowers the defect density of + software. But we're all fallible, so sometimes a defect will + slip through. When this happens, write a failing test that + exposes the defect. When the test passes, you know the defect + is fixed! + </p> + <p> + Don't forget to use this as a learning opportunity. Perhaps the + defect could have been prevented by being more aggressive about + testing everything that could reasonably break. + </p> + </li> + <li> + <p> + <b><a name="best_6"></a>Why not just use <code>System.out.println()</code>?</b> + </p> + <p> + Inserting debug statements into code is a low-tech method for + debugging it. It usually requires that output be scanned + manually every time the program is run to ensure that the code + is doing what's expected. + </p> + <p> + It generally takes less time in the long run to codify + expectations in the form of an automated JUnit test that retains + its value over time. If it's difficult to write a test to + assert expectations, the tests may be telling you that shorter + and more cohesive methods would improve your design. + </p> + </li> + <li> + <p> + <b><a name="best_7"></a>Why not just use a debugger?</b> + </p> + <p> + Debuggers are commonly used to step through code and inspect + that the variables along the way contain the expected values. + But stepping through a program in a debugger is a manual process + that requires tedious visual inspections. In essence, the + debugging session is nothing more than a manual check of + expected vs. actual results. Moreover, every time the program + changes we must manually step back through the program in the + debugger to ensure that nothing broke. + </p> + <p> + It generally takes less time to codify expectations in the form + of an automated JUnit test that retains its value over time. If + it's difficult to write a test to assert expected values, the + tests may be telling you that shorter and more cohesive methods + would improve your design. + </p> + </li> +</ol> + +<!-- + + Miscellaneous + +--> +<div class="header"> +<a name="misc">Miscellaneous</a> +</div> +<ol> + <li> + <p> + <b><a name="misc_1"></a>How do I integrate JUnit with my IDE?</b> + </p> + <p> + The JUnit home page maintains a list of <a + href="http://www.junit.org/news/ide/index.htm">IDE integration + instructions</a>. + </p> + </li> + <li> + <p> + <b><a name="misc_2"></a>How do I launch a debugger when a test fails?</b> + </p> + <p> + Start the <code>TestRunner</code> under the debugger and + configure the debugger so that it catches + the <code>junit.framework.AssertionFailedError</code>. + </p> + <p> + How you configure this depends on the debugger you prefer to + use. Most Java debuggers provide support to stop the program + when a specific exception is raised. + </p> + <p> + Notice that this will only launch the debugger when an expected + failure occurs. + </p> + </li> + <li> + <p> + <b><a name="misc_3"></a>Where can I find unit testing frameworks + similar to JUnit for other languages?</b> + </p> + <p> + XProgramming.com maintains a complete list of available <a + href="http://www.xprogramming.com/software.htm">xUnit testing + frameworks</a>. + </p> + </li> +</ol> + +<br/> + +<div align="right"> + <a href="http://validator.w3.org/check?uri=referer"> + <img src="http://www.w3.org/Icons/valid-xhtml10" + alt="Valid XHTML 1.0!" height="31" width="88" /></a> +</div> + +</body> +</html> |