Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / May 2006

Tip: Looking for answers? Try searching our database.

New to JUnit... Eclipse Question

Thread view: 
ducnbyu@aol.com - 12 May 2006 02:47 GMT
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!
Jim - 12 May 2006 03:44 GMT
>Hi,
>
[quoted text clipped - 26 lines]
>
>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
ducnbyu@aol.com - 12 May 2006 17:55 GMT
>I usually start with a minimal class.

>From what I read this seems to be slightly contrary to TDD, but I like
that the wizard can generate the stubs with this approach.
ducnbyu@aol.com - 12 May 2006 18:02 GMT
>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!
Andrew McDonagh - 12 May 2006 19:53 GMT
>> Hi,
>>
[quoted text clipped - 38 lines]
>
> 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 ...
Oliver Wong - 12 May 2006 20:46 GMT
>>> 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
[quoted text clipped - 14 lines]
>
> 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
Dale King - 15 May 2006 18:40 GMT
>>>> The tutorial says "...according to TDD... " we
>>>> should be able to create the test case before writing any code for the
[quoted text clipped - 28 lines]
>
>    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.

Signature

 Dale King

Andrew McDonagh - 15 May 2006 19:03 GMT
>>>>> The tutorial says "...according to TDD... " we
>>>>> should be able to create the test case before writing any code for the
[quoted text clipped - 32 lines]
> 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.)
Dale King - 15 May 2006 21:01 GMT
>> Now it is probably likely that you would write the interface first
>> because when adding this feature you would not be starting with the
[quoted text clipped - 7 lines]
> 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.

Signature

 Dale King

Andrew McDonagh - 21 May 2006 22:47 GMT
>>> Now it is probably likely that you would write the interface first
>>> because when adding this feature you would not be starting with the
[quoted text clipped - 13 lines]
> 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.
[quoted text clipped - 27 lines]
> 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
[quoted text clipped - 6 lines]
> 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
Chris Uppal - 22 May 2006 09:35 GMT
> 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
Dale King - 22 May 2006 15:06 GMT
>> 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.
[quoted text clipped - 30 lines]
> 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
[quoted text clipped - 4 lines]
> 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.

>> When you start talking about public API's that are exposed to other
>> programmers outside of your control then the cost of adding something
[quoted text clipped - 16 lines]
> 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
[quoted text clipped - 4 lines]
>
> 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.

>> 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
[quoted text clipped - 16 lines]
> 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
[quoted text clipped - 20 lines]
>
> 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
[quoted text clipped - 3 lines]
> 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.lang.java.programmer/browse_frm/thread/8d68c
4ecb0bdc35c/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.   

Signature

 Dale King

Owen Jacobson - 12 May 2006 03:52 GMT
On Thu, 11 May 2006 18:47:03 -0700, ducnbyu wrote:

> 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
[quoted text clipped - 9 lines]
> 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.
monang - 12 May 2006 10:34 GMT
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.
ducnbyu@aol.com - 12 May 2006 17:52 GMT
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
Andrew McDonagh - 12 May 2006 19:49 GMT
> Hi,
>
[quoted text clipped - 26 lines]
>
> Thanks!

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

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


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.