######################################################################
#                                                                    #
#   This file is part of  JUnitDoclet, a project to generate basic   #
#   test cases  from source code and  helping to keep them in sync   #
#   during refactoring.                                              #
#                                                                    #
#   Copyright (C) 2002  ObjectFab GmbH  (http://www.objectfab.de/)   #
#                                                                    #
#   This library is  free software; you can redistribute it and/or   #
#   modify  it under the  terms of  the  GNU Lesser General Public   #
#   License as published  by the  Free Software Foundation; either   #
#   version 2.1  of the  License, or  (at your option)  any  later   #
#   version.                                                         #
#                                                                    #
#   This library is distributed in the hope that it will be useful,  #
#   but WITHOUT ANY WARRANTY; without even the implied warranty of   #
#   MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.  See the   #
#   GNU Lesser General Public License for more details.              #
#                                                                    #
#   You  should  have  received a  copy of the  GNU Lesser General   #
#   Public License along with this  library; if not, write  to the   #
#   Free  Software  Foundation, Inc.,  59 Temple Place,  Suite 330,  #
#   Boston, MA  02111-1307  USA                                      #
#                                                                    #
######################################################################


Getting Started with JUnitDoclet
================================

We all want to deliver quality software. Therefore we do unit tests.
For Java fans (like us) there is JUnit. It makes unit testing much
more easy. (There are ports of it to many other languages. Just
see http://www.junit.org/ .)

Thanks to Kent Beck and Erich Gamma who created JUnit and to all the
others who contributed.


But still there are a few things we need to do "manually" with JUnit:

 * writing TestCases (Not just the content, but class headers, method
   headers, setUp and tearDown, ... all those things the compiler
   or the framework "need" as well. Who likes to do things, just
   because of a compiler "needing" them?! ;-)

 * coming up with names for test procedures (We don't want to waste
   creativity, right?)

 * creating TestSuites to organize our own TestCases (Did you
   ever miss to execute a TestCase which was there? Well, we did.
   The worst part of it: this TestCase was failing! You don't
   want that.)

 * ...


Let's see, what we can do about it.

 * How about writing one TestCase per class?
   It wouldn't be as bad as it seems. If you want to add
   more TestCases / TestSuites (for example functional tests),
   that is still possible of course.
   The whole point of JUnitDoclet is to do repetitive tasks
   for you. If JUnitDoclet provides a TestCase skeleton for a
   class you didn't intend to test, it will be much less "pain"
   to check a few things anyway.

 * How about each of these TestCases having a test method
   for each public method of the corresponding class?

 * How about one TestSuite per package?

 * How about some help and guidance to keep the tests in sync
   with the application when doing Refactoring?

That sounds like a monotone job. Computers are good at those,
so we make the computer do it. Actually that is what JUnitDoclet
is doing. But the fun (writing the content of the test methods)
remains our job. Can you feel your productivity increasing
already?


Now, how does JUnitDoclet work?
-------------------------------

We all know and admire JavaDoc. It parses our sources, gathering all
sorts of information and finally writes all it's knowledge to HTML.
Marvellous!

Guess what, JavaDoc is even extendable! These extensions are called
Doclets and they do the actual writing based on the information
gathered. JUnitDoclet processes information about our own classes
and packages and creates skeletons of TestCases and TestSuites.

You can even specify a few details:

 * output directory (-d <dir>)   Note: This is required!

   This is, where the TestCases and TestSuites are written to (in
   sub directories according to their package of course). You may
   use a separate source tree for unit tests. This way you have your
   test cases in the same package as the classes they operate on,
   but at the same time, tests are separated from ordinary classes.
   Please don't mix tests and application classes! (There is a
   different way of separating tests from the application, but still
   you need to specify the output directory. See "sub package" for
   details.)

 * sub package (-subpackage <relative_package>)

   If your IDE does not support several source trees, this option
   is for you. It defines a relative package, where to store test
   classes. Usually the relative package is "test". With that
   setting , the TestCase for a class root.sub.Sample would be
   root.sub.test.SampleTest and the TestSuite would be generated
   as root.sub.test.SubSuite.
   Please don't mix tests and application classes! (You could use
   a output directory other than the source directory. See
   "output directory" for details.)

 * build all (-buildall)

   Overwriting default behavior of "smart rewriting". By default,
   TestCases are regenerated only, if the source of the application
   class is newer then the source of the TestCase. And even if a file
   is regenerated, it won't be written if it equals the same file
   already there. To generate and write everything (TestCases and
   TestSuites) use the -buildall flag.

 * property file (-properties <property_file_name>)

   JUnitDoclet is customizable in many areas. Most important:
   the templates for test cases and test suites. If you are not
   happy with the default properties, make up your own definition
   and pass it on to JUnitDoclet.
   JUnitDoclet tries to load the file with this relative
   or absolute path. If this fails, it tries to load it
   as resource from class path. JUnitDoclet will let you
   know, which property file is in use.

 * naming strategy (-naming <naming_strategy_class_name>)

   Defining names is difficult, especially if it has to be
   widely accepted. Don't worry, if you don't like our way,
   create your own and snap it in.

 * testing strategy (-testing <testing_strategy_class_name>)

   If you are working on a large scale application with
   several million lines of source code, the template
   based approach may be to slow. If you want your style
   hard coded, just do it and plug it in here.

 * writing strategy (-writing <writing_strategy_class_name>)

   Reading and writing files is quite simple. But if you
   want to access something else, than a regular file
   system (for example ftp or cvs) you write your own
   strategy and let JUnitDoclet know.
  
 * test in test (-testintest)
  
   If you want to generate TestCases for classes in a part
   of the source path which is output path too, this method
   enables that. (By default JUnitDoclet does not generate
   any tests for classes in the output directory. With
   -testintest enabled, only TestCases and TestSuites are
   excluded.) It is not recommended to use this option
   unless you really know what you are doing.


