New to JUnit... Eclipse Question

D

ducnbyu

Hi,

I'm new to JUnit and went through the tutorial in

http://www.onjava.com/pub/a/onjava/2004/02/04/juie.html

It seemed to work ok in the end, but ran into something in the middle
that was unexpected. The tutorial says "...according to TDD... " we
should be able to create the test case before writing any code for the
class to be tested. I understand and accept that assertion for all the
reasons TDD gives. However JUnit4.0 for Eclipse doesn't seem to agree
with it.

Following the tutorial, I went to create the JUnit Test Case (before
creating the class to be tested) and filled in the first panel which
included test class name and the name of the class to be tested. But,
it would not enable the "Next" button (nor "Finish"). At the top of
the panel the error "Class under test does not exist in current
project." was displayed.

At a minimum I had to create a class with the signature expected by
JUnit Test Case for the wizard to build the JUnit code.

Am I missing something or is Eclipse or JUnit4.0 being too picky for
rote TDD? I'm on Eclipse 3.2.0. Would updating anything resolve this?
Not that it is terribly annoying since that minimum code would need to
be written in the next step anyway. I didn't see anything in
Properties or Preferences that would relax this check.

Thanks!
 
J

Jim

Hi,

I'm new to JUnit and went through the tutorial in

http://www.onjava.com/pub/a/onjava/2004/02/04/juie.html

It seemed to work ok in the end, but ran into something in the middle
that was unexpected. The tutorial says "...according to TDD... " we
should be able to create the test case before writing any code for the
class to be tested. I understand and accept that assertion for all the
reasons TDD gives. However JUnit4.0 for Eclipse doesn't seem to agree
with it.

Following the tutorial, I went to create the JUnit Test Case (before
creating the class to be tested) and filled in the first panel which
included test class name and the name of the class to be tested. But,
it would not enable the "Next" button (nor "Finish"). At the top of
the panel the error "Class under test does not exist in current
project." was displayed.

At a minimum I had to create a class with the signature expected by
JUnit Test Case for the wizard to build the JUnit code.

Am I missing something or is Eclipse or JUnit4.0 being too picky for
rote TDD? I'm on Eclipse 3.2.0. Would updating anything resolve this?
Not that it is terribly annoying since that minimum code would need to
be written in the next step anyway. I didn't see anything in
Properties or Preferences that would relax this check.

Thanks!

I usually start with a minimal class. Also you should have any
interfaces already declared that may need to be implemented.

You do have to write some part of Bar.foo() before you can
construct a Bar and call foo()! BUT as soon as you do write foo()
you write a corresponding test_foo() or something like that.

It does take a little practice, but I'm finding it well worth the
effort.

Jim
 
O

Owen Jacobson

It seemed to work ok in the end, but ran into something in the middle
that was unexpected. The tutorial says "...according to TDD... " we
should be able to create the test case before writing any code for the
class to be tested. I understand and accept that assertion for all the
reasons TDD gives. However JUnit4.0 for Eclipse doesn't seem to agree
with it.

Following the tutorial, I went to create the JUnit Test Case (before
creating the class to be tested) and filled in the first panel which
included test class name and the name of the class to be tested. But,
it would not enable the "Next" button (nor "Finish"). At the top of
the panel the error "Class under test does not exist in current
project." was displayed.

I normally leave "Class under test" blank when creating test cases with
the wizard for that very reason. I start writing tests, then use the
quick fix tool to create the class under test and the methods I'm testing.
 
M

monang

Just leave the "class under test" blank. That field is intended for
test after code. If you are doing TDD, then you've got your steps
correct.
 
D

ducnbyu

Thank you (and Owen too) for pointing that out. I didn't notice that
Finish was enabled until I entered the class to be tested. I see that
now. The problem was the tutorial. Apparently it was written from an
earlier version of Eclipse and perhaps that was allowed or maybe the
tutorial was just incorrectly organized.

Again Thanks
 
D

ducnbyu

Jim said:
I usually start with a minimal class.

While this seems to be slightly contrary to TDD, I like that the wizard
generates the stubs with this approach.

Thanks!
 
A

Andrew McDonagh

Hi,

I'm new to JUnit and went through the tutorial in

