What is JUnit - GoogleCode

jockeyropeInternet and Web Development

Feb 2, 2013 (4 years and 2 months ago)

304 views

JUnit Documentation

http://junit.sourceforge.net/doc/faq/faq.htm#overview_4

J
U
nit

Test Infected: Programmers Love
Writing Tests


Note: this article describes JUnit 3.8.x.


Testing is not closely integrated with development. This prevents you from measurin
g the progress
of development
-

you can't tell when something starts working or when something stops working.
Using
JUnit

you can cheaply and incrementally build a test suite that will help you measure your
progress, spot unintended side effects, and focus
your development efforts.

Contents



The Problem




Example




Testing Practices




Conclusions


The Problem

Every programmer knows they should write tests
for their code. Few do. The universal response to
"Why not?" is "I'm in too much of a hurry." This quickly becomes a vicious cycle
-

the more
pressure you feel, the fewer tests you write. The fewer tests you write, the less productive you are
and the less s
table your code becomes. The less productive and accurate you are, the more pressure
you feel.

Programmers burn out from just such cycles. Breaking out requires an outside influence. We found
the outside influence we needed in a simple testing framework t
hat lets us do a little testing that
makes a big difference.

The best way to convince you of the value of writing your own tests would be to sit down with you
and do a bit of development. Along the way, we would encounter new bugs, catch them with tests,
fix them, have them come back, fix them again, and so on. You would see the value of the
immediate feedback you get from writing and saving and rerunning your own unit tests.

Unfortunately, this is an article, not an office overlooking charming old
-
town Z
ürich, with the bustle
of medieval commerce outside and the thump of techno from the record store downstairs, so we'll
have to simulate the process of development. We'll write a simple program and its tests, and show
you the results of running the tests. T
his way you can get a feel for the process we use and advocate
without having to pay for our presence.

Example

As you read, pay attention to the interplay of the code and the tests. The style here is to write a few
lines of code, then a test that should r
un, or even better, to write a test that won't run, then write the
code that will make it run.

The program we write will solve the problem of representing arithmetic with multiple currencies.
Arithmetic between single currencies is trivial, you can just a
dd the two amounts. Simple numbers
suffice. You can ignore the presence of currencies altogether.

Things get more interesting once multiple currencies are involved. You cannot just convert one
currency into another for doing arithmetic since there is no s
ingle conversion rate
-

you may need to
compare the value of a portfolio at yesterday's rate and today's rate.

Let's start simple and define a class
Money

to represen
t a value in a single currency. We represent
the amount by a simple int. To get full accuracy you would probably use double or
java.math.BigDecimal to store arbitrary
-
precision signed decimal numbers. We represent a currency
as a string holding the ISO thr
ee letter abbreviation (USD, CHF, etc.). In more complex
implementations, currency might deserve its own object.

class Money {



private int fAmount;



private String fCurrency;



public Money(int amount, String currency) {



fAmount= amount;



fCurrency= currency;



}




public int amount() {



return fAmount;



}




public String currency() {



return fCurrency;



}

}

When you add two Moneys of the same currency, the resulting Money has as its amount the sum of
the

other two amounts.

public Money add(Money m) {



return new Money(amount()+m.amount(), currency());

}

Now, instead of just coding on, we want to get immediate feedback and practice "code a little, test a
little, code a little, test a little". To implem
ent our tests we use the JUnit framework. To write tests
you need to get the
latest copy