Accessor tests
--------------

Do you write tests for "set*" and "get*"? Do these methods
fail sometimes? So why does not everyone write tests for them?

If your accessor methods ("set"/"get" and "set"/"is") follow
a few very basic rules, JUnitDoclet will help you. It will
generate a combined test, provide an array with default values,
call set* with every single value and check if get* returns it.
With JUnitDoclet you get accessor tests for free (even for
boolean kind of accessors like set*/is*).

If you don't like, what JUnitDoclet generated, you can change
the generated code. You can add values to the array or remove
some of them. Because JUnitDoclet placed this default tests
within markers, your modifications will remain.


Tests are growing with the application
--------------------------------------

Software development is very seldom pure top down. Instead, we
constantly refactor our application and this is a good thing.

By spec JUnitDoclet generates the TestCases and Suites based
on the current application source. But while generating it can
access the old TestCases as well. At some interesting places
in each file, there are pairs of markers (at import, in each
class and in each test method and -if you like that- around
javadoc comments as well).

Place your code/javadoc only within this marker pairs!

All the code within marker pairs from an old TestCase will be
merged into the new TestCase. All of it, but none of the code
outside the pairs! This is very important, so please keep it
in mind.

When a method is renamed the name of the test method will change
the next time you are generating. Fortunately marker pairs from
the old TestCase without the same marker in the new TestCase
are not lost. Instead they are placed in a special test method:
"testVault". Just make sure to move the code to the test method
where it belongs. JUnitDoclet will write a warning, if a
"testVault" is not empty. With version 1.0 we changed the
way markers are generated: Now the name(s) of the tested methods
are in the marker, not the name of the test method. This way
tools like IntelliJ IDEA can help you even more: When renaming
a method during refactoring, comments (for example markers) are
modified as well. When you are running JUnitDoclet the test
will at it's place without the need to move it. (We felt, this
benefit was worth the change in marker syntax from version 0.9.2
to version 1.0.)

When renaming classes there is no such help within JUnitDoclet.
Tools like IntelliJ IDEA offer some help, but (yet) can't do it
all. Anyway, the old TestCase is still there for you. If you
have any suggestion, about further help here, please let us know.


Limits
------

JUnitDoclet does not solve all problems. There are some limits.
For example it can't create an instance of an interface or
an abstract class. But if they are used in a accessor...

How could JUnitDoclet know, what to do? It just can't, and
it won't confuse us by trying to. If generated TestCases
don't compile when first generated, this is not a bug.
Relax, make it compilable the way YOU want it and enjoy.

Background: there is software on this planet, trying to solve
problems for us, even if there are no problems. That kind of
software is standing in the way. JUnitDoclet follows a different
approach:

  "simple is beautiful."

You should be glad to fix a few spots in generated code manually.
This is much more predictable, than the results when trying to
outsmart an assistant (or "evil wizard" as known from the book
"The Pragmatic Programmer").


The down side of JUnitDoclet
----------------------------

Yes there is one, and it's not the fault of JUnit nor of JUnitDoclet.
By using this tool you create lots of test methods. There are two
extremes you have to avoid:

 * too few tests
   That is, if you get impressed by the high number of tests but
   most of the test methods are empty. Don't lie to yourself! Make
   test coverage more important to you then the number of tests!

 * too many tests
   Since it is so easy to write simple tests, you may get dragged
   away in writing millions of tests, but only for easy methods.
   Don't laugh, it happened. So don't forget to create some more
   advanced tests. They may be more difficult, but while being
   written they already help you to understand your system.
   Just don't forget to write application code as well, or you
   may get fired. ;-)

There are no simple rules to decide how many tests are enough.

Let's assume this: application classes and TestCases (!) need to
be tested. TestCases test the application classes. And by doing
that, indirectly the TestCases are proven to be working as well.

Until you dig deeper into test coverage, let's compare sizes
of tests and application.
Rule of thumb: They should be about the same.

In business projects this is often impossible because of time
pressure. But managers will learn their lesson. Keep teaching
and please do so in a kindly manner. ;-)


License:
--------

Please see lgpl.txt or GNU Lesser General Public License (www.gnu.org)


Feedback
---------

If you want to share your thoughts about JUnitDoclet feel free to
write an Email to junitdoclet@objectfab.de . Please don't forget to
see the other tools we provide on our website (www.objectfab.de).


And now: H A V E   F U N !


Kind Regards,

Steffen Gemkow