http://www.onjava.com/pub/a/onjava/2004/02/04/juie.html

It seemed to work ok in the end, but ran into something in the middle
that was unexpected. The tutorial says "...according to TDD... " we
should be able to create the test case before writing any code for the
class to be tested. I understand and accept that assertion for all the
reasons TDD gives. However JUnit4.0 for Eclipse doesn't seem to agree
with it.

Following the tutorial, I went to create the JUnit Test Case (before
creating the class to be tested) and filled in the first panel which
included test class name and the name of the class to be tested. But,
it would not enable the "Next" button (nor "Finish"). At the top of
the panel the error "Class under test does not exist in current
project." was displayed.

At a minimum I had to create a class with the signature expected by
JUnit Test Case for the wizard to build the JUnit code.

Am I missing something or is Eclipse or JUnit4.0 being too picky for
rote TDD? I'm on Eclipse 3.2.0. Would updating anything resolve this?
Not that it is terribly annoying since that minimum code would need to
be written in the next step anyway. I didn't see anything in
Properties or Preferences that would relax this check.

Thanks!

That particular wizard is for applying unit tests to existing classes.

Instead you need to use the menus File ->New -> Junit test Case
 
A

Andrew McDonagh

Jim said:
I usually start with a minimal class. Also you should have any
interfaces already declared that may need to be implemented.

You do have to write some part of Bar.foo() before you can
construct a Bar and call foo()! BUT as soon as you do write foo()
you write a corresponding test_foo() or something like that.

It does take a little practice, but I'm finding it well worth the
effort.

Jim

Well you can do it that way, but you'll find the majority of TDD
practicing folks write the entire test case before going anywhere near
the code to make it work.

As in...