JUnit (or write your own equivalent
-

it's not so much work).

JUnit defines how to structure your test cases and

provides the tools to run them. You implement a
test in a subclass of TestCase. To test our Money implementation we therefore define
MoneyTest

as
a subclass of
TestCase. In Java, classes are contained in packages and we have to decide where to
put MoneyTest. Our current practice is to put MoneyTest in the same package as the classes under
test. In this way a test case has access to the package private methods. We

add a test method
testSimpleAdd, that will exercise the simple version of
Money.add()

above. A JUnit test method is
an ordinary method without any parameters.

public
class MoneyTest extends TestCase {



//…



public void testSimpleAdd() {



Money m12CHF= new Money(12, "CHF");


//

(1)



Money m14CHF= new Money(14, "CHF");




Money expected= new Money(26, "CHF");



Money result= m12CHF.
add(m14CHF);


//

(2)



Assert.assertTrue(expected.equals(result));


//

(3)



}

}

The testSimpleAdd() test case consists of:

1.

Code

which creates the objec
ts we will interact with during the test. This testing context is
commonly referred to as a test's
fixture
. All we need for the testSimpleAdd test are some
Money objects.

2.

Code

which exercises the objects in the fixture.

3.

Code

which verifies the result.

Before we can verify the result we have to digress a little since we need a w
ay to test that two
Money objects are equal. The Java idiom to do so is to override the method
equals

defined in
Object. Before we implement equals let's a write a test for equals in MoneyTest.

public void testEquals() {



Money m12CHF= new Money(12, "C
HF");



Money m14CHF= new Money(14, "CHF");




Assert.assertTrue(!m12CHF.equals(null));



Assert.assertEquals(m12CHF, m12CHF);



Assert.assertEquals(m12CHF, new Money(12, "CHF")); //

(1)



Assert.assertTrue(!m12CHF.equals(m14CHF));

}

The equals m
ethod in Object returns true when both objects are the same. However, Money is a
value object
. Two Monies are considered equal if they have the same currency and value. To test
this property we have added a test
(1)

to verify that Monies are equal when they have the same
value but are not the same object.

Next let's write the equals method in Money:

public boolean equals(Object anObject) {



if (anObject instanceo
f Money) {



Money aMoney= (Money)anObject;



return aMoney.currency().equals(currency())



&& amount() == aMoney.amount();



}



return false;

}

Since equals can receive any kind of object as its argument we first have to check i
ts type before we
cast it as a Money. As an aside, it is a recommended practice to also override the method hashCode
whenever you override method equals. However, we want to get back to our test case.

With an equals method in hand we can verify the outcom
e of testSimpleAdd. In JUnit you do so by
a calling
Assert.assertTrue
, which triggers a failure that is recorded by JUnit when the argument
isn't true
. Since assertions for equality are very common, there is also an Assert.assertEquals
convenience method. In addition to testing for equality with equals, it reports the printed value of
the two objects in the case they differ. This lets us immediately see

why a test failed in a JUnit test
result report. The value a string representation created by the toString converter method. There are
other asertXXXX variants

not discussed
here.

Now that we have implemented two test cases we notice some code duplication for setting
-
up the
tests. It would be nice to reuse some of this test set
-
up code. In other words, we would like to have a
common fixture for running the tests. With JUnit y
ou can do so by storing the fixture's objects in
instance variables of your
TestCase

subclass and initialize them by overridding the setUp method.
The symmetric operation to

setUp is tearDown which you can override to clean up the test fixture at
the end of a test. Each test runs in its own fixture and JUnit calls setUp and tearDown for each test
so that there can be no side effects among test runs.

public class MoneyTest ex
tends TestCase {



private Money f12CHF;



private Money f14CHF;





protected void setUp() {



f12CHF= new Money(12, "CHF");



f14CHF= new Money(14, "CHF");



}

}

We can rewrite the two test case methods, removing the common setup co
de:

public void testEquals() {



Assert.assertTrue(!f12CHF.equals(null));



Assert.assertEquals(f12CHF, f12CHF);



Assert.assertEquals(f12CHF, new Money(12, "CHF"));



Assert.assertTrue(!f12CHF.equals(f14CHF));

}


public void testSimpleAdd() {



Money expected= new Money(26, "CHF");



Money result= f12CHF.add(f14CHF);



Assert.assertTrue(expected.equals(result));

}

Two additional steps are needed to run the two test cases:

1.

define how to run an individual test case,

2.

define how to run a
test
suite
.

JUnit supports two ways of running single tests:



static



dynamic

In the static way you override the runTest method inherited from TestCase and call the desired test
case. A convenient way to do this is with an anonymous inner class. Note that eac
h test must be
given a name, so you can identify it if it fails.

TestCase test= new MoneyTest("simple add") {



public void runTest() {



testSimpleAdd();



}

};

A template method
[1]

in the superclass will make sure runTest is executed when the time comes.

The dynamic way to create a test case to be run uses reflection to implement runTest. It assumes the
name of the test

is the name of the test case method to invoke. It dynamically finds and invokes the
test method. To invoke the testSimpleAdd test we therefore construct a MoneyTest as shown below:

TestCase test= new MoneyTest("testSimpleAdd");

The dynamic way is more co
mpact to write but it is less static type safe. An error in the name of the
test case goes unnoticed until you run it and get a NoSuchMethodException. Since both approaches
have advantages, we decided to leave the choice of which to use up to you.

As the
last step to getting both test cases to run together, we have to define a test suite. In JUnit this
requires the definition of a static method called suite. The suite method is like a main method that is
specialized to run tests. Inside suite you add the t
ests to be run to a
TestSuite

object and return it. A
TestSuite can run a collection of tests. TestSuite and TestCase both implement an interface called
Test which defines
the methods to run a test. This enables the creation of test suites by composing
arbitrary TestCases and TestSuites. In short TestSuite is a Composite
[1].

The code below illustrates
the creation of a test suite with the dynamic way to run a test.

public static Test suite() {



TestSuite suite= new TestSuite();



suite.addTest(new MoneyTest("testEquals"));



suite.addTest(new
MoneyTest("testSimpleAdd"));



return suite;

}

Since JUnit 2.0 there is an even simpler dynamic way. You only pass the class with the tests to a
TestSuite and it extracts the test methods automatically.

public static Test suite() {



return new TestSu
ite(MoneyTest.class);

}


Here is the corresponding code using the static way.

public static Test suite() {



TestSuite suite= new TestSuite();



suite.addTest(



new MoneyTest("money equals") {



protected void runTest() { testEquals()
; }



}



);





suite.addTest(



new MoneyTest("simple add") {



protected void runTest() { testSimpleAdd(); }



}



);



return suite;

}

Now we are ready to run our tests. JUnit comes with a graphical


interface to
run tests. Type the
name of your test class in the field at the top of the window. Press the Run button. While the test is
run JUnit shows its progress with a progress bar below the input field. The bar is initially green but
turns into red as soon as ther
e is an unsuccessful test. Failed tests are shown in a list at the bottom.
Figure 1

shows the TestRunner window after we run our trivial test suite.



Figure 1
: A Successful Run

After having verified that the simple currency case works we move on to multiple currencies. As
mentioned above the problem of mixed currency arithmetic is that

there isn't a single exchange rate.
To avoid this problem we introduce a MoneyBag which defers exchange rate conversions. For
example adding 12 Swiss Francs to 14 US Dollars is represented as a bag containing the two
Monies 12 CHF and 14 USD. Adding anoth
er 10 Swiss francs gives a bag with 22 CHF and 14
USD. We can later evaluate a MoneyBag with different exchange rates.

A MoneyBag is represented as a list of Monies and provides different constructors to create a
MoneyBag. Note, that the constructors are
package private since MoneyBags are created behind the
scenes when doing currency arithmetic.

class MoneyBag {



private Vector fMonies= new Vector();




MoneyBag(Money m1, Money m2) {



appendMoney(m1);



appendMoney(m2);



}




Money
Bag(Money bag[]) {



for (int i= 0; i < bag.length; i++)



appendMoney(bag[i]);



}

}

The method appendMoney is an internal helper method that adds a Money to the list of Moneys and
takes care of consolidating Monies with the same currenc
y. MoneyBag also needs an equals method
together with a corresponding test. We skip the implementation of equals and only show the
testBagEquals method. In a first step we extend the fixture to include two MoneyBags.

protected void setUp() {



f12CHF= n
ew Money(12, "CHF");



f14CHF= new Money(14, "CHF");



f7USD=


new Money( 7, "USD");



f21USD= new Money(21, "USD");



fMB1= new MoneyBag(f12CHF, f7USD);



fMB2= new MoneyBag(f14CHF, f21USD);

}

With this fixture the testBagEquals test case become
s:

public void testBagEquals() {



Assert.assertTrue(!fMB1.equals(null));



Assert.assertEquals(fMB1, fMB1);



Assert.assertTrue(!fMB1.equals(f12CHF));



Assert.assertTrue(!f12CHF.equals(fMB1));



Assert.assertTrue(!fMB1.equals(fMB2));

}

Followi
ng "code a little, test a little" we run our extended test with JUnit and verify that we are still
doing fine. With MoneyBag in hand, we can now fix the add method in Money.

public Money add(Money m) {



if (m.currency().equals(currency()) )



ret
urn new Money(amount()+m.amount(), currency());



return new MoneyBag(this, m);

}

As defined above this method will not compile since it expects a Money and not a MoneyBag as its
return value. With the introduction of MoneyBag there are now two represent
ations for Moneys
which we would like to hide from the client code. To do so we introduce an interface IMoney that
both representations implement. Here is the IMoney interface:

interface IMoney {



public abstract IMoney add(IMoney aMoney);



//…

}

To

fully hide the different representations from the client we have to support arithmetic between all
combinations of Moneys with MoneyBags. Before we code on, we therefore define a couple more
test cases. The expected MoneyBag results use the convenience co
nstructor shown above,
initializing a MoneyBag from an array.

public void testMixedSimpleAdd() {




// [12 CHF] + [7 USD] == {[12 CHF][7 USD]}




Money bag[]= { f12CHF, f7USD };




MoneyBag expected= new MoneyBag(bag);




Assert.assertEquals(expec
ted, f12CHF.add(f7USD));


}

The other tests follow the same pattern:



testBagSimpleAdd
-

to add a MoneyBag to a simple Money



testSimpleBagAdd
-

to add a simple Money to a MoneyBag



testBagBagAdd
-

to add two MoneyBags

Next, we extend our test suite accor
dingly:

public static Test suite() {



TestSuite suite= new TestSuite();



suite.addTest(new MoneyTest("testMoneyEquals"));



suite.addTest(new MoneyTest("testBagEquals"));



suite.addTest(new MoneyTest("testSimpleAdd"));



suite.addTest(new Mon
eyTest("testMixedSimpleAdd"));



suite.addTest(new MoneyTest("testBagSimpleAdd"));



suite.addTest(new MoneyTest("testSimpleBagAdd"));



suite.addTest(new MoneyTest("testBagBagAdd"));



return suite;

}

Having defined the test cases we can start to
implement them. The implementation challenge here is
dealing with all the different combinations of Money with MoneyBag. Double dispatch
[2]

is an
elegant way to solve this problem. The idea behind double dispatch is to use an additional call to
discover the kind of argument we are dealing with. We call a method on the argument with the name
of the original method followed by the class n
ame of the receiver. The add method in Money and
MoneyBag becomes:

class Money implements IMoney {



public IMoney add(IMoney m) {



return m.addMoney(this);



}



//…

}

class MoneyBag implements IMoney {



public IMoney add(IMoney m) {




return m.addMoneyBag(this);



}



//…

}

In order to get this to compile we need to extend the interface of IMoney with the two helper
methods:

interface IMoney {

//…



IMoney addMoney(Money aMoney);



IMoney addMoneyBag(MoneyBag aMoneyBag);

}

To complete the implementation of double dispatch, we have to implement these methods in Money
and MoneyBag. This is the implementation in Money.

public IMoney addMoney(Money m) {



if (m.currency().equals(currency()) )



return new Money(amount()
+m.amount(), currency());



return new MoneyBag(this, m);

}


public IMoney addMoneyBag(MoneyBag s) {



return s.addMoney(this);

}

Here is the implemenation in MoneyBag which assumes additional constructors to create a
MoneyBag from a Money and a MoneyB
ag and from two MoneyBags.

public IMoney addMoney(Money m) {



return new MoneyBag(m, this);

}


public IMoney addMoneyBag(MoneyBag s) {



return new MoneyBag(s, this);

}

We run the tests, and they pass. However, while reflecting on the implementation
we discover
another interesting case. What happens when as the result of an addition a MoneyBag turns into a
bag with only one Money? For example, adding
-
12 CHF to a Moneybag holding 7 USD and 12
CHF results in a bag with just 7 USD. Obviously, such a bag

should be equal with a single Money
of 7 USD. To verify the problem let's implement a test case and run it.

public void testSimplify() {



// {[12 CHF][7 USD]} + [
-
12 CHF] == [7 USD]



Money expected= new Money(7, "USD");



Assert.assertEquals(expe
cted, fMB1.add(new Money(
-
12, "CHF")));

}

When you are developing in this style you will often have a thought and turn immediately to writing
a test, rather than going straight to the code.

It comes to no surprise that our test run ends with a red progres
s bar indicating the failure. So we fix
the code in MoneyBag to get back to a green state.

public IMoney addMoney(Money m) {



return (new MoneyBag(m, this)).simplify();

}


public IMoney addMoneyBag(MoneyBag s) {



return (new MoneyBag(s, this)).simpl
ify();

}


private IMoney simplify() {



if (fMonies.size() == 1)



return (IMoney)fMonies.firstElement()



return this;

}

Now we run our tests again and voila we end up with green.

The code above solves only a small portion of the multi
-
currency

arithmetic problem. We have to
represent different exchange rates, print formatting, and the other arithmetic operations, and do it all
with reasonable speed. However, we hope you can see how you could develop the rest of the objects
one test at a time
-

a

little test, a little code, a little test, a little code.

In particular, review how in the development above:



We wrote the first test, testSimpleAdd, immediately after we had written add(). In general,
your development will go much smoother if you write

tests a little at a time as you develop.
It is at the moment that you are coding that you are imagining how that code will work.
That's the perfect time to capture your thoughts in a test.



We refactored the existing tests, testSimpleAdd and testEqual, as

soon as we introduced the
common setUp code. Test code is just like model code in working best if it is factored well.
When you see you have the same test code in two places, try to find a way to refactor it so it
only appears once.



We created a suite me
thod, then extended it when we applied Double Dispatch. Keeping old
tests running is just as important as making new ones run. The ideal is to always run all of
your tests. Sometimes that will be too slow to do 10 times an hour. Make sure you run all of
yo
ur tests at least daily.



We created a new test immediately when we thought of the requirement that a one element
MoneyBag should just return its element. It can be difficult to learn to switch gears like this,
but we have found it valuable. When you are s
truck by an idea of what your system should
do, defer thinking about the implementation. Instead, first write the test. Then run it (you
never know, it might already work). Then work on the implementation.

Testing Practices

Martin Fowler makes this easy f
or you. He says, "Whenever you are tempted to type something into
a print statement or a debugger expression, write it as a test instead." At first you will find that you
have to create a new fixtures all the time, and testing will seem to slow you down a
little. Soon,
however, you will begin reusing your library of fixtures and new tests will usually be as simple as
adding a method to an existing TestCase subclass.

You can always write more tests. However, you will quickly find that only a fraction of the

tests you
can imagine are actually useful. What you want is to write tests that fail even though you think they
should work, or tests that succeed even though you think they should fail. Another way to think of it
is in cost/benefit terms. You want to wri
te tests that will pay you back with information.

Here are a couple of the times that you will receive a reasonable return on your testing investment:



During Development
-

When you need to add new functionality to the system, write the tests
first. Then,
you will be done developing when the test runs.



During Debugging
-

When someone discovers a defect in your code, first write a test that
will succeed if the code is working. Then debug until the test succeeds.

One word of caution about your tests. Once yo
u get them running, make sure they stay running.
There is a huge difference between having your suite running and having it broken. Ideally, you
would run every test in your suite every time you change a method. Practically, your suite will soon
grow too l
arge to run all the time. Try to optimize your setup code so you can run all the tests. Or, at
the very least, create special suites that contain all the tests that might possibly be affected by your
current development. Then, run the suite every time you
compile. And make sure you run every test
at least once a day: overnight, during lunch, during one of those long meetings….

Conclusion

This article only scratches the surface of testing. However, it focuses on a style of testing that with a
remarkably sma
ll investment will make you a faster, more productive, more predictable, and less
stressed developer.

Once you've been test infected, your attitude toward development is likely to change. Here are some
of the changes we have noticed:

There is a huge diff
erence between tests that are all running correctly and tests that aren't. Part of
being test infected is not being able to go home if your tests aren't 100%. If you run your suite ten
or a hundred times an hour, though, you won't be able to create enough
havoc to make you late for
supper.

Sometimes you just won't feel like writing tests, especially at first. Don't. However, pay attention to
how much more trouble you get into, how much more time you spend debugging, and how much
more stress you feel when y
ou don't have tests. We have been amazed at how much more fun
programming is and how much more aggressive we are willing to be and how much less stress we
feel when we are supported by tests. The difference is dramatic enough to keep us writing tests even
when we don't feel like it.

You will be able to refactor much more aggressively once you have the tests. You won't understand
at first just how much you can do, though. Try to catch yourself saying, "Oh, I see, I should have
designed this thus and so. I c
an't change it now. I don't want to break anything." When you say this,
save a copy of your current code and give yourself a couple of hours to clean up. (This part works
best you can get a buddy to look over your shoulder while you work.) Make your change
s, all the
while running your tests. You will be surprised at how much ground you can cover in a couple of
hours if you aren't worrying every second about what you might be breaking.

For example, we switched from the Vector
-
based implementation of MoneyBa
g to one based on
HashTable. We were able to make the switch very quickly and confidently because we had so many
tests to rely on. If the tests all worked, we were sure we hadn't changed the answers the system
produced at all.

You will want to get the res
t of your team writing tests. The best way we have found to spread the
test infection is through direct contact. The next time someone asks you for help debugging, get
them to talk about the problem in terms of a fixture and expected results. Then say, "I'
d like to write
down what you just told me in a form we can use." Have them watch while you write one little test.
Run it. Fix it. Write another. Pretty soon they will be writing their own.

So
-

give JUnit a try. If you make it better, please send us the c
hanges so we can spread them around.
Our next article will double click on the JUnit framework itself. We will show you how it is
constructed, and talk a little about our philosophy of framework development.

We would like to thank Martin Fowler, as good a

programmer as any analyst can ever hope to be,
for his helpful comments in spite of being subjected to early versions of JUnit.

References

1.

Gamma, E., et al. Design Patterns: Elements of Reusable Object
-
Oriented Software,
Addison
-
Wesley, Reading, MA, 1995


2.

Beck, K. Smalltalk Best Practice Patterns, Prentice Hall, 1996


source:
http://junit.sourceforge.net/doc/testinfected/testing.htm


J
U
nit Cookbook

Kent Beck, Erich Gamma



Here is
a short cookbook showing you the steps you can follow in writing and organizing your own
tests using JUnit.

Simple Test Case

How do you write testing code?

The simplest way is as an expression in a debugger. You can change debug expressions without
recom
piling, and you can wait to decide what to write until you have seen the running objects. You
can also write test expressions as statements which print to the standard output stream. Both styles
of tests are limited because they require human judgment to a
nalyze their results. Also, they don't
compose nicely
-

you can only execute one debug expression at a time and a program with too many
print statements causes the dreaded "Scroll Blindness".

JUnit tests do not require human judgment to interpret, and it i
s easy to run many of them at the
same time. When you need to test something, here is what you do:

1.

Annotate a method with @org.junit.Test

2.

When you want to check a value, import org.junit.Assert.* statically, call
assertTrue
()
and pass a boolean that is t
rue if the test succeeds

For example, to test that the sum of two Moneys with the same currency contains a value which is
the sum of the values of the two Moneys, write:

@Test public void simpleAdd() {



Money m12CHF= new Money(12, "CHF");




Money m
14CHF= new Money(14, "CHF");




Money expected= new Money(26, "CHF");




Money result= m12CHF.add(m14CHF);




assertTrue(expected.equals(result));

}

If you want to write a test similar to one you have already written, write a Fixture instead.

Fixtur
e

What if you have two or more tests that operate on the same or similar sets of objects?

Tests need to run against the background of a known set of objects. This set of objects is called a
test fixture. When you are writing tests you will often find that

you spend more time writing the
code to set up the fixture than you do in actually testing values.

To some extent, you can make writing the fixture code easier by paying careful attention to the
constructors you write. However, a much bigger savings come
s from sharing fixture code. Often,
you will be able to use the same fixture for several different tests. Each case will send slightly
different messages or parameters to the fixture and will check for different results.

When you have a common fixture, he
re is what you do:

1.

Add a field for each part of the fixture

2.

Annotate a method with @org.junit.Before and initialize the variables in that method

3.

Annotate a method with @org.junit.After to release any permanent resources you allocated
in setUp

For examp
le, to write several test cases that want to work with different combinations of 12 Swiss
Francs, 14 Swiss Francs, and 28 US Dollars, first create a fixture:

public class MoneyTest {




private Money f12CHF;




private Money f14CHF;




private Money

f28USD;






@Before public void setUp() {




f12CHF= new Money(12, "CHF");




f14CHF= new Money(14, "CHF");




f28USD= new Money(28, "USD");




}

}

Once you have the Fixture in place, you can write as many Test Cases as you'd lik
e. Add as many
test methods (annotated with @Test) as you'd like.

Running Tests

How do you run your tests and collect their results?

Once you have tests, you'll want to run them. JUnit provides tools to define the suite to be run and
to display its resul
ts. To run tests and see the results on the console, run this from a Java program:

org.junit.runner.JUnitCore.runClasses(TestClass1.class, ...);

or this from the command line, with both your test class and junit on the classpath:

java org.junit.runner.JU
nitCore TestClass1 [...other test classes...]

You make your JUnit 4 test classes accessible to a TestRunner designed to work with earlier
versions of JUnit, declare a static method
suite

that returns a test.

public static junit.framework.Test suite() {





return new JUnit4TestAdapter(Example.class);


}

Expected Exceptions

How do you verify that code throws exceptions as expected?

Verifying that code completes normally is only part of programming. Making sure the code behaves
as expected in exceptional s
ituations is part of the craft of programming too. For example:

new ArrayList<Object>().get(0);


This code should throw an IndexOutOfBoundsException. The @Test annotation has an optional
parameter "expected" that takes as values subclasses of Throwable. I
f we wanted to verify that
ArrayList throws the correct exception, we would write:

@Test(expected= IndexOutOfBoundsException.class) public void empty()
{




new ArrayList<Object>().get(0);


}


source: http://junit.sourceforge.net/doc/cookbook/cookbook.h
tm


J
U
nit A Cook's Tour


Note: this article is based on JUnit 3.8.x.


1. Introduction


In an earlier article (see Test Infected: Programmers Love Writing Tests, Java Report, July 1998, Volume 3, Number 7),
we described how to use a simple framework to wri
te repeatable tests. In this article, we will take a peek under the
covers and show you how the framework itself is constructed.


We carefully studied the JUnit framework and reflected on how we constructed it. We found lessons at many different
levels. In

this article we will try communicate them all at once, a hopeless task, but at least we will do it in the context
of showing you the design and construction of a piece of software with proven value.


We open with a discussion of the goals of the framework
. The goals will reappear in many small details during the
presentation of the framework itself. Following this, we present the design and implementation of the framework. The
design will be described in terms of patterns (surprise, surprise), the implemen
tation as a literate program. We conclude
with a few choice thoughts about framework development.


2. Goals


What are the goals of JUnit?


First, we have to get back to the assumptions of development. If a program feature lacks an automated test, we assume

it doesn’t work. This seems much safer than the prevailing assumption, that if a developer assures us a program feature
works, then it works now and forever.


From this perspective, developers aren’t done when they write and debug the code, they must also

write tests that
demonstrate that the program works. However, everybody is too busy, they have too much to do, they don’t have
enough time, to screw around with testing. I have too much code to write already, how am I supposed write test code,
too? Answer

me that, Mr. Hard
-
case Project Manager.


So, the number one goal is to write a framework within which we have some glimmer of hope that developers will
actually write tests. The framework has to use familiar tools, so there is little new to learn. It has
to require no more
work than absolutely necessary to write a new test. It has to eliminate duplicated effort.


If this was all tests had to do, you would be done just by writing expressions in a debugger. However, this isn’t
sufficient for testing. Telling

me that your program works now doesn’t help me, because it doesn’t assure me that your
program will work one minute from now after I integrate, and it doesn’t assure me that your program will still work in
five years, when you are long gone.


So, the seco
nd goal of testing is creating tests that retain their value over time. Someone other than the original author
has to be able to execute the tests and interpret the results. It should be possible to combine tests from various authors
and run them together
without fear of interference.


Finally, it has to be possible to leverage existing tests to create new ones. Creating a setup or fixture is expensive and a
framework has to enable reusing fixtures to run different tests. Oh, is that all?


3. The Design of
JUnit


The design of JUnit will be presented in a style first used in (see "Patterns Generate Architectures", Kent Beck and
Ralph Johnson, ECOOP 94). The idea is to explain the design of a system by starting with nothing and applying
patterns, one after an
other, until you have the architecture of the system. We will present the architectural problem to be
solved, summarize the pattern that solves it, and then show how the pattern was applied to JUnit.


3.1 Getting started
-

TestCase


First we have to make an

object to represent our basic concept, the TestCase. Developers often have tests cases in mind,
but they realize them in many different ways
-




print statements,




debugger expressions,




test scripts.


If we want to make manipulating tests easy, we have to
make them objects. This takes a test that was only implicit in the
developer’s mind and makes it concrete, supporting our goal of creating tests that retain their value over time. At the
same time, object developers are used to, well, developing with objec
ts, so the decision to make tests into objects
supports our goal of making test writing more inviting (or at least less imposing).


The Command pattern (see Gamma, E., et al. Design Patterns: Elements of Reusable Object
-
Oriented Software,
Addison
-
Wesley, R
eading, MA, 1995) fits our needs quite nicely. Quoting from the intent, "Encapsulate a request as an
object, thereby letting you… queue or log requests…" Command tells us to create an object for an operation and give it
a method "execute". Here is the code

for the class definition of TestCase:


public abstract class
TestCase

implements Test {






}

Because we expect this class to be reused through inheritance, we declare it "public abstract". For now, ignore the fact
that it implements the Test interfac
e. For the purposes of our current design, you can think of TestCase as a lone class.


Every TestCase is created with a name, so if a test fails, you can identify which test failed.


public abstract class
TestCase

implements Test {




private final Strin
g fName;




public
TestCase
(String name) {




fName= name;




}




public abstract void
run
();






}

To illustrate the evolution of JUnit, we use diagrams that show snapshots of the architecture. The notation we use is
simple. It annota
tes classes with shaded boxes containing the associated pattern. When the role of the class in the
pattern is obvious then only the pattern name is shown. If the role isn’t clear then the shaded box is augmented by the
name of the participant this class co
rresponds to. This notation minimizes the clutter in diagrams and was first shown in
(see Gamma, E., Applying Design Patterns in Java, in Java Gems, SIGS Reference Library, 1997) Figure 1 shows this
notation applied to TestCase. Since we are dealing with a

single class and there can be no ambiguities just the pattern
name is shown.




Figure 1

TestCase applies Command

3.2 Blanks to fill in
-

run()


The next problem to solve is g
iving the developer a convenient "place" to put their fixture code and their test code. The
declaration of TestCase as abstract says that the developer is expected to reuse TestCase by subclassing. However, if all
we could do was provide a superclass with
one variable and no behavior, we wouldn’t be doing much to satisfy our first
goal, making tests easier to write.


Fortunately, there is a common structure to all tests
-

they set up a test fixture, run some code against the fixture, check
some results, and
then clean up the fixture. This means that each test will run with a fresh fixture and the results of one
test can’t influence the result of another. This supports the goal of maximizing the value of the tests.


Template Method addresses our problem quite
nicely. Quoting from the intent, "Define the skeleton of an algorithm in
an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm
without changing the algorithm’s structure." This is exactly r
ight. We want the developer to be able to separately
consider how to write the fixture (set up and tear down) code and how to write the testing code. The execution of this
sequence, however, will remain the same for all tests, no matter how the fixture cod
e is written or how the testing code
is written.


Here is the template method:


public void
run
() {




setUp();




runTest();




tearDown();


}

The default implementations of these methods do nothing:


protected void
runTest
() {


}


protected void
se
tUp
() {


}


protected void
tearDown
() {


}

Since setUp and tearDown are intended to be overridden but will be called by the framework we declare them as
protected. The second snapshot of our tour is depicted in Figure 2.




Figure 2

TestCase.run() applies Template Method

3.3 Reporting results
-

TestResult


If a TestCase runs in a forest, does anyone care about the result? Sure
-

you run tests to make sure they run. After the test

has run, you want a record, a summary of what did and didn’t work.


If tests had equal chances of succeeding or failing, or if we only ever ran one test, we could just set a flag in the
TestCase object and go look at the flag when the test completed. Howe
ver, tests are (intended to be) highly asymmetric
-

they usually work. Therefore, we only want to record the failures and a highly condensed summary of the successes.


The Smalltalk Best Practice Patterns (see Beck, K. Smalltalk Best Practice Patterns, Pren
tice Hall, 1996) has a pattern
that is applicable. It is called
Collecting Parameter
. It suggests that when you need to collect results over several
methods, you should add a parameter to the method and pass an object that will collect the results for you.

We create a
new object, TestResult, to collect the results of running tests.


public class
TestResult

extends Object {




protected int fRunTests;




public
TestResult
() {




fRunTests= 0;




}


}

This simple version of TestResult only counts t
he number of tests run. To use it, we have to add a parameter to the
TestCase.run() method and notify the TestResult that the test is running:


public void
run
(TestResult result) {




result.startTest(this);




setUp();




runTest();




tearDown();


}

And the TestResult has to keep track of the number of tests run:


public synchronized void
startTest
(Test test) {




fRunTests++;


}

We declare the TestResult method startTest as synchronized so that a single TestResult can collect the results safely

when the tests are run in different threads. Finally, we want to retain the simple external interface of TestCase, so we
create a no
-
parameter version of run() that creates its own TestResult:


public TestResult
run
() {




TestResult result= createResul
t();




run(result);




return result;


}


protected TestResult
createResult
() {




return new TestResult();


}

Figure 3 shows our next design snapshot.




Figure 3: Tes
tResult applies Collecting Parameter

If tests always ran correctly, then we wouldn’t have to write them. Tests are interesting when they fail, especially if we
didn’t expect them to fail. What’s more, tests can fail in ways that we expect, for example by c
omputing an incorrect
result, or they can fail in more spectacular ways, for example by writing outside the bounds of an array. No matter how
the test fails we want to execute the following tests.


JUnit distinguishes between
failures

and
errors
. The possi
bility of a failure is anticipated and checked for with
assertions. Errors are unanticipated problems like an ArrayIndexOutOfBoundsException. Failures are signaled with an
AssertionFailedError error. To distinguish an unanticipated error from a failure, fa
ilures are caught in an extra catch
clause (1). The second clause (2) catches all other exceptions and ensures that our test run continues..


public void
run
(TestResult result) {




result.startTest(this);




setUp();




try {




runTest();





}




catch (AssertionFailedError e) { //1




result.addFailure(this, e);




}




catch (Throwable e) { // 2




result.addError(this, e);




}




finally {




tearDown();




}


}

An AssertionFailedError is triggered by the as
sert methods provided by TestCase. JUnit provides a set of assert methods
for different purposes. Here is the simplest one:


protected void
assertTrue
(boolean condition) {




if (!condition)




throw new AssertionFailedError();


}

The AssertionFail
edError is not meant to be caught by the client (a testing method inside a TestCase) but inside the
Template Method TestCase.run(). We therefore derive AssertionFailedError from Error.


public class
AssertionFailedError

extends Error {




public Assertio
nFailedError () {}


}

The methods to collect the errors in TestResult are shown below:


public synchronized void
addError
(Test test, Throwable t) {




fErrors.addElement(new TestFailure(test, t));


}


public synchronized void
addFailure
(Test test, Throwa
ble t) {




fFailures.addElement(new TestFailure(test, t));


}

TestFailure is a little framework internal helper class to bind together the failed test and the signaled exception for later

reporting.


public class
TestFailure

extends Object {




protec
ted Test fFailedTest;




protected Throwable fThrownException;


}

The canonical form of collecting parameter requires us to pass the collecting parameter to each method. If we followed
this advice, each of the testing methods would require a parameter fo
r the TestResult. This results in a "pollution" of
these method signatures. As a benevolent side effect of using exceptions to signal failures we can avoid this signature
pollution. A test case method, or a helper method called from it, can throw an except
ion without having to know about
the TestResult. As a refresher here is a sample test method from our MoneyTest suite. It illustrates how a testing method
doesn’t have to know anything about a TestResult:


public void
testMoneyEquals
() {




assertTrue(!f
12CHF.equals(null));




assertEquals(f12CHF, f12CHF);




assertEquals(f12CHF, new Money(12, "CHF"));




assertTrue(!f12CHF.equals(f14CHF));


}

JUnit comes with different implementations of TestResult. The default implementation counts the number of f
ailures
and errors and collects the results. TextTestResult collects the results and presents them in a textual form. Finally,
UITestResult is used by the graphical version of the JUnit Test Runner to update the graphical test status.


TestResult is an ext
ension point of the framework. Clients can define their own custom TestResult classes, for example,
an HTMLTestResult reports the results as an HTML document.


3.4 No stupid subclasses
-

TestCase again


We have applied Command to represent a test. Command
relies on a single method like execute() (called run() in
TestCase) to invoke it. This simple interface allows us to invoke different implementations of a command through the
same interface.


We need an interface to generically run our tests. However, all
test cases are implemented as different methods in the
same class. This avoids the unnecessary proliferation of classes. A given test case class may implement many different
methods, each defining a single test case. Each test case has a descriptive name l
ike testMoneyEquals or testMoneyAdd.
The test cases don’t conform to a simple command interface. Different instances of the same Command class need to be
invoked with different methods. Therefore our next problem is make all the test cases look the same fr
om the point of
view of the invoker of the test.


Reviewing the problems addressed by available design patterns, the Adapter pattern springs to mind. Adapter has the
following intent "Convert the interface of a class into another interface clients expect".

This sounds like a good match.
Adapter tells us different ways to do this. One of them is a class adapter, which uses subclassing to adapt the interface.
For example, to adapt testMoneyEquals to runTest we implement a subclass of MoneyTest and override ru
nTest to
invoke testMoneyEquals.


public class
TestMoneyEquals

extends MoneyTest {




public TestMoneyEquals() { super("testMoneyEquals"); }




protected void runTest () { testMoneyEquals(); }


}

The use of subclassing requires us to implement a subcla
ss for each test case. This puts an additional burden on the
tester. This is against the JUnit goal that the framework should make it as simple as possible to add a test case. In
addition, creating a subclass for each testing method results in class bloat.

Many classes with only a single method are
not worth their costs and it will be difficult to come up with meaningful names.


Java provides anonymous inner classes which provide an interesting Java
-
specific solution to the class naming problem.
With anonym
ous inner classes we can create an Adapter without having to invent a class name:


TestCase test= new MoneyTest("testMoneyEquals ") {




protected void runTest() { testMoneyEquals(); }


};

This is much more convenient than full subclassing. It preserves
compile
-
time type checking at the cost of some burden
on the developer. Smalltalk Best Practice Patterns describes another solution for the problem of different instances
behaving differently under the common heading of
pluggable behavior
. The idea is to u
se a single class which can be
parameterized to perform different logic without requiring subclassing.


The simplest form of pluggable behavior is the
Pluggable Selector
. Pluggable Selector stores a Smalltalk method
selector in an instance variable. This i
dea is not limited to Smalltalk. It is also applicable to Java. In Java there is no
notion of a method selector. However, the Java reflection API allows us to invoke a method from a string representing
the method’s name. We can use this feature to implemen
t a pluggable selector in Java. As an aside, we usually don’t use
reflection in ordinary application code. In our case we are dealing with an infrastructure framework and it is therefore
OK to wear the reflection hat.


JUnit offers the client the choice of

using pluggable selector or implementing an anonymous adapter class as shown
above. To do so, we provide the pluggable selector as the default implementation of the runTest method. In this case the
name of the test case has to correspond to the name of a
test method. We use reflection to invoke the method as shown
below. First we look up the Method object. Once we have the method object we can invoke it and pass its arguments.
Since our test methods take no arguments we can pass an empty argument array:


p
rotected void
runTest
() throws Throwable {




Method runMethod= null;




try {




runMethod= getClass().getMethod(fName, new Class[0]);




} catch (NoSuchMethodException e) {




assertTrue("Method
\
""+fName+"
\
" not found", false);




}




try {




runMethod.invoke(this, new Class[0]);




}




// catch InvocationTargetException and IllegalAccessException


}

The JDK 1.1 reflection API only allows us to find public methods. For this reason you have to declare the test methods
as

public, otherwise you will get a NoSuchMethodException.


Here is the next design snapshot, with Adapter and Pluggable Selector added.




Figure 4: TestCase applies either Ada
pter with an anonymous inner class or Pluggable Selector

3.5 Don’t care about one or many
-

TestSuite


To get confidence in the state of a system we need to run many tests. Up to this point JUnit can run a single test case
and report the result in a TestRe
sult. Our next challenge is to extend it so that it can run many different tests. This
problem can be solved easily when the invoker of the tests doesn’t have to care about whether it runs one or many test
cases. A popular pattern to pull out in such a sit
uation is Composite. To quote its intent "Compose objects into tree
structures to represent part
-
whole hierarchies. Composite lets clients treat individual objects and compositions of
objects uniformly." The point about part
-
whole hierarchies is of interes
t here. We want to support suites of suites of
suites of tests.


Composite introduces the following participants:




Component: declares the interface we want to use to interact with our tests.




Composite: implements this interface and maintains a collection

of tests.




Leaf: represents a test case in a composition that conforms to the Component interface.


The pattern tells us to introduce an abstract class which defines the common interface for single and composite objects.
The primary purpose of the class i
s to define an interface. When applying Composite in Java we prefer to define an
interface and not an abstract class. Using an interface avoids committing JUnit to a specific base class for tests. All that
is required is that the tests conform to this inte
rface. We therefore tweak the pattern description and introduce a Test
interface:


public interface
Test

{




public abstract void run(TestResult result);


}

TestCase corresponds to a Leaf in Composite and implements this interface as we have seen above.


Next, we introduce the Composite participant. We name the class TestSuite. A TestSuite keeps its child tests in a Vector:


public class
TestSuite

implements
Test

{




private Vector fTests= new Vector();


}

The run() method delegates to its children:


public void
run
(TestResult result) {




for (Enumeration e= fTests.elements(); e.hasMoreElements(); ) {




Test test= (Test)e.nextElement();




test.run(result);




}


}



Figure 5: TestSuite applies Composite

Finally, clients have to be able to add tests to a suite, they can do so with the method addTest:


public void
addTest
(Test test) {




fTests.addElement(test);


}

Notice how all of the above code only de
pends on the Test interface. Since both TestCase and TestSuite conform to the
Test interface we can recursively compose suites of test suites. All developers can create their own TestSuites. We can
run them all by creating a TestSuite composed of those sui
tes.


Here is an example of creating a TestSuite:


public static Test
suite
() {




TestSuite suite= new TestSuite();




suite.addTest(new MoneyTest("testMoneyEquals"));




suite.addTest(new MoneyTest("testSimpleAdd"));


}

This works fine, but it requ
ires us to add all the tests to a suite manually. Early adopters of JUnit told us this was stupid.
Whenever you write a new test case you have to remember to add it to a static suite() method, otherwise it will not be
run. We added a convenience constructo
r to TestSuite which takes the test case class as an argument. Its purpose is to
extract the test methods and create a suite containing them. The test methods must follow the simple convention that
they start with the prefix "test" and take no arguments. T
he convenience constructor uses this convention, constructing
the test objects by using reflection to find the testing methods. Using this constructor the above code is simplified to:


public static Test
suite
() {




return new TestSuite(MoneyTest.class)
;


}

The original way is still useful when you want to run a subset of the test cases only.


3.6 Summary


We are at the end of our cook’s tour through JUnit. The following figure shows the design of JUnit at a glance explained
with patterns.




Figure 6: JUnit Patterns Summary

Notice how TestCase, the central abstraction in the framework, is involved in four patterns. Pictures of mature object
designs show this same "pattern de
nsity". The star of the design has a rich set of relationships with the supporting
players.


Here is another way of looking at all of the patterns in JUnit. In this storyboard you see an abstract representation of the
effect of each of the patterns in turn
. So, the Command pattern creates the TestCase class, the Template Method pattern
creates the run method, and so on. (The notation of the storyboard is the notation of figure 6 with all the text deleted).




Figure 7: JUnit Pattern Storyboard

One point to notice about the storyboard is how the complexity of the picture jumps when we apply Composite. This is
pictorial corroboration for our intuition that Composite is a powerful
pattern, but that it "complicates the picture." It
should therefore be used with caution.


4. Conclusion


To conclude, let’s make some general observations:




Patterns


We found discussing the design in terms of patterns to be invaluable, both as we were de
veloping the
framework and as we try to explain it to others. You are now in a perfect position to judge whether describing a
framework with patterns is effective. If you liked the discussion above, try the same style of presentation for
your own system.




Pattern density


There is a high pattern "density" around TestCase, which is the key abstraction of JUnit. Designs with high
pattern density are easier to use but harder to change. We have found that such a high pattern density around
key abstractions is c
ommon for mature frameworks. The opposite should be true of immature frameworks
-

they should have low pattern density. Once you discover what problem you are really solving, then you can
begin to "compress" the solution, leading to a denser and denser fie
ld of patterns where they provide leverage.




Eat your own dog food


As soon as we had the base unit testing functionality implemented, we applied it ourselves. A TestTest verifies
that the framework reports the correct results for errors, successes, and fa
ilures. We found this invaluable as we
continued to evolve the design of the framework. We found that the most challenging application of JUnit was
testing its own behavior.




Intersection, not union


There is a temptation in framework development to includ
e every feature you can. After all, you want to make
the framework as valuable as possible. However, there is a counteracting force
-

developers have to decide to
use your framework. The fewer features the framework has, the easier it is to learn, the more
likely a developer
will use it. JUnit is written in this style. It implements only those features absolutely essential to running tests
-

running suites of tests, isolating the execution of tests from each other, and running tests automatically. Sure,
we co
uldn’t resist adding some features but we were careful to put them into their own extensions package
(test.extensions). A notable member of this package is a TestDecorator allowing execution of additional code
before and after a test.




Framework writers re
ad their code


We spent far more time reading the JUnit code than we spent writing it, and nearly as much time removing
duplicate functionality as we spent adding new functionality. We experimented aggressively with the design,
adding new classes and movin
g responsibility around in as many different ways as we could imagine. We were
rewarded (and are still being rewarded) for our monomania by a continuous flow of insights into JUnit, testing,
object design, framework development, and opportunities for furth
er articles.

The latest version of JUnit can be downloaded from http://www.junit.org.


5. Acknowledgements


Thanks to John Vlissides, Ralph Johnson, and Nick Edgar for careful reading and gentle correction.



source: http://junit.sourceforge.net/doc/cookst
our/cookstour.htm



JUnit Primer

This article demonstrates a quick and easy way to write and run
JUnit

test cases and test suites.
We'll start by reviewing the key benefits of using JUnit and then write some

example tests to
demonstrate its simplicity and effectiveness.

Table of Contents

This article contains the following sections:



Introduction




Why Use JUnit?




Design of JUnit




Step 1: Install JUnit




Step 2: Write a Test Case




Step 3: Write a Test Suite




Step 4: Run the Tests




Step 5: Organize the Tests




Testing Idioms




Training




Resources


Why Use JUnit?

Before we begin, it's worth asking why we should use JUnit at all. The subject of unit te
sting always
conjures up visions of long nights slaving over a hot keyboard trying to meet the project's test case
quota. However, unlike the Draconian style of conventional unit testing, using JUnit actually helps
you write code faster while increasing co
de quality. Once you start using JUnit you'll begin to
notice a powerful synergy emerging between coding and testing, ultimately leading to a
development style of only writing new code when a test is failing.

Here are just a few reasons to use JUnit:



JUn
it tests allow you to write code faster while increasing quality.


Yeah, I know, it sounds counter
-
intuitive, but it's true! When you write tests using JUnit,
you'll spend less time debugging, and you'll have confidence that changes to your code
actually w
ork. This confidence allows you to get more aggressive about refactoring code and
adding new features.

Without tests, it's easy to become paranoid about refactoring or adding new features because
you don't know what might break as a result. With a compreh
ensive test suite, you can
quickly run the tests after changing the code and gain confidence that your changes didn't
break anything. If a bug is detected while running tests, the source code is fresh in your
mind, so the bug is easily found. Tests written

in JUnit help you write code at an extreme
pace and spot defects quickly.



JUnit is elegantly simple.


Writing tests should be simple
-

that's the point! If writing tests is too complex or takes too
much time, there's no incentive to start writing tests i
n the first place. With JUnit, you can
quickly write tests that exercise your code and incrementally add tests as the software grows.

Once you've written some tests, you want to run them quickly and frequently without
disrupting the creative design and de
velopment process. With JUnit, running tests is as easy
and fast as running a compiler on your code. In fact, you should run your tests every time
you run the compiler. The compiler tests the syntax of the code and the tests validate the
integrity of the c
ode.



JUnit tests check their own results and provide immediate feedback.


Testing is no fun if you have to manually compare the expected and actual result of tests,
and it slows you down. JUnit tests can be run automatically and they check their own
resul
ts. When you run tests, you get simple and immediate visual feedback as to whether the
tests passed or failed. There's no need to manually comb through a report of test results.



JUnit tests can be composed into a hierarchy of test suites.


JUnit tests can

be organized into test suites containing test cases and even other test suites.
The composite behavior of JUnit tests allows you to assemble collections of tests and
automatically regression test the entire test suite in one fell swoop. You can also run t
he tests
for any layer within the test suite hierarchy.



Writing JUnit tests is inexpensive.


Using the JUnit testing framework, you can write tests cheaply and enjoy the convenience
offered by the testing framework. Writing a test is as simple as writing
a method that
exercises the code to be tested and defining the expected result. The framework provides the
context for running the test automatically and as part of a collection of other tests. This small
investment in testing will continue to pay you back

in time and quality.



JUnit tests increase the stability of software.


The fewer tests you write, the less stable your code becomes. Tests validate the stability of
the software and instill confidence that changes haven't caused a ripple
-
effect through th
e
software. The tests form the glue of the structural integrity of the software.



JUnit tests are developer tests.


JUnit tests are highly localized tests written to improve a developer's productivity and code
quality. Unlike functional tests, which treat
the system as a black box and ensure that the
software works as a whole, unit tests are written to test the fundamental building blocks of
the system from the inside out.

Developer's write and own the JUnit tests. When a development iteration is complete,

the
tests are promoted as part and parcel of the delivered product as a way of communicating,
"Here's my deliverable and the tests which validate it."



JUnit tests are written in Java.


Testing Java software using Java tests forms a seamless bond between
the test and the code
under test. The tests become an extension to the overall software and code can be refactored
from the tests into the software under test. The Java compiler helps the testing process by
performing static syntax checking of the unit tes
ts and ensuring that the software interface
contracts are being obeyed.



JUnit is free!


Design of JUnit

JUnit is designed around two key design patterns: the
Command

pattern and the
Composite

pattern.

A
TestCase

is a command object. Any class that contai
ns test methods should subclass the
TestCase

class. A
TestCase

can define any number of public
testXXX()

methods. When
you want to check the expected and actual test results, you invoke a variation of the
assert()

method.

TestCase

subclasses that contain
multiple
testXXX()

methods can use the
setUp()

and
tearDown()

methods to initialize and release any common objects under test, referred to as the
test fixture. Each test runs in the context of its own fixture, calling
setUp()

before and
tearDown()

after ea
ch test method to ensure there can be no side effects among test runs.

TestCase

instances can be composed into
TestSuite

hierarchies that automatically invoke all
the
testXXX()

methods defined in each
TestCase

instance. A
TestSuite

is a composite of
other

tests, either
TestCase

instances or other
TestSuite

instances. The composite behavior
exhibited by the
TestSuite

allows you to assemble test suites of test suites of tests, to an
arbitrary depth, and run all the tests automatically and uniformly to yield
a single pass or fail status.

Step 1: Install JUnit

1.

First,
download

the latest version of JUnit, referred to below as
junit.zip
.

2.

Then install JUnit on your platform of choice:

W
indows


To install JUnit on Windows, follow these steps:

1.

Unzip the
junit.zip

distribution file to a directory referred to as
%JUNIT_HOME%
.

2.

Add JUnit to the classpath:


set CLASSPATH=%JUNIT_HOME%
\
junit.jar

Unix (bash)


To install JUnit on Unix, follow

these steps:

3.

Unzip the
junit.zip

distribution file to a directory referred to as
$JUNIT_HOME
.

4.

Add JUnit to the classpath:


export CLASSPATH=$JUNIT_HOME/junit.jar

3.

Test the installation by using either the textual or graphical test runner to run the sam
ple tests
distributed with JUnit.

Note: The sample tests are not contained in the
junit.jar
, but in the installation
directory directly. Therefore, make sure that the JUnit installation directory is in the
CLASSPATH.

To use the textual test runner, type:



java junit.textui.TestRunner junit.samples.AllTests

To use the graphical test runner, type:


java junit.swingui.TestRunner junit.samples.AllTests

All the tests should pass with an "OK" (textual runner) or a green bar (graphical runner). If
the test
s don't pass, verify that
junit.jar

is in the CLASSPATH.

Step 2: Write a Test Case

First, we'll write a test case to exercise a single software component. We'll focus on writing tests
that exercise the component behavior that has the highest potential for

breakage, thereby
maximizing our return on testing investment.

To write a test case, follow these steps:

1.

Define a subclass of
TestCase
.

2.

Override the
setUp()

method to initialize object(s) under test.

3.

Optionally override the
tearDown()

method to releas
e object(s) under test.

4.

Define one or more public
testXXX()

methods that exercise the object(s) under test and
assert expected results.

The following is an example test case:

import junit.framework.TestCase;


public class ShoppingCartTest extends TestCa
se {



private ShoppingCart cart;


private Product book1;



/**


* Sets up the test fixture.


*


* Called before every test case method.


*/


protected void setUp() {



cart = new ShoppingCart();



book1 = new Prod
uct("Pragmatic Unit Testing", 29.95);



cart.addItem(book1);


}



/**


* Tears down the test fixture.


*


* Called after every test case method.


*/


protected void tearDown() {


// release objects under test here, if

necessary


}



/**


* Tests emptying the cart.


*/


public void testEmpty() {



cart.empty();




assertEquals(0, cart.getItemCount());


}



/**


* Tests adding an item to the cart.


*/


public void testAd
dItem() {



Product book2 = new Product("Pragmatic Project Automation", 29.95);


cart.addItem(book2);



double expectedBalance = book1.getPrice() + book2.getPrice();




assertEquals(expectedBalance, cart.getBalance(), 0.0);




assertEquals(2, cart.getItemCount());


}



/**


* Tests removing an item from the cart.


*


* @throws ProductNotFoundException If the product was not in the cart.


*/


public void testRemoveItem() throws ProductNotFoundExcepti
on {



cart.removeItem(book1);



assertEquals(0, cart.getItemCount());


}



/**


* Tests removing an unknown item from the cart.


*


* This test is successful if the


* ProductNotFoundException is raised.


*/


pu
blic void testRemoveItemNotInCart() {



try {



Product book3 = new Product("Pragmatic Version Control", 29.95);


cart.removeItem(book3);



fail("Should raise a ProductNotFoundException");



} catch(ProductNot
FoundException expected) {


// successful test


}


}

}

(The complete source code for this example is available in the
Resources

section).


Step 3: Write a Te
st Suite

Next, we'll write a test suite that includes several test cases. The test suite will allow us to run all of
its test cases in one fell swoop.

To write a test suite, follow these steps:

1.

Write a Java class that defines a static
suite()

factory met
hod that creates a
TestSuite

containing all the tests.

2.

Optionally define a
main()

method that runs the
TestSuite

in batch mode.

The following is an example test suite:

import junit.framework.Test;

import junit.framework.TestSuite;


public class Ecommerc
eTestSuite {




public static Test suite() {



TestSuite suite = new TestSuite();




//


// The ShoppingCartTest we created above.


//


suite.addTestSuite(ShoppingCartTest.class);



//


// Another examp
le test suite of tests.


//


suite.addTest(CreditCardTestSuite.suite());



//


// Add more tests here


//



return suite;


}



/**


* Runs the test suite using the textual runner.


*/


public stat
ic void main(String[] args) {


junit.textui.TestRunner.run(suite());


}

}

Step 4: Run the Tests

Now that we've written a test suite containing a collection of test cases and other test suites, we can
run either the test suite or any of its test c
ases individually. Running a
TestSuite

will
automatically run all of its subordinate
TestCase

instances and
TestSuite

instances. Running
a
TestCase

will automatically invoke all of its public
testXXX()

methods.

JUnit provides both a textual and a graphica
l user interface. Both user interfaces indicate how many
tests were run, any errors or failures, and a simple completion status. The simplicity of the user
interfaces is the key to running tests quickly. You should be able to run your tests and know the te
st
status with a glance, much like you do with a compiler.

To run our test case using the textual user interface, use:

java junit.textui.TestRunner ShoppingCartTest

The textual user interface displays "OK" if all the tests passed and failure messages if
any of the
tests failed.

To run the test case using the graphical user interface, use:

java junit.swingui.TestRunner ShoppingCartTest

The graphical user interface displays a Swing window with a green progress bar if all the tests
passed or a red progress

bar if any of the tests failed.

The
EcommerceTestSuite

can be run similarly:

java junit.swingui.TestRunner EcommerceTestSuite

Step 5: Organize the Tests

The last step is to decide where the tests will live within our development environment.

Here's the

recommended way to organize tests:

1.

Create test cases in the same package as the code under test. For example, the
com.mydotcom.ecommerce

package would contain all the application
-
level classes as
well as the test cases for those components.

2.

To avoid com
bining application and testing code in your source directories, create a
mirrored directory structure aligned with the package structure that contains the test code.

3.

For each Java package in your application, define a
TestSuite

class that contains all the

tests for validating the code in the package.

4.

Define similar
TestSuite

classes that create higher
-
level and lower
-
level test suites in the
other packages (and sub
-
packages) of the application.

5.

Make sure your build process includes the compilation of all

tests. This helps to ensure that
your tests are always up
-
to
-
date with the latest code and keeps the tests fresh.

By creating a
TestSuite

in each Java package, at various levels of packaging, you can run a
TestSuite

at any level of abstraction. For examp
le, you can define a
com.mydotcom.AllTests

that runs all the tests in the system and a
com.mydotcom.ecommerce.EcommerceTestSuite

that runs only those tests validating
the e
-
commerce components.

The testing hierarchy can extend to an arbitrary depth. Depen
ding on the level of abstraction you're
developing at in the system, you can run an appropriate test. Just pick a layer in the system and test
it!

Here's an example test hierarchy:

AllTests (Top
-
level Test Suite)


SmokeTestSuite (Structural Integrity
Tests)


EcommerceTestSuite


ShoppingCartTestCase


CreditCardTestSuite


AuthorizationTestCase


CaptureTestCase


VoidTestCase


UtilityTestSuite


MoneyTestCas
e


DatabaseTestSuite


ConnectionTestCase


TransactionTestCase


LoadTestSuite (Performance and Scalability Tests)


DatabaseTestSuite


ConnectionPoolTestCase


ThreadPoolTestCase

Testing Idioms

Keep the

following things in mind when writing JUnit tests:



The software does well those things that the tests check.



Test a little, code a little, test a little, code a little...



Make sure all tests always run at 100%.



Run all the tests in the system at least

once per day (or night).



Write tests for the areas of code with the highest probability of breakage.



Write tests that have the highest possible return on your testing investment.



If you find yourself debugging using
System.out.println()
, write a test t
o
automatically check the result instead.



When a bug is reported, write a test to expose the bug.



The next time someone asks you for help debugging, help them write a test.



Write unit tests before writing the code and only write new code when a test is
failing.

Resources



JUnit

-

The official JUnit website



JUnit FAQ

-

Frequently asked questions and answers



A Dozen Ways to Get the Testing Bug

by Mike Clark (java.net, 2004)



Pragmatic Unit Testing

by Andy Hunt and Dave Thomas

(The Pragmatic Programmers,
2003)

source: http://clarkware.com/articles/JUnitPrimer.html


A Dozen Ways to Get the Testing Bug in the New Year



Published on
Jav
a.net

(
http://www.java.net
)

Home

> A Dozen Ways to Get the Testing Bug in the New Year


This article gives you 12 practical ways to start (and keep) writing tests, regardless of your

development process. Testing is important, and writing tests first results in the emergence of better
designs.

A dozen ways to get the testing bug

January 22, 2004

Mike Clark

[1]
This article gives you 12 p
ractical ways to start (and keep) writing tests, regardless of your
development process. Testing is important, and writing tests first results in the emergence of better
designs.

Test
-
driven development received a lot of attention in 2003, and the interest

will grow in 2004. For
good reason: everyone agrees testing is important, but now many respected programmers are
claiming that by writing tests first, they see better designs emerge. These same programmers
quickly point out that test
-
driven development ma
kes them feel more productive and less stressed.
At the end of a shorter programming day they've built a suite of passing tests
and

code with better
designs. Sound too good to be true? Well, there's nothing to lose in giving it a whirl. In fact, there's
mu
ch to be gained.

This article gives you 12 practical ways to start writing tests, and keep writing tests, regardless of
your development process. The first two techniques play off of things you're probably already
doing, so you don't have to move too far o
ut of your comfort zone. The next two challenge you to
wade deeper into the pool to realize the benefits of test
-
driven development. The remaining
techniques round out the regimen to keep you testing effectively all year. You'll be well on your way
to fulf
illing your new year's resolutions. Caution: contents have been known to be infectious!

1. Let Your Computer Do the Boring Stuff

The easiest way to start writing tests is to identify situations where you visually inspect results, then
replace that human ch
ecking process with automated checking. Color me lazy, but I want to put this
thing called a computer to work for me. It's much more reliable than I am at keeping my
expectations in check. Some results are difficult to check without a human in the loop; do
n't start
there. Instead, go after low
-
hanging fruit to get a few small victories under your belt. I've found the
pervasive
main()

test driver to be easy pickings for automating. I'm not referring to the entry
point that bootstraps your application, but ra
ther the
main()

method that acts like a test driver by
printing results to the console.

For example, imagine that you're writing a Java class that performs the functions of a simple
spreadsheet. A spreadsheet cell
--

indexed by a column and row combinatio
n such as "A1"
--

can
store a number or a formula that may include numbers and cell references. Here's an example
main()

test driver for the
Spreadsheet

class:

public static void main(String args[]) {




Spreadsheet sheet = new Spreadsheet();





System.out.println("Cell reference:");


sheet.put("A1", "5");


sheet.put("A2", "=A1");


System.out.println("A2 = " + sheet.get("A2"));




System.out.println("
\
nCell change propagates:");


sheet.put("A1", "10");


System.ou
t.println("A2 = " + sheet.get("A2"));




System.out.println("
\
nFormula calculation:");


sheet.put("A1", "5");


sheet.put("A2", "2");


sheet.put("B1", "=A1*(A1
-
A2)+A2/3");


System.out.println("B1 = " + sheet.get("B1"));

}

You may recog
nize this testing style or may have even written similar test drivers yourself, if only
to give you some confidence that the code produced the results you expected. The
main()

method
was my testing harness of choice for many years, and I still get the urge

to use it from time to time
because it's easy. But just as I'm about to take the bait, I remember how a
main()

test driver sucks
the life out of me. See, every time I change code that affects the
Spreadsheet

class, I want to
run the test to see if my chan
ge broke anything. I'm confident in my changes if I run the test
afterward and see the following console output:

Cell reference:

A2 = 5


Cell change propagates:

A2 = 10


Formula calculation:

B1 = 15

This testing approach has at least one problem: it requir
es that I visually inspect the output every
time I run the test. Worse yet, as the number of results output by the test driver increases, my
workload also increases. I'll quickly grow weary of doing work best suited for a computer and stop
running the test

altogether. Inspecting the output also implies that between test runs I have to
remember how the expected output should look. Is the correct result of the formula calculation 10
or 15? Hmm, I can't remember. And if I can't remember, there's little hope of

sharing the test with
other folks.

JUnit is a computer's taskmaster when it comes to checking expectations. If you've never used
JUnit, the
JUnit FAQ

[13] will
get you up and running in less time than it takes to type a
main()

method signature. Using JUnit, a
main()

test driver requiring human checking can be easily
replaced by automated tests that check their own results. Here's the equivalent
Spreadsheet

test,
expressed in a JUnit test:

import junit.framework.TestCase;


public class SpreadsheetTest extends TestCase {




public void testCellReference() {


Spreadsheet sheet = new Spreadsheet();


sheet.put("A1", "5");


sheet.put("A2", "=A
1");


assertEquals("5", sheet.get("A2"));


}



public void testCellChangePropagates() {


Spreadsheet sheet = new Spreadsheet();


sheet.put("A1", "5");


sheet.put("A2", "=A1");


sheet.put("A1", "10");


assertE
quals("10", sheet.get("A2"));


}



public void testFormulaCalculation() {


Spreadsheet sheet = new Spreadsheet();


sheet.put("A1", "5");


sheet.put("A2", "2");


sheet.put("B1", "=A1*(A1
-
A2)+A2/3");


assertEquals("15
", sheet.get("B1"));


}

}

Notice that the result checking is now codified in the use of
assertEquals()

methods that
automatically check whether the expected value (the first parameter) matches the actual value (the
second parameter). There's no need for

you to remember what the correct results should be.

JUnit is distributed with two test runners
--

textual and graphical
--

that both produce simple and
unambiguous output. Using the textual runner, an "OK" on the console signifies that all of your
expect
ations were met:

> java junit.textui.TestRunner SpreadsheetTest


...

Time: 0.04


OK (3 tests)

Using the graphical runner (
junit.swingui.TestRunner
), you're looking for a comforting
green bar. Most Java IDEs have an integrated graphical runner just waiting
to stroke your ego, such
as this runner in
Eclipse

[14]:


Figure 1. Green is good

If your expectations aren't met, JUnit is quick to let you know. Depending on the test runner
used, if
a test fails, you'll either see an eye
-
popping failure message on the console or a flaming red bar,
along with details of the failed test.

Automation isn't necessarily testing, you say? I couldn't agree more. So now that you have an
automated test

harness that takes the pain out of manual testing, feel free to write more
comprehensive tests. The book
Pragmatic Unit Testing

[15] wi
ll help you strengthen your testing
skills and write better tests. As you write more tests, it doesn't cost you anything to keep them
running. Indeed, automated tests increase in value over time as ongoing regression tests, so that you
have more time to wr
ite good tests.

2. Stop Debugger Testing

There was a time when I followed the conventional wisdom of running my code through a debugger
to check that the code worked as I expected. That approach worked well, if only I never had to
change the code again. B
ut then when the code needed to be changed, I resisted the change because
I dreaded firing up the debugger and walking through the code. In other words, using the debugger
as a regression testing tool had the same drawbacks as using the
main()

method as a
test driver. It
just didn't scale. Consequently, I tended not to touch working code for fear of unknowingly
breaking something. The result was code rot.

If you're like me, you use a debugger to validate mental assertions as follows:

1.

Set a breakpoint right
before a section of code you have questions about.

2.

Set watches on interesting variables within that code section.

3.

Run the program up to the breakpoint.

4.

Single
-
step through each line, examining the variables along the way.

5.

Optionally, manipulate variabl
es on the fly to force certain code paths to be exercised.

The entire time I'm doing this, in my head I have expectations about the values of variables and the
results of method calls. The debugger merely gives me answers that I then match against my
expe
ctations. That is, when I use a debugger, I'm really settling for human checking that's prone to
error and boredom.

Look for opportunities to replace the human checking you do via debugger with an automated test
that checks its own results. It's not always

easy to initialize the environment required by a section of
code you'd like to test. After all, it's running the program up to the breakpoint that builds that
context around the code, though usually at a significant start
-
up cost. But if the code is likel
y to
undergo change that might break it, then it's worth finding a way to write an automated test. In
doing so, you might just discover that the code being tested can be decoupled from some of its
dependencies.

3. Assert Your Expectations

A lot has been w
ritten about test
-
driven development, summed up in this simple recipe:

1.

Write new code only after an automated test has failed.

2.

Refactor to keep the code clean.

The notion of writing a failing test before writing the code that makes it pass may seem awkwa
rd,
but think about how you write code. Before you write a method, you generally have some idea what
the method should do. If you don't, one might argue you're not yet ready to write the method.
Writing the test first is typically easier and quicker than w
riting the corresponding code. The test
then keeps you from wandering down rabbit holes and lets you know when you're done coding. So,
before writing that next method, stop to consider what expectations you already have in mind.
Assume you've already writt
en the method, then simply write an automated test that asserts that the
method works correctly.

Say, for example, you're staring at a blank editor screen, ready to begin writing a
ShoppingCart

class. The first thing you want it to do is manage a collecti
on of items. If the same item is added
twice, each time with a specified quantity, the shopping cart should contain the sum of both
quantities. Now turn that mental assertion
--

the success criteria for the code you wish you had
--

into an automated test.
The following is an example JUnit test:

import junit.framework.TestCase;


public class ShoppingCartTest extends TestCase {



public void testAddItems() {


ShoppingCart cart = new ShoppingCart();


cart.addItems("Snowboard", 1);


car
t.addItems("Lift Ticket", 2);


cart.addItems("Snowboard", 1);


assertEquals(4, cart.itemCount());


}

}

Serious question: how much more effort would it take to write that test after you'd already expended
brain cycles deciding what the shop
ping cart should do? Think of test
-
driven development as a way
of structuring and refining that thought process.

Now that you have a test, write just enough code to make it pass. No more, no less. Just let the test
guide you rather than speculating about w
hat you might need in the future or worrying about the
next test. When the test passes, refactor the code as necessary to keep it clean and as simple as
possible. Then re
-
run the test to make sure refactoring didn't break anything. Repeat by asserting
your

expectations for what the code should do next. Before long you'll fall into your own test
-
code
-
refactor rhythm. Stick with it; it will serve you well.

4. Think of It as Design

Writing tests first is a design activity because it forces you to think through

how the code should
work from the outside before diving into an implementation. In good time and with practice, you'll
notice test
-
driven development is more of a design technique than a testing technique. But if you go
looking for stunning design insight
s with your first tests, you'll be disappointed. For now, just listen
to what the tests are trying to tell you about your design by paying careful attention to difficulties
writing the tests. Tests are just another client of your code, and writing the test
s first gives you a
client's perspective. If the code is difficult to test, it follows that it will be difficult for a client to
use.

Here's an example design scenario: you're writing a shopping cart application. Client code should be
able to add named ite
ms to a shopping cart and retrieve detailed information for the items currently
in the cart. Without worrying about the infrastructure necessary to support the shopping cart, start
by writing a JUnit test similar to the following:

public void testGetItem(
) {



ShoppingCart cart = new ShoppingCart();


cart.addItems("ISBN123", 1);




Iterator items = cart.items();


Product item = (Product)items.next();




assertEquals("Confessions of an OO Hired Gun", item.getDescription());


assertEquals(9.95, item.getUnitCost(), 0.0);


assertEquals(1, item.getQuantity());

}

This test documents how you'd want the ideal
ShoppingCart

class to look and behave from the
outside. The test won't pass; nay, it won't even compile. But how much code
do you need to write to
make the test pass? Remember, somehow you need to swizzle a named item ("ISBN123") into its
corresponding
Product

instance. Sounds like a good job for a database, eh? Ugh! Setting up a
database and writing JDBC code at this point wi
ll only delay the feedback loop. A passing test
sooner rather than later would do wonders for your confidence. Do you really need a database to
make the test pass? No, you just need a data structure that associates keys with
Product

instances.
You could ce
rtainly take a small step for now just to get the test to pass by hard
-
coding the iterator
to return the expected product. In a subsequent step, you could encapsulate the mapping layer
behind a simple interface:

public interface Catalog {


public void a
ddProduct(String key, Product p);


public Product getProduct(String key);

}

Now you can avoid setting up a database by writing an in
-
memory implementation of the
Catalog

interface that uses something like a
HashMap
. The decision to put off writing a
per
sistent catalog implementation isn't triggered by laziness. Rather, by choosing a natural and
simple implementation first, the
Catalog

interface is naturally clean. Indeed, the test helps you
separate interface design from implementation design so that imp
lementation details don't creep
into the interface. The
Catalog

interface can now be used to decouple the shopping cart from any
particular catalog implementation. Simply construct a
ShoppingCart

with any implementation
of the
Catalog

interface. Here's the

same test refactored to do just that:

public void testGetItem() {



Catalog catalog = new InMemoryCatalog();


catalog.addProduct("ISBN123", new Product("Confessions of an OO Hired Gun",
9.95));



ShoppingCart cart = new ShoppingCart(catalog);



cart.addItems("ISBN123", 1);




Iterator items = cart.items();


Product item = (Product)items.next();




assertEquals("Confessions of an OO Hired Gun", item.getDescription());


assertEquals(9.95, item.getUnitCost(), 0.0);


ass
ertEquals(1, item.getQuantity());

}

Getting this test to pass is markedly easier now that a database isn't in the picture. Yes, you'll
probably need a real database at some point. And you'll want to test that the shopping cart behaves
the same with a real
database plugged in. Until then, the in
-
memory catalog helped you focus on
designing the shopping cart before speculating on infrastructure. Writing the test first revealed an
insight for a design with low coupling and high cohesion: the
ShoppingCart

class

is decoupled
from any particular catalog implementation, and the
Catalog

interface encapsulates details of
how named items are mapped to products.

You don't have to be an OO hired gun to craft good designs. You just have to listen to what the test
says yo
u need, and then write the simplest code that will make it pass. Remember to refactor
between tests to keep the code clean.

5. Build Safety Nets

You wouldn't sign up to compete in a triathlon as your first goal toward exercising more in the new
year; you'l
l experience the same pain and frustration if you attempt to test legacy code as your first
testing exercise. Nothing kills a resolution quicker than going overboard. That being said, unless
you're on a new project, legacy code
--

code already written, but

without tests
--

is a fact of life. And
without tests, legacy code is a liability. You can't change the code for fear of breaking something,
and you usually can't write tests without having to change the code. Rock meets hard place.

When faced with chang
ing legacy code, reduce the risk of breakage by building safety nets. I don't
mean you should halt forward progress to write comprehensive tests for the entire legacy code base.
That is the road to discouragement and lost opportunity cost. Instead, be prag
matic by writing
focused tests that create a safety net around the code you intend to change. Then change the code
and run the tests to ensure that nothing unexpected happened. If you can't write focused tests
without first refactoring, use any other safet
y nets at your disposal to gain confidence, including
existing functional tests or a buddy looking over your shoulder.

Refactoring helps prevent code rot. Safety nets make refactoring safe. If you're writing new code
test
-
first, you're building safety nets

along the way. If you're attempting to refactor legacy code, it's
dangerous without safety nets. Building them isn't always easy, but it's usually well worth it.

6. Learn by Checked Example

Learning how to use third
-
party APIs can be frustrating. If you'r
e lucky, the API might include a
comprehensive JavaDoc. If you're really lucky, the API might even behave as the JavaDoc claims.
Regardless of the documentation (or lack thereof), I learn best by doing. To truly understand how an
API works, I need to write

code that pokes and prods the API to get feedback about my
assumptions. But exploring an API by first attempting to use it in my production code doesn't give
me a warm fuzzy feeling. I hear dear Mom reminding me to "Put my play clothes on." I'd rather
lea
rn in a forgiving environment where I can explore an API with impunity.
Checked examples

provide a safe context for learning.

A checked example is a test, though perhaps not in the traditional sense of the word. Think of it as a
learning test that validate
s your assumptions about how an API behaves, but doesn't necessarily
attempt to uncover errors in the API. For example, say you're writing an application that will use
Lucene

[16]
--

a search engine technology with a Java API. How do you begin writing code that
uses Lucene to search for indexed documents? Start by writing a learning test similar to the
following that checks its own results and teaches

you what you want to learn:

<imports omitted for brevity>


public class LuceneLearningTest extends TestCase {




public void testIndexedSearch() throws Exception {




//


// Prepare a writer to store documents in an in
-
memory index.


//


Directory indexDirectory = new RAMDirectory();


IndexWriter writer =


new IndexWriter(indexDirectory, new StandardAnalyzer(), true);



//


// Create a document to be searched and add it to the index.



//


Document document = new Document();


document.add(Field.Text("contents", "Learning tests build
confidence!"));


writer.addDocument(document);


writer.close();



//


// Search for all indexed documents that
contain a search term.


//


IndexSearcher searcher = new IndexSearcher(indexDirectory);


Query query = new TermQuery(new Term("contents", "confidence"));




Hits hits = searcher.search(query);


assertEquals(1, hits
.length());


}

}

The
LuceneLearningTest

is a standard JUnit test that invokes the Lucene API to index an
example document in an in
-
memory directory (
RAMDirectory
), then asserts that a search for the
word "confidence" in the document's contents yields a
hit. With this test under your belt, you can
continue to grow the learning test suite one test at a time. For each new thing you need to learn,
write a test method and refactor any common test code into the
setUp()

method. The following
refactored version
of the
LuceneLearningTest

includes checked examples for two additional
query types:

<imports omitted for brevity>


public class LuceneLearningTest extends TestCase {



private IndexSearcher searcher;




public void setUp() throws Exception {



Directory indexDirectory = new RAMDirectory();


IndexWriter writer =


new IndexWriter(indexDirectory, new StandardAnalyzer(), true);



Document document = new Document();


document.add(Field.Text("contents", "Learning te
sts build
confidence!"));


writer.addDocument(document);


writer.close();




searcher = new IndexSearcher(indexDirectory);


}



public void testSingleTermQuery() throws Exception {


Query query = new TermQuery(new T
erm("contents", "confidence"));




Hits hits = searcher.search(query);


assertEquals(1, hits.length());


}




public void testBooleanQuery() throws Exception {


Query query =


QueryParser.parse("tests AND co
nfidence", "contents", new
StandardAnalyzer());




Hits hits = searcher.search(query);


assertEquals(1, hits.length());


}



public void testWildcardQuery() throws Exception {


Query query =


QueryParser.parse(
"test*", "contents", new StandardAnalyzer());




Hits hits = searcher.search(query);


assertEquals(1, hits.length());


}

}

Notice that the indexing step has been refactored into the
setUp()

method, which is called prior
to every tes
t method. In this case, the use of the
setUp()

method has four functions:



Removes code duplication from the test methods.



Ensures that the test methods don't affect or rely on each other.



Helps readers of the test understand the purpose of this particula
r set of tests: indexing and
searching.



Serves as a reminder that your application using Lucene will generally index documents less
frequently than it will search documents.

Writing learning tests in isolation helps you focus on one thing at a time. You
first focus on writing
a learning test that confirms your understanding of an API. Then you write a test for the production
code that relies on the underlying API. When that test passes, you've successfully integrated the API
into your application. In othe
r words, build confidence layer by layer. If the behavior of the API
ever changes, your learning tests will pinpoint the change with greater accuracy than your
integration test.

What happens when a new version of the API is available? Well, your learning
tests also serve as an
automated regression test suite that you can use to detect changes. Before upgrading to a new
version of an API, run your learning tests to ensure that your assumptions about the API are still
valid.

One more thing, while you have y
our play clothes on: you can also use this technique to learn new
programming languages. For example, I learned
Ruby

[17] (and you should too!) by writing a
learning test every t
ime I discovered something new in the language. The following is an example
learning test that documents and validates two features of Ruby arrays:

require 'test/unit'


class RubyArrayTest < Test::Unit::TestCase



def testPushPopShift


a = Array.new



a.push("A")


a.push("B")


a.push("C")


assert_equal(["A", "B", "C"], a)


assert_equal("A", a.shift)


assert_equal("C", a.pop)


assert_equal("B", a.pop)


assert_equal(nil, a.pop)


end




def testCollect


a = ["H", "A", "L"]


collected = a.collect { |element| element.succ }


assert_equal(["I", "B", "M"], collected)


end


end

Any time I need to remember how to use an API or Ruby language feature, I refer back to my suite
of learning tests. They document working examples that

I can continually run and modify until I'm
confident enough to move forward. And if I can't find what I'm looking for, I expand my knowledge
base by writing a new test.

7. Corner Bugs

Even when we've written solid tests, once in a while someone using our

code (a paying customer, a
persnickety cubemate) discovers a bug. Don't let that stop you from continuing to write tests that
catch the majority of bugs. Instead, use it as an opportunity to improve your testing skills. In the
meantime, a bug has been rep
orted and it needs to be fixed. Thankfully, you're able to quickly
identify the suspect lines of code because you happen to have vast knowledge of the code base. So
you fire up your favorite editor with fingers poised on the keyboard, ready to make the nec
essary
repairs. But before you do that, don't let a golden opportunity to forever corner that bug pass you by.

How will you know when your code changes have squashed the bug? After all, if you're moments
away from making a change, then you must have expect
ations about how the code will work after
you've made the change. Writing code is a means to an end. Now is the time to turn your
expectations into an automated test that will signify the end. The bug has been fixed when the test
passes. Moreover, once the

test passes, you have an automated way to keep the bug cornered for
life.

8. Expand Your Toolbox

Often, we'd like to test something, but we just don't have the right tool for the job. We're short on
time as it is, and spending precious time crafting a tes
t harness is yet another reason not to test.
Thanks to the work of others, there's no excuse for skimping on testing for lack of sufficient tools.
The open source world is currently teeming with handy testing tools. It pays to be creatively lazy by
looking

around before reinventing yet another test harness.

Say, for example, you're writing a servlet that provides a shopping cart service. The intent of the
servlet is to add the item and quantity specified in the request parameters to the shopping cart. You'd

like to test that the servlet works, but the method you want to test requires an
HttpServletRequest

instance. You can't create one of those very easily. And if you have to
crank up a J2EE server to put the servlet in a known state every time you want to r
un the test, you
won't run the test very often. It's time to expand your toolbox to include the
Mock Objects

[16]
framework. The following JUnit test uses the Mock Objects framework t
o test the servlet outside of
a J2EE server:

import junit.framework.TestCase;

import com.mockobjects.servlet.*;


public class ShoppingServletTest extends TestCase {



public void testAddRequestedItem() throws Exception {



ShoppingServlet servlet

= new ShoppingServlet();


MockHttpServletRequest request = new MockHttpServletRequest();


request.setupAddParameter("item", "Snowboard");


request.setupAddParameter("quantity", "1");



ShoppingCart cart = new ShoppingCart();



servlet.addRequestedItem(request, cart);



assertEquals(1, cart.itemCount());


}

}

Notice that the test presets the request parameters on a
MockHttpServletRequest

instance.
That instance is then passed in to the servlet's
addRequestedItem()

method. When you run the
test, your servlet is fooled into thinking that it's running in a servlet container. Later on, your
integration tests will cast a wider net by validating that the servlet works in its native environment.
But when you're writing th
e servlet code, using mock objects makes running the tests quick and
painless.

So, before attempting to write a test harness from scratch or giving up on testing altogether, survey
the tools others have crafted in their times of need. JUnit is a framework
, not an application. By all
means, if the standard JUnit assertion methods aren't enough, then write custom assertion methods.
It's also relatively easy to write applications that build upon JUnit.
JUnit.org

[18] maintains a list of
existing JUnit applications and extensions. Don't stop with JUnit and its Java ilk. Many xUnit
testing framework implementations for other languages and technologies are already there

for the
taking (visit
XProgramming.com

[19]). If you can't seem to find what you're looking for, let
Google

[20] be your guide. And if you do end up building a test harness, please share it so that others can
expand their toolbox.

9. Make It Part of Your Build Process

A test is a valuable radiator of information. It documents
--

in an executable form
at
--

how code
works. You don't have to trust that the documentation is correct; just run the test for yourself. If it
fails, the output tells you straight up that the code doesn't work as the test promises. So once you've
written a passing test, treat it
with the respect it deserves by checking it in to your version control
system. Then capitalize on the investment by running the test as part of your team's build process.

While you're grooving in the test
-
code rhythm, it's convenient to use the JUnit test
runner integrated
into your favorite IDE. But you also need to externalize the build process so that anybody on your
team, regardless of their IDE loyalties, can build and test the code on their machine. In the Java
world,
Ant

[21] is the king of the hill when it comes to making your build and test process portable.
The following snippet of an Ant
build.xml

file uses the built
-
in
<junit>

and
<batchtest>

tasks to run all JUnit tests conf
orming to the
*Test

naming convention:

<path id="build.classpath">


<pathelement location="${classes.dir}" />


<pathelement location="${lib.dir}/junit.jar" />

</path>


<target name="test" depends="compile" description="Runs all the *Test tests">



<juni
t haltonfailure="true" printsummary="true">


<batchtest>


<fileset dir="${classes.dir}" includes="**/*Test.class" />


</batchtest>


<formatter type="brief" usefile="false" />


<classpath refid="build.classpath" />


</junit>


</target>

Fi
rst notice the use of the
<path>

element to explicitly declare a classpath for the build rather than
relying on the
CLASSPATH

environment variable being set correctly. This makes the classpath
portable across machines. Second, notice that the
test

target i
s dependent on the
compile

target.
So, to compile and test the code in one fell swoop, anybody on your team can check out the project
from the version control system and type:

ant test

Finally, notice that the
<junit>

task is configured with
haltonfailure
="true"
. This means
that the build process will fail if any test fails. After all, the build contains tainted goods if all the
tests don't pass.

Why stop there? Now that you have an Ant target that compiles and tests the project, schedule the
test

target t
o be automatically run by a computer at a periodic interval. For example, using
CruiseControl

[22] or
Anthill

[23] (both free) you can put an idle machine to good use running any
Ant target as often as you'd like. Using a separate build
-
and
-
test machine implies that everything
needed to build and test

your project is under version control. You are using version control, aren't
you? You'll be surprised how often a separate machine flushes out build problems. And if the build
fails, those schedulers will even send you an email so that you can take approp
riate action to get
back on solid ground.

So, no matter how many tests you have, realize their value to your team early and often by making
testing part of your process. Add each passing test you write to your version control system and run
all the tests
continuously to radiate confidence.

10. Buddy Up

When learning anything new, I've found it helpful to buddy up with another newbie. Besides being
a lot more fun than trudging up the learning curve alone, together, you and your buddy can cover
more ground.

You can also keep each other accountable to the goals you share and challenge each
other to become better. As you practice the techniques described in this article, openly discuss with
your buddy your triumphs and struggles. Critique each other's tests an
d share design insights gained
from code driven by tests. And when you feel pressure to slip back into old coding habits, a good
buddy will bring you back from the brink.

So how do you find a buddy? It's been my experience that many folks secretly want to
try test
-
driven development, but they don't want to be the
only

person on the team doing it. So start by
expressing your desire to learn and practice test
-
driven development. By making this proclamation,
you'll invite social support that can be a powerful
motivator to help you follow through. Moreover,
once you step into the spotlight you'll likely draw others out of the shadows.

11. Travel With a Guide

Sometimes buddying up just isn't enough. If you and your buddy are learning at the same time, you
may bo
th stumble into the same pitfalls. Traveling with an experienced guide will help you avoid
getting bogged down. Don't feel that seeking outside help is a way of copping out. You'll be more
productive if you don't have to blaze your own trails.

Consider ar
ranging for training in unit testing or test
-
driven development to quickly put these
techniques into practice. For this kind of training to be truly effective, it needs to be customized for
you. For example, students I've taught have found short and focuse
d sessions
--

tailored and applied
to the software they're building and the technologies they're using
--

to be most beneficial. So look
for training that covers the basic trails, but then lets you chose advanced paths of interest.

As you continue to prac
tice test
-
driven development, you'll undoubtedly hit a few snags. Don't
spend too much time fighting through them. A few minutes of one
-
on
-
one discussion with a mentor
who's been there and done that will keep you on pace.

12. Practice, Practice, Practice

Writing tests first is a programming technique that takes practice, and lots of it. Accept the fact that
you won't see miraculous results overnight. Experts say it takes a minimum of 21 days to build a
positive habit and six months for it to become part of

your personality. So when you feel yourself
backsliding, don't despair. Just keep pressing on and pay careful attention to mental assertions
you're making that could be codified in tests. Your brain will love you for it!

As with anything new, the more you

practice, the better you get. Start simple by promising yourself
to write just one good automated test a day. If you write more, it's bonus points. Tomorrow
morning, you'll at least have one passing test. In a week, you'll have at least five. Run all your

tests
every time you change code, even if you don't think your change could possibly break anything.
This will get you in the habit of running the tests often and build your confidence in the tests.
Before long, you'll have a suite full of tests and you w
on't be able to confidently touch the code
without running the suite afterward. Green bars are your reward for progress.

Summary

Getting started writing tests doesn't have to be difficult or time
-
consuming. Just wade in gradually
by spotting practical opp
ortunities to let your computer automatically check what you're already
checking manually. Before writing new code, assert your expectations about what it should do.
Along the way, listen to the tests for design insights. Make testing an integral part of y
our
development process by writing tests first and making it easy for anyone on your team to run all the
tests at any time. Finally, don't go it alone.

I hope these techniques help you get the testing bug this year. It's a resolution that's sure to improv
e
your design and testing skills. Don't forget to relax by reminding yourself that every day you're just
getting started. You'll quickly find that indeed you do have time to test, and then some.

Resources



JUnit Download Page

[24]



JUnit FAQ

[13]

Answers to the world's most frequently asked JUnit questions.



Pragmatic Unit Testing

[15]

Andy Hunt and Dave Thomas, The Pragmatic Programmers, LLC, 2003.

A must
-
have, easy
-
to
-
read book that will help you quick
ly start writing good JUnit tests.



"
Lucene Intro

[25]"

by Erik Hatcher

The first of a two
-
part series of great Lucene articles. I buddied up with Erik to write the
Lucene learni
ng tests.



Mike Clark

[1] is an independent consultant with
Clarkware Consulti
ng

[26] based in Denver, CO.
He is co
-
author of
Bitter EJB

[27] and editor of the
JUnit

FAQ

[13].
Related Topics >>
Extreme Programming

[28]


|



Testing

[29]


|







Testing




Extreme Programming

Your use of this web site or any of its content or software indicates your agreement to be bound by
these
Terms of Pa
rticipation
.

Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Oracle and Java are registered
trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective
owners.


Powered by Oracle, Project Kenai and Co
gnisync

Source URL:

http://www.java.net/pub/a/today/2004/01/22/DozenWays.html

Links:

[1] http://www.java.net/pub/au/7

[2] http://www.java.net/pub/a/today/2004/01/22/DozenWays.html?p
age=2#4

[3] http://www.java.net/pub/a/today/2004/01/22/DozenWays.html?page=2#5

[4] http://www.java.net/pub/a/today/2004/01/22/DozenWays.html?page=2#6

[5] http://www.java.net/pub/a/today/2004/01/22/DozenWays.html?page=3#7

[6] http://www.java.net/pub/a/today
/2004/01/22/DozenWays.html?page=3#8

[7] http://www.java.net/pub/a/today/2004/01/22/DozenWays.html?page=3#9

[8] http://www.java.net/pub/a/today/2004/01/22/DozenWays.html?page=3#10

[9] http://www.java.net/pub/a/today/2004/01/22/DozenWays.html?page=3#11

[10]
http://www.java.net/pub/a/today/2004/01/22/DozenWays.html?page=3#12

[11] http://www.java.net/pub/a/today/2004/01/22/DozenWays.html?page=3#summary

[12] http://www.java.net/pub/a/today/2004/01/22/DozenWays.html?page=3#resources

[13] http://junit.sourceforge.
net/doc/faq/faq.htm

[14] http://eclipse.org/

[15] http://www.pragmaticprogrammer.com/starter_kit/ut/index.html

[16] http://www.java.net/<cs_comment

[17] http://www.ruby
-
lang.org/en/

[18] http://www.junit.org/news/extension/index.htm

[19] http://xprogrammin
g.com/software.htm

[20] http://www.google.com/

[21] http://ant.apache.org/

[22] http://cruisecontrol.sourceforge.net/

[23] http://www.urbancode.com/projects/anthill/default.jsp

[24] http://sourceforge.net/project/showfiles.php?group_id=15278

[25] http://to
day.java.net/pub/a/today/2003/07/30/LuceneIntro.html

[26] http://www.clarkware.com

[27] http://manning.com/tate2/

[28] http://www.java.net/articles/topic/13

[29] http://www.java.net/articles/topic/27


source: http://today.java.net/pub/a/today/2004/01/22/Do
zenWays.html


Eclipse Junit testing tutorial

JUnit is a simple Java testing framework to

write tests for you Java application. This tutorial gives you an

overview of the features of JUnit and shows a little example how you

can write tests for your Java ap
plication.

General

Author
:

Sascha

Wolski

Sebastian

Hennebrueder

http://www.laliluna.de/tutorials.html

Date
:

April,

12 2005


Software:

Eclipse

3.x

Junit

2.x


Source

code:

http://www.laliluna.de/assets/tutorials/junit
-
testing
-
source.zip

PDF

Version

http://www.laliluna.de/assets/tutorials/junit
-
testing
-
en.pdf

What is
JUnit

JUnit is a simple open source Java testing

framework used to write and run repeatable automated tests. It is an

instance of the xUnit architecture for unit testing framework.

Eclipse supports creating test cases and running test suites, so it

is easy

to use for your Java applications.

JUnit features include:



Assertions for testing expected results



Test fixtures for sharing common test

data



Test suites for easily organizing and

running tests



Graphical and textual test runners

What is a test case

A test

case is a class which holds a number

of test methods. For example if you want to test some methods of a

class
Book

you create a class
BookTest

which extends

the JUnit
TestCase

class and place your test methods in there.

How you write and run a simple test

1.


Create

a subclass of TestCase:

public class BookTest extends TestCase{


//..

}


2.


Write

a test method to assert expected results on the object under test:

Note: The naming convention for a test

method is testXXX()

public void testCollection() {



Collection collection = new ArrayList();


assertTrue(collection.isEmpty());

}

Write

a
suite()

method that uses reflection to dynamically create a

test suite containing all the
testXXX()

methods:

public static Test suite(){


retur
n new TestSuite(BookTest.class);

}


4.


Activate the JUnit view in Eclipse

(
Window > Show View > Other.. > Java > JUnit
).



You

find the
JUnit

tab near the
Package Explorer

tab. You

can change the position of the tab
by drag and drop it.


5.



Right click on t
he subclass of

TestCase

and choose
Run > JUnit Test

to run the

test.


Using a test fixture

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 test code necessary to initialize and

cleanup those

common objects for each test.


To create a test fixture, define a
setUp()

method that initializes common object and a
tearDown()

method

to cleanup those objects. The JUnit framework automatically invokes

the
setUp()

method before a each test

is run and the

tearDown()

method after each test is run.


The following test uses a test fixture:


public class BookTest2 extends TestCase {


private Collection collection;


protected void setUp() {


collection = new ArrayList();


}


pro
tected void tearDown() {


collection.clear();


}


public void testEmptyCollection(){


assertTrue(collection.isEmpty());


}

}


Dynamic and static way of running single tests

JUnit supports two ways (static and dynamic)

of runnin
g single tests.

In static way you override the
runTest()

method inherited form TestCase class and call the desired test case.

A convenient way to do this is with an anonymous inner class.

Note: Each test must be given a name, so

you can identify it if it f
ails.

TestCase test = new BookTest("equals test") {<br> public void runTest()
{<br> testEquals();<br> }<br>};



The dynamic way to create a test case to be

run uses reflection to implement
runTest
. It assumes the name

of the test is
the name of the test case method to invoke. It

dynamically finds and invokes the test method. The dynamic way is

more compact to write but it is less static type safe. An error in

the name of the test case goes unnoticed until you run it and get a

NoSuchMe
thodException
. We leave the choice of which to use up

to you.


TestCast test = new BookTest(“testEquals”);


What is a TestSuite

If you have two tests and you’ll run them

together you could run the tests one at a time yourself, but you

would quickly grow ti
red of that. Instead, JUnit provides an object

TestSuite

which runs any number of test cases together. The

suite method is like a main method that is specialized to run tests.

Create a suite and add each test case you

want to execute:

public static void su
ite(){<br> TestSuite suite = new TestSuite();<br>
suite.addTest(new BookTest("testEquals"));<br> suite.addTest(new
BookTest("testBookAdd"));<br> return suite;<br>}


Since JUnit 2.0 there is an even simpler way

to create a test suite, which holds all test
XXX() methods. You only

pass the class with the tests to a TestSuite and it extracts the test

methods automatically.


Note: If you use this way to create a

TestSuite all test methods will be added. If you do not want all test

methods in the TestSuite use t
he normal way to create it.


Example:


public static void suite(){


return new TestSuite(BookTest.class);

}


A little example

Create a new Java project named

JUnitExample.

Add a package

de.laliluna.tutorial.junitexample

where you place the example

c
lasses and a package
test.laliluna.tutorial.junitexample

where you place your test classes.

The class Book

Create a new class
Book

in the

package
de.laliluna.tutorial.junitexample
.

Add two properties
title

of type

String

and
price

of type
double
.

Add a con
structor to set the two properties.

Provide a getter
-

and setter
-
method for each

of them.

Add a method trunk for a method

equals(Object object)

which checks if the object is an

instance of the class Book and the values of the object are equal.

The method r
eturn a boolean value.

Note: Do not write the logic of the

equals(..)

method, we do it after finish creating the test

method.

The following source code shows the class

Book.

public class Book {<br><br> private String title;<br> private double
price;<
br><br> /**<br> * Constructor <br> * <br> * @param
title<br> * @param price<br> */<br> public Book(String title,<br>
double price) {<br> this.title = title;<br> this.price =
price;<br> }<br><br>
/**<br> * Check if an object is an instance of
book<br> * and the values of title and price are equal<br> * then return
true, otherwise return false<br> */<br> public boolean equals(Object
object) {<br><br> return false;<br> }<
br><br> public double
getPrice() {<br> return price;<br> }<br><br> public void
setPrice(double price) {<br> this.price = price;<br> }<br><br>
public String getTitle() {<br> return title;<br> }<br><br> public
void s
etTitle(String title) {<br> this.title = title;<br> }<br>}

The test case BookTest

Create a new test case
BookTest

in

the package
test.laliluna.tutorial.junitexample

Right click on the package and choose
New > JUnit Test

Case
.

In the wizard

choos
e the methods stubs
setUp()
,
tearDown()

and

constructor()
.



The

following source code shows the class BookTest

public class BookTest extends TestCase {<br><br> /**<br> * setUp() method
that initializes common objects<br> */<br> protected vo
id setUp() throws
Exception {<br> super.setUp();<br> }<br><br> /**<br> *
tearDown() method that cleanup the common objects<br> */<br> protected
void tearDown() throws Exception {<br> super.tearDown();<br> }<br><br>
/**<
br> * Constructor for BookTest.<br> * @param name<br> */<br>
public BookTest(String name) {<br> super(name);<br> }<br><br>}



Now we want to write a test for the

equals(..)

method of the class
Book
. We provide three

private propert
ies, book1, book2 and book3 of type
Book.

private Book book1;<br>private Book book2;<br>private Book book3;



Within the
setUp()

method we

initializes the three properties with some values. Property book1 and

book3 are the same.


protected void setUp() th
rows Exception {


super.setUp();


book1 = new Book(“ES”, 12.99);


book2 = new Book(“The Gate”, 11.99);


book3 = new Book(“ES”, 12.99);

}





Within the tearDown() method we cleanup the

properties:


protected void tearDown() throws E
xception {


super.tearDown();


book1 = null;


book2 = null;


book3 = null;

}





Now, add a test method
testEquals()

to the test case. Within the method we use the
assertFalse()

method of the JUnit framework to test if the return
-
va
lue of the

equals(..) method is false, because book1 and book2 are not the same.

If the return
-
value is false the logic of the equals() method is

correct, otherwise there is a logical problem while comparing the

objects. We want to test if the method compa
res the objects correctly

by using the assertTrue() method. Book1 and Book3 are the same,

because both are an instance of the class Book and have the same

values.


The following source code shows the

testEquals() method:


public void testEquals(){


assertFalse(book2.equals(book1));


assertTrue(book1.equals(book1));

}



Writing the logic of the equals() method

We have finished the test and now we can add

the logic to the
equals()

method stub. Open the class Book and

add the logic to the
equals(
)

method. First we check if the

object given by the method is an instance of
Book
. Then

compare the properties
title

and
price
,

if they are equal return true.

public boolean equals(Object object) {<br> if (object instanceof Book)
{<br> Book

book = (Book) object;<br> return
getTitle().equals(book.getTitle())<br> &amp;&amp; getPrice()
== book.getPrice();<br> }<br> return false;<br>}


Create the suite() method

In order to run the test method
testEquals()

ad
d a method
suite()

to the class
BookTest
.

Note: You can also create a separate class

where you add the
suite()

method.

Within the method create a new instance of

TestSuite

and use the method
addTest(..)

to add a test.

Here we use the dynamically way to add

a test to a TestSuite.

The method looks like the follows:

public static Test suite(){<br> TestSuite suite = new TestSuite();<br>
suite.addTest(new BookTest("testEquals"));<br> return suite;<br>}

Run the test

After finishing all test methods we w
ant to

run the JUnit test case. Right mouse button on the class BookTest and

choose
Run As > JUnit Test
.

On the JUnit view (Menu Windows
-
> show

view) of Eclipse you can see how many runs, errors and failures

occurred.


source: http://www.laliluna.de/artic
les/posts/eclipse
-
junit
-
testing
-
tutorial.html