From: Rhino on
I think I understand the basics of using JUnit - I'm still using JUnit3
for the moment - but I want to ask some things that I don't find clear in
the documentation that I've found.

Would it be reasonable to say all of the following?

1. For each class that I develop, I should have one JUnit class that
extends TestCase and that this TestCase class should test each of the
methods in the class I developed?

2. When I look at the JUnit window in Eclipse to see the results of that
TestCase class, all of them should have a Green icon beside them? In
other words, should each test be written to show a positive result? That
would seem to make life a lot easier in one way: whenever I ran a
TestCase that was written that way, any bug would be easy to spot because
it didn't have the Green icon beside it.

3. Is a TestSuite just a group of TestCases that can all be invoked from
the same JUnit class? For instance, given a project Foo, would I
typically have a single TestSuite for Foo that, when invoked, runs the
TestCases for each of the classes that makes up Foo?

Basically, I'm having a bit of confusion over exactly how much you put in
each class that extends TestCase (sorry for the strange wording but I
want to distinguish between the class that is being tested and the class
that is doing the testing and don't know the most concise wording) and
what a TestSuite should comprise.

Also, I'm very uncertain about the individual methods in each class that
extends TestCase and what sorts of results they should return. Should all
test methods result in a Green icon?

I can see where that would be very convenient: you simply run the test
case and even if it has dozens of methods, you just scan down the list
and make sure all of them have Green icons. If they do, all your tests
just passed and you can move on to the next thing.

On the other hand, I'm not completely sure how to accomplish that. I'm
picturing a method like bar() which takes two input parameters. Whenever
the values of the two input parameters are valid, bar() should produce a
valid result, which I can predict and put in a test that would look like
this:

int actualResult = myclass.bar(4);
int expectedResult = 2;
assertTrue("The actual result, " + actualResult + ", does not equal the
expected result, " + expectedResult, actualResult==expectedResult);

But bar() also anticipates bad values for input parameters and throws
IllegalArgumentException for those. What would my test for that look
like? Any case I've ever written like that returns a Black icon. How
would I write a case involving an Exception so that it gives a Green icon
as the result?

--
Rhino

--- news://freenews.netfront.net/ - complaints: news(a)netfront.net ---
From: Eric Sosman on
On 3/18/2010 3:22 PM, Rhino wrote:
> I think I understand the basics of using JUnit - I'm still using JUnit3
> for the moment - but I want to ask some things that I don't find clear in
> the documentation that I've found.
>
> Would it be reasonable to say all of the following?
>
> 1. For each class that I develop, I should have one JUnit class that
> extends TestCase and that this TestCase class should test each of the
> methods in the class I developed?

Sort of, I'd say. Private and even package-private classes
might get a waiver, the idea being that their "contracts" are only
with the public classes that "employ" them. Non-public nested
classes, same thing: If they're really just "implementation details"
of their containing classes, they might not need separate testing.
(For some inner classes, it won't be possible to test in isolation.)

"Each method" may be a overkill, too. Getters and setters come
to mind as "too simple to test" -- usually. I've never heard of
anyone writing a unit test for the hashCode()/equals() pair (their
agreement should be verified, but it's not clear that testing is
the best way to go about it).

> [...] Whenever
> the values of the two input parameters are valid, bar() should produce a
> valid result, which I can predict and put in a test that would look like
> this:
>
> int actualResult = myclass.bar(4);
> int expectedResult = 2;
> assertTrue("The actual result, " + actualResult + ", does not equal the
> expected result, " + expectedResult, actualResult==expectedResult);
>
> But bar() also anticipates bad values for input parameters and throws
> IllegalArgumentException for those. What would my test for that look
> like? Any case I've ever written like that returns a Black icon. How
> would I write a case involving an Exception so that it gives a Green icon
> as the result?

try {
int actual = myclass.bar(invalid);
assertTrue("Got result " + actual + " from " + invalid
+ " instead of an exception", false);
}
catch (IllegalArgumentException ex) {
// Thanks; I needed that!
}

--
Eric Sosman
esosman(a)ieee-dot-org.invalid
From: Jim on
On Thu, 18 Mar 2010 15:38:05 -0400, Eric Sosman
<esosman(a)ieee-dot-org.invalid> wrote:

>On 3/18/2010 3:22 PM, Rhino wrote:
>> I think I understand the basics of using JUnit - I'm still using JUnit3
>> for the moment - but I want to ask some things that I don't find clear in
>> the documentation that I've found.
>>
>> Would it be reasonable to say all of the following?
>>
>> 1. For each class that I develop, I should have one JUnit class that
>> extends TestCase and that this TestCase class should test each of the
>> methods in the class I developed?
>
> Sort of, I'd say. Private and even package-private classes
>might get a waiver, the idea being that their "contracts" are only
>with the public classes that "employ" them. Non-public nested
>classes, same thing: If they're really just "implementation details"
>of their containing classes, they might not need separate testing.
>(For some inner classes, it won't be possible to test in isolation.)
>
> "Each method" may be a overkill, too. Getters and setters come
>to mind as "too simple to test" -- usually. I've never heard of
>anyone writing a unit test for the hashCode()/equals() pair (their
>agreement should be verified, but it's not clear that testing is
>the best way to go about it).
<snip>

Have to disagree about equals() at least. Having a unit test for
equals ensures that when you make changes to your class you
don't break the method. As me how I know ;-)

Jim
From: Daniel Pitts on
On 3/18/2010 12:38 PM, Eric Sosman wrote:
> On 3/18/2010 3:22 PM, Rhino wrote:
>> But bar() also anticipates bad values for input parameters and throws
>> IllegalArgumentException for those. What would my test for that look
>> like? Any case I've ever written like that returns a Black icon. How
>> would I write a case involving an Exception so that it gives a Green icon
>> as the result?
>
> try {
> int actual = myclass.bar(invalid);
> assertTrue("Got result " + actual + " from " + invalid
> + " instead of an exception", false);
> }
> catch (IllegalArgumentException ex) {
> // Thanks; I needed that!
> }
>

I think there is a "fail(String )" method you can call instead of
assertTrue(String, false). At least, on the versions of JUnit I have used.


--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
From: Tom Anderson on
On Thu, 18 Mar 2010, Rhino wrote:

> I think I understand the basics of using JUnit - I'm still using JUnit3
> for the moment

I'd strongly advise moving to 4 right away - there are some differences to
get used to, so best to do that before you get comfortable with 3.

> 1. For each class that I develop, I should have one JUnit class that
> extends TestCase and that this TestCase class should test each of the
> methods in the class I developed?

There doesn't have to be a strict 1:1 relationship. Test classes are
classes, and are subject to the same principles of design as any other
classes - give each class a single responsibility, splitting classes that
do too many different things. A responsibility could be "test that the
Furnace class works", but it could also be "test that the Furnace class
incinerates various kinds of rubbish properly", where you'd then have
other classes to test other aspects of Furnace behaviour. You might also
want more integrationish tests, which would involve the interaction of two
classes - test that the ResourceLoader works properly when coupled to the
JDBCDataStore.

> 2. When I look at the JUnit window in Eclipse to see the results of that
> TestCase class, all of them should have a Green icon beside them?

Yes, absolutely.

> In other words, should each test be written to show a positive result?

Yes, absolutely.

> That would seem to make life a lot easier in one way: whenever I ran a
> TestCase that was written that way, any bug would be easy to spot
> because it didn't have the Green icon beside it.

Bingo. Eclipse has a button - the little red and blue squares at the top
of the JUnit pane - that hides all green tests, leaving only failed and
errored ones, which makes it even easier to spot the troublemakers.

> 3. Is a TestSuite just a group of TestCases that can all be invoked from
> the same JUnit class?

Yes.

> For instance, given a project Foo, would I typically have a single
> TestSuite for Foo that, when invoked, runs the TestCases for each of the
> classes that makes up Foo?

Precisely.

Although you might have several suite classes, and you might nest them.
For instance, in our current project, we have an AllTests suite (this is
quite a common name for such a thing, i think) that runs all the tests
that are meaningful on a development machine. We have some extra tests
which only make sense on the nightly build (which does some extra tasks
which take longer, and which need to be tested), so we have a
ServerBuildTests suite. We then have a super-suite
AllTestsAndServerBuildTests, which runs both of the other suites. To be
honest, those names probably aren't quite right, but hey, at least we have
the tests.

Note that Eclipse doesn't require you to have a suite to run all your
tests - in the context menu for a source folder, there's Run As > JUnit
Test, which will find all the tests in that package and run them. You
can't use this in a non-Eclipse situation (like a command-line build, such
as you might distribute, or use for a nightly build), but there are
equivalents; i have build-and-test scripts which employ the following
science:

grep -rl --include='*.java' @Test "$TEST_SRC_DIR" | cut -d / -f 2- | cut -d . -f 1 | tr / . | xargs java -ea -classpath "$TEST_CLASSES_DIR:$CLASSES_DIR" org.junit.runner.JUnitCore

> Basically, I'm having a bit of confusion over exactly how much you put
> in each class that extends TestCase

There's no easy answer to this. On the bright side, there are no hard and
fast rules, so you can't get it wrong. Approach the matter as you would
any other question of how much should go in a class, but don't sweat it
too much. There tends to be fairly little coupling between test methods in
a test class, so it's not a disaster if the classes that contain them are
too big or too small. Where i work, our test classes very much tend to run
to the too big end of the scale rather than the too small - i think
there's one with thirty or so test methods. That really could do with
breaking up, actually.

> (sorry for the strange wording but I want to distinguish between the
> class that is being tested and the class that is doing the testing and
> don't know the most concise wording)

I call that a test class. The target is the 'class under test'.

> and what a TestSuite should comprise.
>
> Also, I'm very uncertain about the individual methods in each class that
> extends TestCase and what sorts of results they should return. Should
> all test methods result in a Green icon?

Yes, absolutely. This is essential. Fundamental.

> I can see where that would be very convenient: you simply run the test
> case and even if it has dozens of methods, you just scan down the list
> and make sure all of them have Green icons. If they do, all your tests
> just passed and you can move on to the next thing.

Not just convenient, essential.

> On the other hand, I'm not completely sure how to accomplish that. I'm
> picturing a method like bar() which takes two input parameters. Whenever
> the values of the two input parameters are valid, bar() should produce a
> valid result, which I can predict and put in a test that would look like
> this:
>
> int actualResult = myclass.bar(4);

Hey, what happened to the other parameter?

> int expectedResult = 2;
> assertTrue("The actual result, " + actualResult + ", does not equal the
> expected result, " + expectedResult, actualResult==expectedResult);
>
> But bar() also anticipates bad values for input parameters and throws
> IllegalArgumentException for those. What would my test for that look
> like? Any case I've ever written like that returns a Black icon. How
> would I write a case involving an Exception so that it gives a Green
> icon as the result?

Under JUnit 4:

@Test(expected=IllegalArgumentException.class)
public void testBarThrowsExceptionForInvalidParameters() {
myclass.bar(-1);
}

Under JUnit 3:

public void testBarThrowsExceptionForInvalidParameters() {
try {
myclass.bar(-1);
}
catch (IllegalArgumentException e) {
return;
}
fail(); // this will only be reached if an exception is not thrown
}

Or some variation on that - the fail() could be inside the try, right
after the call to bar, or you could have a boolean exceptionThrown =
false, then set it to true in the catch block, then do
assertTrue(exceptionThrown) at the end.

HTH.

tom

--
I need a proper outlet for my tendency towards analytical thought. --
Geneva Melzack