class TestCalulator extends TestCase {

public void testAddingTwoZeros() {
Calculator calc = new Calculator();
assertEquals("Wrong answer!", 0 calc.add(0, 0);
}
}

Now I know what Calculator looks like and can implement just enough to
make the test pass.

But I haven't even started writing the Calculator class yet ...
 
O

Oliver Wong

Andrew McDonagh said:
Jim said:
The tutorial says "...according to TDD... " we
should be able to create the test case before writing any code for the
class to be tested. [...]

At a minimum I had to create a class with the signature expected by
JUnit Test Case for the wizard to build the JUnit code.

I usually start with a minimal class. Also you should have any
interfaces already declared that may need to be implemented.
[...]

Well you can do it that way, but you'll find the majority of TDD
practicing folks write the entire test case before going anywhere near the
code to make it work.

As in...


class TestCalulator extends TestCase {

public void testAddingTwoZeros() {
Calculator calc = new Calculator();
assertEquals("Wrong answer!", 0 calc.add(0, 0);
}
}

Now I know what Calculator looks like and can implement just enough to
make the test pass.

But I haven't even started writing the Calculator class yet ...

I thought the TDD best practices was first to write the interface:

public interface Calculator {
public int add(int a, int b);
}

Then to write the test case around that interface:

class TestCalulatorImpl extends TestCase {

public void testAddingTwoZeros() {
Calculator calc = new CalculatorImpl();
assertEquals("Wrong answer!", 0 calc.add(0, 0);
}
}


Then to write the code around the interface and the tests:

private class CalculatorImpl implements Calculator {
/*etc.*/
}

- Oliver
 
D

Dale King

Oliver said:
Andrew McDonagh said:
Jim said:
On 11 May 2006 18:47:03 -0700, (e-mail address removed) wrote:

The tutorial says "...according to TDD... " we
should be able to create the test case before writing any code for the
class to be tested. [...]

At a minimum I had to create a class with the signature expected by
JUnit Test Case for the wizard to build the JUnit code.


I usually start with a minimal class. Also you should have any
interfaces already declared that may need to be implemented.
[...]

Well you can do it that way, but you'll find the majority of TDD
practicing folks write the entire test case before going anywhere near
the code to make it work.

As in...


class TestCalulator extends TestCase {

public void testAddingTwoZeros() {
Calculator calc = new Calculator();
assertEquals("Wrong answer!", 0 calc.add(0, 0);
}
}

Now I know what Calculator looks like and can implement just enough to
make the test pass.

But I haven't even started writing the Calculator class yet ...

I thought the TDD best practices was first to write the interface:

The way I have seen TDD defined (can't seem to find any links to it at
the moment) is that you don't write any code until you first have a
failing test case for it.

Now it is probably likely that you would write the interface first
because when adding this feature you would not be starting with the
calculator implementation, but with the code that calls it. That calling
code will need the interface to compile without errors. You create the
interface to get the caller to compile then you have to write the
implementation to get it to pass.
 
A

Andrew McDonagh

Dale said:
Oliver said:
Andrew McDonagh said:
Jim wrote:
On 11 May 2006 18:47:03 -0700, (e-mail address removed) wrote:

The tutorial says "...according to TDD... " we
should be able to create the test case before writing any code for the
class to be tested. [...]

At a minimum I had to create a class with the signature expected by
JUnit Test Case for the wizard to build the JUnit code.


I usually start with a minimal class. Also you should have any
interfaces already declared that may need to be implemented. [...]

Well you can do it that way, but you'll find the majority of TDD
practicing folks write the entire test case before going anywhere
near the code to make it work.

As in...


class TestCalulator extends TestCase {

public void testAddingTwoZeros() {
Calculator calc = new Calculator();
assertEquals("Wrong answer!", 0 calc.add(0, 0);
}
}

Now I know what Calculator looks like and can implement just enough
to make the test pass.

But I haven't even started writing the Calculator class yet ...

I thought the TDD best practices was first to write the interface:

The way I have seen TDD defined (can't seem to find any links to it at
the moment) is that you don't write any code until you first have a
failing test case for it.

Absolutely!

See
http://www.testdriven.com/files/doshi/TestDrivenDevelopmentReferenceGuide.pdf

Now it is probably likely that you would write the interface first
because when adding this feature you would not be starting with the
calculator implementation, but with the code that calls it. That calling
code will need the interface to compile without errors. You create the
interface to get the caller to compile then you have to write the
implementation to get it to pass.

No, with TDD, you'd only create an Interface if you need it - and you
only need it if you have a testcase that makes you need it OR a
refactoring produces the need for it. (e.g. removing duplication, by
extracting an common Interface from two classes that are almost identical.)
 
D

Dale King

Andrew said:
No, with TDD, you'd only create an Interface if you need it - and you
only need it if you have a testcase that makes you need it OR a
refactoring produces the need for it. (e.g. removing duplication, by
extracting an common Interface from two classes that are almost identical.)

That's where I disagree. I've argued before with someone claimed that
according to YAGNI you would never create an interface until you have
two classes that would implement the interface. I disagree strongly with
that notion.

I actually disagree with YAGNI or more particularly with this
overstatement of it.

From a previous discussion I had on the subject:

YAGNI flies in the face of sound engineering judgment. The real problem
is that it is a statement not a question. Good engineering is about
balancing trade offs and cost benefit analysis. Do you really want an
engineer on a safety critical device designing by proclamations like
"You aren't going to need it"?

To me YAGNI should be replaced with a series of questions:

- How likely is it that you are ever gonna need it?
- How likely is it that someone else is gonna need it?
- How much will it cost to wait until someone does need it?
- How much does it cost to go ahead and do it now?
- How much will it cost if someone does need it, they don't have it, and
they have to work around the fact that it isn't there?
- Is the design better (e.g. better encapsulation, tighter coupling,
lower cohesion, more flexible) if I add it even if I don't need it yet?

You can't necessarily know the future with absolute certainty, but you
can make reasonable predictions and weigh the probabilities and the
costs and benefits. YAGNI assumes that there is no probability that any
one will need it and the costs of adding it now versus later are
constant. Neither of these are universally true.

It is quite often the case that you can say with high probability it
will be needed and it is almost always the case that it is much cheaper
to add something in the beginning than to add it later.

When you start talking about public API's that are exposed to other
programmers outside of your control then the cost of adding something
later is extremely high and you really have to try to predict how it is
going to be used.

I'm not advocating over-designing systems, just using good, engineering
judgment instead of using over-simplistic platitudes like YAGNI.

So there are many good reasons for using interfaces even if you don't
have a bona fide "need" yet.

I can't say with any certainty in this hypothetical example, but I could
reasonably see constraints that would lead you to create the interface
first.

But my actual point was that the need to create the interface did not
come from the creation of the implementation, but from the caller of the
implementation and its tests.
 
A

Andrew McDonagh

Dale said:
That's where I disagree. I've argued before with someone claimed that
according to YAGNI you would never create an interface until you have
two classes that would implement the interface. I disagree strongly with
that notion.

YAGHI (You Aint Gonna Need It) and DTSTTCPW
(DoTheSimplestThingThatCouldpossiblyWork) are XP concepts more than TDD
ones. Its just that the majority of TDDers tend to be Agile (XP, Scrum,
etc) Developers also and so naturally favour them.
I actually disagree with YAGNI or more particularly with this
overstatement of it.

From a previous discussion I had on the subject:

YAGNI flies in the face of sound engineering judgment. The real problem
is that it is a statement not a question. Good engineering is about
balancing trade offs and cost benefit analysis. Do you really want an
engineer on a safety critical device designing by proclamations like
"You aren't going to need it"?

To me YAGNI should be replaced with a series of questions:

- How likely is it that you are ever gonna need it?
- How likely is it that someone else is gonna need it?
- How much will it cost to wait until someone does need it?
- How much does it cost to go ahead and do it now?
- How much will it cost if someone does need it, they don't have it, and
they have to work around the fact that it isn't there?
- Is the design better (e.g. better encapsulation, tighter coupling,
lower cohesion, more flexible) if I add it even if I don't need it yet?

You can't necessarily know the future with absolute certainty, but you
can make reasonable predictions and weigh the probabilities and the
costs and benefits. YAGNI assumes that there is no probability that any
one will need it and the costs of adding it now versus later are
constant. Neither of these are universally true.

It is quite often the case that you can say with high probability it
will be needed and it is almost always the case that it is much cheaper
to add something in the beginning than to add it later.

YAGNI does not mean 'turn off your brain and ignore all of the skills
you have learned'

It merely means, 'think about these cases, keep them in mind when
designing, but unless you need them 'AT THIS VERY MOMENT', dont
implement them.

You might well need them 5 minutes later, next month, quarter or year,
but AT THIS VERY MOMENT you dont, so dont worry too much. You might need
later but for now you dont, so its better business value to concentrate
on the things that you need now.

That being said, its not a license for being dumb or lazy and making
stupid design choices - see the end of this email for an account of when
it did happen on one of my previous teams.

When you start talking about public API's that are exposed to other
programmers outside of your control then the cost of adding something
later is extremely high and you really have to try to predict how it is
going to be used.

I'm not advocating over-designing systems, just using good, engineering
judgment instead of using over-simplistic platitudes like YAGNI.

So there are many good reasons for using interfaces even if you don't
have a bona fide "need" yet.


Public or rather Published APIs are different to non-public APIs and I'd
agree with you, that you'd want to make sure you use Interfaces from the
start.

In fact with published APIs I'd make sure I only ever have Interfaces,
there would be no Classes (concrete or abstract). As good design
experience has shown that classes in published APIs cause more trouble
for the client than benefit.

But then again, YAGNI isn't violated here. You DO need an API now, and
your design choice should be the most appropriate for what you need to
do now, which in this case means testing and creating an Interface.

You deliberately start out with a Failing testcase that makes use of the
Interface and not the class thats implementing it.

This also does not violate DTSTTCPW for the same reasons.


Again, these ideas are not about ignoring sound engineering principles
that we have learned, its about learning to apply them When They Are
Truly Needed.
I can't say with any certainty in this hypothetical example, but I could
reasonably see constraints that would lead you to create the interface
first.

yeah its a simple example.
But my actual point was that the need to create the interface did not
come from the creation of the implementation, but from the caller of the
implementation and its tests.

This can happen. It'll happen alot when you have a any reasonable sized
code base. TDDing tends to introduce interfaces very quickly as they
provide means of injecting or inverting dependencies, which makes
testing SO MUCH MORE easier!

The upside of Easy To Test Code, is that it naturally is highly
decoupled and cohesive. This stems from the fact that every class has at
least two clients :

1) The testcases
2) The other classes/interfaces within the system.

Without testing, its easy to create classes within an overall well
designed system, that still have high couplings and low cohesiveness.,
simply because we may not see a need for breaking these at that time.
Where as TDD creates that need straight away.

That being said, anyone saying that TDD will prevent these is barking
mad and a liar!

TDD doesn't prevent anything. Its a design methodology.

And like any design methodology can be used to create crap, awful
tangled messes if applied wrongly.

The same goes for YAGNI and DTSTTCPW being applied blindly and naively.

In a previous job, two experienced developers who were pair programming
no less! Decided for some reason (probably laziness rather than
stupidity, but who knows) to create a Singleton instead of just Creating
One instance of a class.

The reason they gave was both....

DTSTTCPW

For them, this gave them license to sprinkle the GUI code base with
invocations of the static method 'getInstance()' to gain access to the
singleton. This was 'easier' than changing the design so that an
instance of the class could be passed around or obtained as would have
been a more appropriate design.

YAGNI

'Whilst we NEED to have multiple instances next month, TODAY we only
need one instance so lets create a Singleton!!'.

They effectively ignored the sound design experience they both have in
favour of an easy life, for that day.

Needless to say, the rest of the team wasn't impressed!

And it was yours truly that then had to spend 2 days changing and
refactoring the code in order to remove the singleton. Mind you, this
wasn't all bad as it allowed me to show the team how to actually apply
refactoring in small steps to change a large design.

I hope this clears some of the picture of what YAGNI and DTSTTCPW
actually mean, but feel free to fire more questions about them if not.

Regards

Andrew
 
C

Chris Uppal

Andrew said:
YAGNI does not mean 'turn off your brain and ignore all of the skills
you have learned'

It merely means, 'think about these cases, keep them in mind when
designing, but unless you need them 'AT THIS VERY MOMENT', dont
implement them.

There's another consideration which (IMO) should be taken into account when
deciding what the YAGNI/DTSTTCPW principles are /actually/ telling us about
some specific design question. Quite often it is /easier/ to solve a somewhat
more general question than is actually required.

That's to say that the code can be simpler, easier to understand, and easier to
write. I presume that is because the more specific solution tends to tangle
the specifics with the underlying generality -- thus obscuring both. You get a
mess instead of a clean separation between a feature and an /application/ of
that feature.

Doesn't happen all the time, or even most of the time, but it does happen quite
often.

Your later example (snipped) could be interpreted as the developers failing to
realise this.

-- chris
 
D

Dale King

Andrew said:
YAGNI does not mean 'turn off your brain and ignore all of the skills
you have learned'

I agree that it shouldn't mean that, but I can't think of too many
instances where YAGNI has come that it meant anything but that. I have
seen YAGNI and DTSTTCPW used to justify throwing out the simplest design
principles and for creating really crappy code.

Those you get that YAGNI really just means don't waste a lot of effort
in overdesigning the system think that is obvious and don't go around
saying that. The most vocal ones that go around quoting YAGNI are the
ones that use it as an excuse to stop thinking.
It merely means, 'think about these cases, keep them in mind when
designing, but unless you need them 'AT THIS VERY MOMENT', dont
implement them.

And I find "if you need them at this very moment" to not be a very good
test and find the tests I gave above better.
You might well need them 5 minutes later, next month, quarter or year,
but AT THIS VERY MOMENT you dont, so dont worry too much. You might need
later but for now you dont, so its better business value to concentrate
on the things that you need now.

That being said, its not a license for being dumb or lazy and making
stupid design choices - see the end of this email for an account of when
it did happen on one of my previous teams.

In reality that seems to be the primary use for YAGNI that I have seen.
My point is that YAGNI is stated too simply and it should be expanded
upon to avoid this abuse.
Public or rather Published APIs are different to non-public APIs and I'd
agree with you, that you'd want to make sure you use Interfaces from the
start.

In fact with published APIs I'd make sure I only ever have Interfaces,
there would be no Classes (concrete or abstract). As good design
experience has shown that classes in published APIs cause more trouble
for the client than benefit.

But YAGNI doesn't say anything about that. YAGNI is not explained well
enough to avoid those that would apply it to this case to say that you
shouldn't have the interfaces.

In the case of published API's it may be someone else that needs it not
you and you really do have to make an attempt at trying to predict the
future. You can't just say that the future can't be predicted and you
can change it later when the need does arise.

But once again that is not stated anywhere in regards to YAGNI.
But then again, YAGNI isn't violated here. You DO need an API now, and
your design choice should be the most appropriate for what you need to
do now, which in this case means testing and creating an Interface.

You deliberately start out with a Failing testcase that makes use of the
Interface and not the class thats implementing it.

This also does not violate DTSTTCPW for the same reasons.

I have seen YAGNI restated to say that you should never create an
interface until you have two concrete classes that implement the
interface, no exceptions. According to those people YAGNI would be violated.

I find in general that it goes beyond just public API's. Often whenever
you have one class that talks to another class that should probably be
through an interface. In reality even if I don't have 2 concrete classes
in the application I usually do have 2 classes that implement the
interface: the one in the actual application and the mock object that is
created to test the calling code (using JMock).
Again, these ideas are not about ignoring sound engineering principles
that we have learned, its about learning to apply them When They Are
Truly Needed.

Because the over simplistic way that YAGNI is stated leads to too many
people using it as a justification for ignoring sound engineering
principles, I think it should be changed to talk about how and when they
should be applied.
This can happen. It'll happen alot when you have a any reasonable sized
code base. TDDing tends to introduce interfaces very quickly as they
provide means of injecting or inverting dependencies, which makes
testing SO MUCH MORE easier!

The upside of Easy To Test Code, is that it naturally is highly
decoupled and cohesive. This stems from the fact that every class has at
least two clients :

1) The testcases
2) The other classes/interfaces within the system.

Without testing, its easy to create classes within an overall well
designed system, that still have high couplings and low cohesiveness.,
simply because we may not see a need for breaking these at that time.
Where as TDD creates that need straight away.

I agree and as such said that above.
That being said, anyone saying that TDD will prevent these is barking
mad and a liar!

I don't see anyone saying that.
TDD doesn't prevent anything. Its a design methodology.

And like any design methodology can be used to create crap, awful
tangled messes if applied wrongly.

The same goes for YAGNI and DTSTTCPW being applied blindly and naively.

And my point is that this could be prevented if YAGNI were restated to
make this misapplication less rampant.
In a previous job, two experienced developers who were pair programming
no less! Decided for some reason (probably laziness rather than
stupidity, but who knows) to create a Singleton instead of just Creating
One instance of a class.

The reason they gave was both....

DTSTTCPW

For them, this gave them license to sprinkle the GUI code base with
invocations of the static method 'getInstance()' to gain access to the
singleton. This was 'easier' than changing the design so that an
instance of the class could be passed around or obtained as would have
been a more appropriate design.

YAGNI

'Whilst we NEED to have multiple instances next month, TODAY we only
need one instance so lets create a Singleton!!'.

They effectively ignored the sound design experience they both have in
favour of an easy life, for that day.

Needless to say, the rest of the team wasn't impressed!

This is a very common occurrence in my experience. Don't you think if
that if these two principles were expanded upon as I did above that it
would reduce the likelihood of such abuse?
And it was yours truly that then had to spend 2 days changing and
refactoring the code in order to remove the singleton. Mind you, this
wasn't all bad as it allowed me to show the team how to actually apply
refactoring in small steps to change a large design.

I hope this clears some of the picture of what YAGNI and DTSTTCPW
actually mean, but feel free to fire more questions about them if not.

I think *we* agree on what it means, but your experience seems to be the
same as mine that there are plenty of others that disagree. The way that
these principles are stated actually leads to this misunderstanding.

For a *long* discussion I had on the subject 6 years ago, see this thread*:

<http://groups.google.com/group/comp..._frm/thread/8d68c4ecb0bdc35c/937e667679b07689>

* Note that google groups seems to be confused on this thread and the
index on the left seemed to have some problems and did not navigate
through the thread correctly, so it is kind of hard to read the thread.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,479
Members
44,900
Latest member
Nell636132

Latest Threads

Top