From: Arne Vajhøj on
On 18-03-2010 23:53, Eric Sosman wrote:
> On 3/18/2010 10:00 PM, Arne Vajh�j wrote:
>> On 18-03-2010 15:38, Eric Sosman 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?
>>> [...]
>>> "Each method" may be a overkill, too. Getters and setters come
>>> to mind as "too simple to test" -- usually.
>>
>> I recommend testing them as well.
>>
>> They are easy to test and weird things have been seen in code before.
>
> Well, I *did* say "usually."
>
> If setters are supposed to do something more than merely
> set a value -- fire change events, say, or recompute allied
> values other than the ones directly set -- that's worth testing.
> If getters return arrays, it's worth verifying that mucking with
> the returned array doesn't magically modify the state of the
> object it came from (unless it's supposed to, in which case one
> should test that it actually does). And so on, and so on.
>
> But I put it to you that
>
> public void setScrew(int screw) {
> this.screw = screw;
> }
>
> ... is more amenable to verification by inspection than by test.

People can mess up one line as well.

Before IDE's generated setters the following sometimes happen
during copy paste from setNail.

public void setScrew(int nail) {
this.nail = nail;
}

I would not drop unit tests for inspection. Nor drop inspection
for unit tests.

> As to ease of testing, I note that the code to test a simple
> getter or setter is more complex than the code tested; something
> seems fundamentally wrong with this. If we think a one-liner
> needs testing, why aren't we writing tests for the umpteen-line
> test class?

The benefits of unit testing unit tests would probably be
very minimal.

Arne
From: Arne Vajhøj on
On 19-03-2010 09:08, Patricia Shanahan wrote:
> Graham Cox wrote:
>> Rhino <no.offline.contact.please(a)example.com> writes:
>>
>>> I've been lucky enough not to get burned by one of those yet - at
>>> least as far as I know! - but you make a good point. Murphy's Laws,
>>> right? Anything that can go wrong, will go wrong.
>>>
>>> It probably makes sense to test even really trivial-looking code....
>>>
>> I tend to think that any function with more than 2 lines of code
>> should be unit tested. This means that getters and setters are
>> generally exempt *unless they do something*. Specifically it means
>> that the setters that do data validation first should be tested, but
>> the setters that do nothign more than
>> store the value to a member variable can be ignored...
>
> I use different criteria. The Eclipse "Source" code generation seems to
> be well tested. If I merely told Eclipse to generate a setter or getter,
> or the equals/hashCode pair, I don't write a test. If I wrote a getter
> or setter myself, it needs testing. I'm fully capable of making a
> mistake in a single line of code.

Code generation has almost removed the chance of errors in
simple getters and setters.

But I would hesitate to make decisions about unit test strategy
based on assumptions that the programmer writing the original
code did (or will if the tests are written first) use the tools
as intended.

Arne
From: Arne Vajhøj on
On 19-03-2010 07:23, Tom Anderson wrote:
> However, you often test getters and setters in the course of testing
> other methods. For example:
>
> @Test
> testOverdraftLimit() {
> Account ac = new Account();
> ac.setBalance(100000);
> ac.setOverdraftLimit(20000);
> int withdrawn = ac.withdraw(150000);
> assertEqual(120000, withdrawn);
> assertEqual(-20000, ac.getBalance());
> }
>
> That method is ostensibly about testing the overdraft limit logic, but
> it depends on setBalance and getBalance working right. If they don't, it
> will break, and you'll find out about it.

True.

And if it is all done by the same person, then "the difference
is equal".

But if the programmer writing OverDraftLimit received an
Account class from somebody else and were told that it was
unit tested, then I believe that there is basis for a
complaint.

Arne


From: Jean-Baptiste Nizet on
Rhino a �crit :

>
> Now THAT is helpful! In fact, it means that I can consolidate all of the
> testing for a given method into a single method in the TestCase class
> rather than having a substantial number of tiny test methods for a given
> method in the class I developed. And that's where I was hoping to end up
> when I asked the question in the first place.
>

You have to find a good compromise. Smaller test methods are easier to
write, read and understand, and they spot a specific bug. If you have
very long test methods, the first failed assertion will stop the test
method, and all the other, unrelated assertions, won't be tested.

For example, let's suppose I have this kind of method :
public void divide(int dividend, int divisor) {
if (divisor == 0) {
throw new IllegalArgumentException("divisor may not be 0");
}
return dividend / divisor;
}

I prefer to have a test for the nominal case, and another one for the
exceptional case :

public void testDivide() {
assertEquals(3, myObject.divide(6, 2));
}

public void testDivideWhenBadArgument() {
try {
myObject.divide(6, 0);
fail("divide should have thrown an IllegalArgumentException");
}
catch (IllegalArgumentException e) {
// expected
}
}

This may seem overkill, but once your tested method gets longer, more
complicated, and with more code branches, having multiple smaller test
cases is often easier and more maintainable.

JB.
From: Mike Schilling on
Eric Sosman wrote:
> On 3/19/2010 11:49 AM, Graham Cox wrote:
>> Patricia Shanahan<pats(a)acm.org> writes:
>>
>>> I use different criteria. The Eclipse "Source" code generation
>>> seems to be well tested. If I merely told Eclipse to generate a
>>> setter or getter, or the equals/hashCode pair, I don't write a
>>> test. If I wrote a getter or setter myself, it needs testing. I'm
>>> fully capable of making a mistake in a single line of code.
>>
>> Fair point, but I was more getting at the fact that I *do* unit test
>> generated functions like equals and hashCode, simply because the
>> class often changes after they were generated and they are no longer
>> valid. Just because the code was correct at the time of writing
>> doesn't mean it will always remain so...
>
> This is true: Sometimes "maintenance" and "enhancement"
> are synonyms for "bit rot."
>
> But I'm curious: What sort of a test do you write to ensure
> that equals() and hashCode() play nicely together? For example,
> if you were writing unit tests for java.lang.String, what would
> they look like?

Not compiled or tested, so typos are inevitable:

// Strings that are interesting and varied, and include all the edge
cases I
// can think of. All are distinct.
String[] strings = .new String[] {...};

for (int i = 0; i < strings.length; i++)
{
for (int j = 0; j < strings.length; j++)
{
if (i == j)
{
String s = strings[i];
String t = new String(s);
assertEquals("'" + s + "' != '" + t + "'", s, t);
assertEquals("'" + s + "'.hashCode() != '" + s +
"'.hashCode()", s.hashCode(), t.hashCode());
}
else
{
String s = strings[i];
String t = strings[j];
assertNotEquals("'" + s + "' == '" + t + "'", s, t);
}
}
}