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 / December 2005

Tip: Looking for answers? Try searching our database.

JUnit et al approach - criticisms

Thread view: 
VisionSet - 27 Nov 2005 17:10 GMT
Does anyone have anything negative to say about using JUnit or a similar
approach in the overall lifecycle of their project?

--
Mike W
Thomas Hawtin - 27 Nov 2005 17:42 GMT
> Does anyone have anything negative to say about using JUnit or a similar
> approach in the overall lifecycle of their project?

That's a difficult one. Issues with JUnit implementation of the concept,
certainly. I actually think unit testing has a very localised effect on
the running of a project, and needn't impact on other aspects of the
life-cycle. Kind of like having a common set of code formatting conventions.

The only negative thing I can come up with is that writing tests is
really, really boring. Pissing about with debuggers, traces, printfs and
bug reports is much more interesting (true).

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

VisionSet - 27 Nov 2005 17:45 GMT
> I actually think unit testing has a very localised effect on
> the running of a project, and needn't impact on other aspects of the
> life-cycle.

mmm, depends when you write the tests I suppose.

--
Mike W
Thomas Hawtin - 27 Nov 2005 18:07 GMT
>>I actually think unit testing has a very localised effect on
>>the running of a project, and needn't impact on other aspects of the
>>life-cycle.
>
> mmm, depends when you write the tests I suppose.

Together with the code is traditional.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

VisionSet - 27 Nov 2005 18:12 GMT
> >>I actually think unit testing has a very localised effect on
> >>the running of a project, and needn't impact on other aspects of the
[quoted text clipped - 3 lines]
>
> Together with the code is traditional.

Okay, it depends when you write the code!
Or what weight of RUP you are following - something I'm a bit at odds with,
the lighter weight approaches seem to emphasise unit testing more.

--
Mike W
slippymississippi@yahoo.com - 11 Dec 2005 17:22 GMT
> The only negative thing I can come up with is that writing tests is
> really, really boring.

I think that's where test-driven-development really proves its mettle.
You write your methods and tests as stubs.  Then you flesh out a test
to satisfy your requirement, flesh out a method that satisfies the
test, and then run the Junit test.  How it reacts will give you insight
into what problems you might have with your design.  Refactor, then
test again, until your method is tight.  Boom, thirty minutes have gone
by, and you move on to the next method.  In one day, you can have a
complex class completely fleshed out and fully tested, with a suite of
JUnit tests that will let you know if anything gets broken by future
code changes.  Because of this, you jump confidently into massive
refactoring exercises without a blink, where before you would
vascillate in the face of such an exercise for hours or even days.
Roedy Green - 27 Nov 2005 17:45 GMT
>Does anyone have anything negative to say about using JUnit or a similar
>approach in the overall lifecycle of their project?

Frank Zappa named his daughter Moon Unit. This is a blatant rip off of
the Zappa name.

Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Andrew McDonagh - 27 Nov 2005 22:40 GMT
> Does anyone have anything negative to say about using JUnit or a similar
> approach in the overall lifecycle of their project?
>
> --
> Mike W

Curious, why would testing in any form or with any framework  be a
negative thing?

Keep in mind, JUnit (and its other language variants dUnit,cppUnit,
sUnit, NUnit, etc) are just unit testing frameworks and as such can be
used in may ways.

The reason I mention this, is because whilst there is value in unit
testing our code, these particular frameworks have come about to support
TestDrivenDevelopment (TDD).

TDD uses unit tests as a means of capturing the design that we create,
much like UML diagrams capture design.

TDD is a design methodology not a testing one.

The TDD cycle being:

1 Make a Failing test
2 Make the test pass
3 Refactor to remove duplication

However, every time this cycle has been completed, the existing tests
start to also be a regression test suite for the code at the unit level.

TDD's unit tests (or more right -Programmer tests) do not replace
acceptance/integration tests - they support them.

As for JUnit - I have only good things to say about it - I've learnt
more about real OO, design, development & testing in the 4 years I've
been using it, than in the previous 6 years developing.

Andrew
Mike Schilling - 28 Nov 2005 00:43 GMT
> Does anyone have anything negative to say about using JUnit or a similar
> approach in the overall lifecycle of their project?

The JUnit approach (that the first failure ends the test) seems unproductive
to me. At times it's apt, but there are other times where I'd like to
continue the test and generate a report of all the failures rather than only
be told about the first one.
Andrew McDonagh - 28 Nov 2005 00:57 GMT
>>Does anyone have anything negative to say about using JUnit or a similar
>>approach in the overall lifecycle of their project?
[quoted text clipped - 3 lines]
> continue the test and generate a report of all the failures rather than only
> be told about the first one.

Why?

Normally any subsequent failures are just by productions of the initial
failure.  So, fixing the first failures usually fixes all of the others.

The later failures in these cases are just noise.

Andrew
Mike Schilling - 28 Nov 2005 01:04 GMT
>>>Does anyone have anything negative to say about using JUnit or a similar
>>>approach in the overall lifecycle of their project?
[quoted text clipped - 8 lines]
> Normally any subsequent failures are just by productions of the initial
> failure.  So, fixing the first failures usually fixes all of the others.

Often, that's true.  Sometimes not.   JUnit has no provision for the latter
case.
stevengarcia@yahoo.com - 10 Dec 2005 21:17 GMT
It depends on how you write your tests and execute them, if you use the
JUnit task in Ant you can run all of your tests and see which ones
failed at the end.
Adam Maass - 28 Nov 2005 06:17 GMT
> Does anyone have anything negative to say about using JUnit or a similar
> approach in the overall lifecycle of their project?

I *like* JUnit; I have a great deal of confidence that the code for which I
have JUnit tests works as expected.

Drawbacks to JUnit:

1. It is hard to get an entire project to adopt JUnit if not everyone
believes in automated unit tests.

2. It is sometimes (often, in our case) difficult to write a *unit* test for
each class in isolation.

3. Doing the work to get adequate test coverage from a unit test suite is
generally a thankless job -- unless management buys in to the notion that it
is worthwhile and makes the time to get it done.

4. Maintaining the test suite along with the code it tests is sometimes
painful. (I just changed some code and I have a failing test. Is the test
failing because it's a real failure of the code or because the test case is
now incorrect?)

5. You have to train the people who write the tests what constitutes a good
test. (IE, random or pseudorandom inputs are a bad idea; fixed paths on a
filesystem are a bad idea; etc.)
Thomas Hawtin - 28 Nov 2005 13:26 GMT
> 1. It is hard to get an entire project to adopt JUnit if not everyone
> believes in automated unit tests.

And get them to believe that what they are doing isn't some kind of
magical special case.

> 2. It is sometimes (often, in our case) difficult to write a *unit* test for
> each class in isolation.

It often requires that code is written in a "purer" style.

> 3. Doing the work to get adequate test coverage from a unit test suite is
> generally a thankless job -- unless management buys in to the notion that it
> is worthwhile and makes the time to get it done.

If you've got management who consider unit testing gold plating... then
you've probably got worse problems.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Mike Schilling - 29 Nov 2005 06:14 GMT
> If you've got management who consider unit testing gold plating... then
> you've probably got worse problems.

Have you never had managers who said things like "We're in crunch mode, so
we can't afford to do as much testing as we'd like to."?  If so, you're a
very lucky man.
Chris Uppal - 29 Nov 2005 09:57 GMT
> Have you never had managers who said things like "We're in crunch mode, so
> we can't afford to do as much testing as we'd like to."?

I've had /customers/ who said that.

(To be fair, the customers had their own test plans, so we weren't installing
underdone software, only /shipping/ it ;-)

   -- chris
Mike Schilling - 29 Nov 2005 13:23 GMT
>> Have you never had managers who said things like "We're in crunch mode,
>> so
[quoted text clipped - 5 lines]
> installing
> underdone software, only /shipping/ it ;-)

It's still foolish.  "We want to delay finding the bugs, so they'll be
harder and more expensive to fix."
Chris Uppal - 29 Nov 2005 15:08 GMT
> > > Have you never had managers who said things like "We're in crunch
> > > mode, so
[quoted text clipped - 8 lines]
> It's still foolish.  "We want to delay finding the bugs, so they'll be
> harder and more expensive to fix."

Not necessarily.  Both customers (it's only happened to me twice) were large,
experienced, and competent in the ways of IT.  I think their reasoning was
something like [in the following "we" means the customer, "they" means the mob
I worked for]:

   We have a hard deadline to go live with a system which, we hope, will
   include their software.  If not then we go live anyway with reduced
   functionality.
   We have only a limited time available for testing and are worried that it
   might be insufficient.
   Therefore we must ensure that we are not wasting /any/ time on
   inefficient testing.
   We know (by definition) exactly what priority to give to which functions
   and aspects of the system, and therefore are able to prioritise testing
   appropriately.
   Whatever testing we leave to them risks them spending too little time on
   things that are important to us, or too much time on things that we don't
   care so much about.

   Downside:
       a) They know the implementation of the system better that we do, and
           so they can do finer grained testing, and also can concentrate on
           things they consider (technically) high-risk.

   But on the other hand:
       a) There are some critical things that /only/ we can test properly.
       b) They have proved pretty good at delivering working systems in the
           past.
       c) They can be testing in parallel with us, and so can look for the
           things in downside (a) above (but we may have to pay extra
           for that -- must talk to the lawyers).
       d) We can blame them just as easily for delivering a buggy product as
           we can for delivering late ;-)  [*]

All in all I think it was certainly defensible, and probably sensible, decision
making.

(BTW, why should an error found by their testing be any more or less expensive
to fix than the same error found by our testing ?)

   -- chris

([*] A more cynical version of the same idea, the customer's manager in charge
of the project thinks:
   I have the choice of getting into acceptance testing on time, but with
   increased risk of the delivered product being unacceptable (which we
   would blame on the supplier), or of risking missing /my/ deadlines and
   being blamed myself for not managing the supplier properly.
   Hmm, /tough/ decision...
In all truth, I doubt if the thinking really was quite as cynical in the cases
I experienced, but one never knows.)
Mike Schilling - 29 Nov 2005 19:01 GMT
> (BTW, why should an error found by their testing be any more or less
> expensive
> to fix than the same error found by our testing ?)

Because the earlier you find a bug, the cheaper it is to fix it:

   Fewer people will run into it. (Ideally, only one, if it's found before
the code is released to a shared area.)
   Less of the system will be affected by the problem when there is less of
the system.
   If fixing it requires redesign, less of the system will be affected by
that.

Unless both of you are doing end-to-end testing of the complete system:
then, there's no particular reason.
Andrew McDonagh - 29 Nov 2005 23:07 GMT
>>(BTW, why should an error found by their testing be any more or less
>>expensive
[quoted text clipped - 11 lines]
> Unless both of you are doing end-to-end testing of the complete system:
> then, there's no particular reason.

And then theres developer memory. When a bug is introduced as a
directeffect of the work they are working upon (it identified before
they are 'done' or asap after they are 'done', then they are more likely
to 'know' (i.e. guess correctly) where the problem is. So they can
reproduce and fix quicker & therefore cheaper.
Roedy Green - 29 Nov 2005 18:21 GMT
On Tue, 29 Nov 2005 13:23:38 GMT, "Mike Schilling"
<mscottschilling@hotmail.com> wrote, quoted or indirectly quoted
someone who said :

>It's still foolish.  "We want to delay finding the bugs, so they'll be
>harder and more expensive to fix."

There are cases where it is not foolish.  E.g. You must have SOMETHING
to show for Java One. That date is not negotiable.  Even if it is
buggy you can dance around the bugs in a demo.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Mike Schilling - 30 Nov 2005 01:41 GMT
> On Tue, 29 Nov 2005 13:23:38 GMT, "Mike Schilling"
> <mscottschilling@hotmail.com> wrote, quoted or indirectly quoted
[quoted text clipped - 6 lines]
> to show for Java One. That date is not negotiable.  Even if it is
> buggy you can dance around the bugs in a demo.

If the project is of any complexity,  skipping unit testing is more likely
to result in nothing that's even demoable.
timjowers@gmail.com - 28 Nov 2005 14:15 GMT
Even with Rational Robot and other test tools problem #4 hits you -
especially when the test team is separate from the development team and
swings their own hammer for the project mangement.

JUnit makes for great regression tests. Well, the test suite has to be
made up properly. Testing tools like JMeter and others should be used.
Automating tools like Automate, LoadRunner, etc. should be used.
Banging out JUnits when an automated test can be recorded much more
easily is assanine unless the JUnits strive towards full code and input
coverage. What are the best JUnit-oriented tools? E.g. I used to use
BlackIce and related SW which did memory profiling as well as generated
drivers for C++ classes to do input handling testing so would like a
tool that, given a Java class, would generate the JUnit and test with
normal input tests (e.g. Integer.MIN, MAX, -1, 0, 1, etc.)

Integration of JUnit into a J2EE environment is tough.

Testing and writing JUnit tests are not one and the same. Test Driven
Design ("TDD" was traditionally for Technical Design Document so the
TDD acronym is overly overloaded.) is really a way of saying to gather
requirements. The "tests" of Test Driven Design are really design
validation tests and mostly not breakage tests, input range tests, bad
input handling tests, performance, or integration tests.

Test Driven Design is another way of saying "Fail to plan, plan to
fail" or any other old adage about how running in without a strategy is
fatal. Likewise, saying "JUnit" is not a magic arrow to kill bugs.

Happy coding,
TimJowers
stevengarcia@yahoo.com - 10 Dec 2005 21:26 GMT
>1. It is hard to get an entire project to adopt JUnit if not everyone
>believes in automated unit tests.

Definitely true!

>2. It is sometimes (often, in our case) difficult to write a *unit* test for
>each class in isolation.

This might be true for 2% of all classes, but if you write your test
first and then your production class so it passes the test, you will
always avoid this problem.  This is not always the easiest thing to do
though.

>3. Doing the work to get adequate test coverage from a unit test suite is
>generally a thankless job -- unless management buys in to the notion that it
>is worthwhile and makes the time to get it done.

If you are beginning work on a legacy system this can be EXTREMELY
difficult and something I generally don't recommend.  But all new code,
going forward, should have tests along side of it.

>4. Maintaining the test suite along with the code it tests is sometimes
>painful. (I just changed some code and I have a failing test. Is the test
>failing because it's a real failure of the code or because the test case is
>now incorrect?)

Yea, I agree with that.  When you have 100 test classes and 100
production classes you are maintaining a big codebase.  One of the
master skills of agile development is refactoring, not only production
code but also test classes.  I was not good at it a year ago, now I'm
pretty good at this aspect of programming.

>5. You have to train the people who write the tests what constitutes a good
>test. (IE, random or pseudorandom inputs are a bad idea; fixed paths on a
>filesystem are a bad idea; etc.)

Kind of like #1.  BTW, random imputs in some cases are the proper way
to write unit tests.  It depends on what test you are writing.
Chris Uppal - 28 Nov 2005 09:03 GMT
> Does anyone have anything negative to say about using JUnit or a similar
> approach in the overall lifecycle of their project?

I wouldn't want to put anyone off the idea of testing, but I do want to raise a
couple of small warning about automated tests.

Don't get me wrong, I /like/ automated tests -- what I want to say is that they
can have a downside too, and that you should be aware of it and compensate
accordingly.

[BTW, nothing in the following is Java-specific, even though I mention some
Java-based tools, they are only named as examples, and I may not even have used
them myself.]

Testing means many different things to different people and in different
contexts.  There are several axes of variation, the two I'm interested in here
are granularity, and attitude.

A wise man once told me that "testing is a deliberate attempt to break the
system".  I think that's a very good description of the attitude that should be
present when testing -- or rather, should be applied during /some/ testing.
And that's what I find is missing in almost any automated testing -- whether
the wildly faddish TDD or classical overnight test suites -- the purpose of the
test is to confirm that the system (or module) works.  There is no active
intent to make the system break, there is no intelligent exploration of
corner-cases, there is no inspired guessing at possible-unanticipated
combinations of inputs.  Above all, there is no exploration of the problem
space -- the suite tests the same combinations each time.  (The big exception
to this -- which I have very rarely seen used in practise -- is when automation
is used for a brute-force, exhaustive, exploration of a significant sub-set of
the problem space).  I like to see some real testing (in the above sense) as
part of the development effort.  To me (and assuming that exhaustive testing is
infeasible) that means interactive testing.  Write a test harness or use
something like BeanShell.  Try things out, did they work ?  Did they work
/exactly/ how you expected ?  Push things a bit.  Did the disk-light flash when
it shouldn't ?  Did the screen flicker more than you expected during your GUIs
repaint ?  Try wildly implausible combinations.  You are trying to break your
own code -- which requires imagination and attention to detail.  Some people
like to step through code under the debugger looking for stuff that "works",
but doesn't take quite the expected path through the cod; that's another
example of the same kind of thinking.

Anyway, the warning I wanted to give about automated testing isn't just that
it's not an adequate substitute for aggressive testing (in the above sense),
but also that there's a risk that it will /displace/ aggressive testing.  Once
the automated tests are written (whether before, along-side, or after the code
they apply to), it takes a great deal of self-discipline[*] not just to rely on
those tests.  Press the button, everything comes up green, "Good, it works!".
That's not /testing/ -- it has a great deal of value, but it's confirming that
the system works on some inputs, not trying to find the inputs that break it.

([*] /I/ don't have that much self-discipline, so -- although I've always put a
great deal of effort into testing -- I've settled into a working pattern where
I don't write automated tests until /after/ I'm satisfied that my stuff works.
So my tests are actually regression tests from the very first, since a newly
written test that fails is, according to my rules, a development failure
(either the test itself is buggy -- happens frequently -- or I'm writing tests
too soon).  Actually, I quite often write brute-force/exhaustive tests at this
point too, and failures there /are/ permitted.)

Now, obviously, it's not a black-and-white situation.  Automated test suites
can attempt to explore large chunks of the problem space -- if enough time is
devoted to it by sufficiently skilled and determined programmers.  (I take it
as obvious that /comprehensive/ test suites are a mere wish-fulfilment
fantasy -- the combinatorial explosion kills the idea stone dead.)  But
elaborate test suites have costs too.  Which brings me to the second point --
granularity.

Code changes.  Right from the start, it changes a lot.  (I'm not talking about
changes in response to changing requirements -- that's a different issue).  IMO
that change is a necessary part of getting a properly working and maintainable
system.  Tests, quite obviously, add "weight" to that, in the sense that any
test for a piece of functionality that is changed will have to change too.  If
you refactor stuff (and you've got any tests written) then you'll have to
refactor them too.  Tests, of any sort, inhibit the natural process of change
as a software design grows -- to take a silly example, there's not much point
in testing the property-file handling you are writing this morning if this
afternoon you are going to rip it out and replace it with Windows registry
lookup...    (Presumably a true TDDer would put that the other way around --
there's not much point in writing code to be tested by your property-file
handling tests if you are just going to rip them out and replace them with
Windows registry handling tests this afternoon ;-)  You have to balance the
cost of testing sub-components against the benefits, taking into account the
near certainty of change.  You can all-but eliminate the costs of testing stuff
that will later be scrapped by concentrating on end-to-end testing, testing a
single business function, rather than the components that interact to perform
it, but then (A) you are only exploring an extremely impoverished slice of the
problem space (not aggressive testing at all) and (B) you don't get the very
real benefits of unit tests.  So you'll probably decide that it's better to
have at least /some/ unit testing, and try to optimise the amount so that it
doesn't add too much weight to your development process.  Clearly, the easier
and simpler it is to invent, implement, and run each test, then more testing
you can do before you pass the break-even point.  And that's where my second
warning comes in -- in my experience, writing scripted tests (JUnit, and
similar) takes a lot of work, about an order of magnitude more work than doing
the same tests in the kind of interactive environment I as talking about
earlier.  So, in my experience, I can do about an order of magnitude /more/
testing of code-still-under-development (without compromising my development
fluidity) by avoiding the formal tools.  The downside is that I do end up
writing scripted tests /as well/ -- but only for the final code, and (as I've
already said) I prefer to use two different styles of testing anyway.

   -- chris
VisionSet - 28 Nov 2005 10:56 GMT
> Code changes.  Right from the start, it changes a lot.  (I'm not talking about
> changes in response to changing requirements -- that's a different issue).  IMO
[quoted text clipped - 4 lines]
> refactor them too.  Tests, of any sort, inhibit the natural process of change
> as a software design grows

Yes absolutely and that is my main bug bear.
From what I've seen, and that is very little, those enthusiastic about JUnit
writing tests early, have some really bad OO designs.  And I can understand
why, it's one thing mersillessly refactoring but when essentially that
requires rewrites of the tests it is demorallising beyond belief.
eXtreme programming extols the virtues of unit testing and stipulates
writing the tests first.  Oh it also does away with much of the design stage
too and promotes evolving designs from the code - much in the way I work
presently.  Doesn't sound like the two go hand in hand to me.

--
Mike W
Timbo - 29 Nov 2005 14:18 GMT
> A wise man once told me that "testing is a deliberate attempt to break the
> system".
Yes, this is a common view held in testing literature: a good test
is a test that produces a failure.

> I think that's a very good description of the attitude that should be
> present when testing -- or rather, should be applied during /some/ testing.
[quoted text clipped - 15 lines]
> repaint ?  Try wildly implausible combinations.  You are trying to break your
> own code -- which requires imagination and attention to detail.

While I agree 100% with your view on how inputs should be tested
(many test scripts I see test only the normal case behaviours), I
disagree that interactive testing is better at finding faults, and
that unit testing and aggresive testing are mutually exclusive. If
you are trying wildly implausible combinations of behaviour in an
attempt to produce a failure in an interactive mode, then you
should be testing that same behaviour in your automated tests. I
don't really see why interactive testing would produce more
interesting inputs if it's the same person writing the tests.

This is not to say that interactive scripts are worthless. They
can be quite useful for debugging.

> Anyway, the warning I wanted to give about automated testing isn't just that
> it's not an adequate substitute for aggressive testing (in the above sense),
[quoted text clipped - 4 lines]
> That's not /testing/ -- it has a great deal of value, but it's confirming that
> the system works on some inputs

That's exactly what testing is: confirming that a system works on
SOME inputs. As Dijkstra famously said: "Testing confirms the
presence of bugs, not their absence". While I agree that it takes
a good deal of discipline to maintain test scripts, IMO, it is
much more painful to sit down after every change and interactively
test, which is also testing only some of the inputs. This will
result in only testing the areas of the code that have changed,
and not testing the result of that on the rest of the system/module.

> ([*] /I/ don't have that much self-discipline, so -- although I've always put a
> great deal of effort into testing -- I've settled into a working pattern where
> I don't write automated tests until /after/ I'm satisfied that my stuff works.

I see no problem with that. Failure in testing processes generally
comes at the regression level. It's straightforward to test that
new functionality works as intended, but the effects of that
change on the rest of the system has to be tested also. As long as
those tests are automated, this makes the problem much more
straightforward.

> in my experience, writing scripted tests (JUnit, and
> similar) takes a lot of work, about an order of magnitude more work than doing
> the same tests in the kind of interactive environment I as talking about
> earlier.  

Is it really more difficult to add tests for new behaviour in a
script than it is to interactively test that behaviour? A bonus is
regression testing can be performed, and more importantly, the
tests are better documented.

Tim
Chris Uppal - 01 Dec 2005 14:07 GMT
> While I agree 100% with your view on how inputs should be tested
> (many test scripts I see test only the normal case behaviours), I
> disagree that interactive testing is better at finding faults, and
> that unit testing and aggresive testing are mutually exclusive.

If you have an adequate interactive testing environment, then interactive
testing is an order of magnitude faster, and far less disruptive, than writing
"formal" test code.  (If your environment is not such that you have that order
of difference, then I'd say that's a very serious flaw in your environment, not
a strength of jUnit ;-)  If creating scripted tests were as fast and fluid as
interactive testing, then I would much more nearly agree with you.

Another point is that much testing does not need to be repeated.  E.g. if I
have written some simple buffer manipulation, and want to run a quick sanity
check, then I'll try using inputs that are bunched around the buffer size.
There's no point in "freezing" such tests as code, since it is only useful for
the /specific/ code that I'm testing.  If that code changes the the test would
have to change (completely) too.  Of course, if the buffer handling is in any
way complex, then some proper regression tests should be created too (but
that -- in my book -- is a different issue, and it should wait until the code
has settled down).

One last point -- which to my mind is /extremely/ important, but which I failed
to bring out in my earlier post -- is that each time you "play" with your code
interactively, you will be running a /different/ test.  Think of it as "beta"
testing happening very early in the cycle.  It's /precisely/ the lack of that
variation which makes me uneasy about software (including my own) which is
tested only via scripts.

   -- chris
Timbo - 02 Dec 2005 10:54 GMT
> If you have an adequate interactive testing environment, then interactive
> testing is an order of magnitude faster, and far less disruptive, than writing
> "formal" test code.  (If your environment is not such that you have that order
> of difference, then I'd say that's a very serious flaw in your environment, not
> a strength of jUnit ;-)  If creating scripted tests were as fast and fluid as
> interactive testing, then I would much more nearly agree with you.

Well, we'll have to agree to disagree here, because I think that
if one's interactive testing is quicker than a test script, than
you are not testing a componenent adequately enough. For your
example of a buffer, one could write a automated script to test
different sizes (0,1,many) and the boundary of that in a matter of
minutes, which would be just as straightforward.

Either way, I'm guessing your interactive test code is something
like 'main' program that drives the unit in question. If that's
the case, I don't think it is much harder to write a test script
that reads in files placed in a specific test directory, with each
file specifying the input that you would otherwise be typing in,
and the expected output. It may take a bit more time, but you then
have a test suite that allows you to run your tests over and over
after each change, and that is easily extensible (add new test
input/output files), and easily changed.

> One last point -- which to my mind is /extremely/ important, but which I failed
> to bring out in my earlier post -- is that each time you "play" with your code
> interactively, you will be running a /different/ test.  Think of it as "beta"
> testing happening very early in the cycle.  It's /precisely/ the lack of that
> variation which makes me uneasy about software (including my own) which is
> tested only via scripts.

Yes, that is a very interesting point about running different
tests each time. However, you may use different tests each time,
but if the code-under-test has been changed, the tests you have
run previously are no longer valid, because they have tested a
different implementation.
Chris Uppal - 05 Dec 2005 10:50 GMT
> Well, we'll have to agree to disagree here, because I think that
> if one's interactive testing is quicker than a test script, than
> you are not testing a componenent adequately enough. For your
> example of a buffer, one could write a automated script to test
> different sizes (0,1,many) and the boundary of that in a matter of
> minutes, which would be just as straightforward.

Minutes !  Good gracious, man, I don't have /minutes/ to waste!

;-)

Seriously, if writing a test distracted me for minutes, then that is indeed
something that I would avoid.  That would be killing the fluidity of
development, not to mention causing an immense disturbance of my train of
thought.  As such it should be (IMO) postponed to a time when the software has
settled down, and I am in a position to concentrate on writing test code that
is not only sensible and reasonably thorough, but also clear and maintainable.

> Either way, I'm guessing your interactive test code is something
> like 'main' program that drives the unit in question.

No.  By interactive I /mean/ interactive.  The ideal environment for doing this
sort of thing is Smalltalk (or, perhaps, Lisp), but tools like BeanShell, etc,
can get you part of the way there.  Actually, I don't know of any Java
environment that /really/ supports interactive testing , but this is a pattern
of working that I developed before Java even existed (and long before I started
using Smalltalk).  It's a matter of making best use of the available tools, and
writing your own whenever necessary.

   -- chris
Timbo - 07 Dec 2005 09:54 GMT
>>Well, we'll have to agree to disagree here, because I think that
>>if one's interactive testing is quicker than a test script, than
[quoted text clipped - 6 lines]
>
> ;-)

LOL!

> Seriously, if writing a test distracted me for minutes, then that is indeed
> something that I would avoid.  That would be killing the fluidity of
> development, not to mention causing an immense disturbance of my train of
> thought.  As such it should be (IMO) postponed to a time when the software has
> settled down, and I am in a position to concentrate on writing test code that
> is not only sensible and reasonably thorough, but also clear and maintainable.

Fair enough. I'm the opposite. I like to run the test scripts
while I continue with other stuff (tidying up comments etc).

> No.  By interactive I /mean/ interactive.
Yeah, sorry, I meant an interactive 'main' program that drives the
testing by prompting for input etc.

> The ideal environment for doing this
> sort of thing is Smalltalk (or, perhaps, Lisp), but tools like BeanShell, etc,
[quoted text clipped - 3 lines]
> using Smalltalk).  It's a matter of making best use of the available tools, and
> writing your own whenever necessary.

In my best Homer Simpson voice: MMmmmmm... Smalltalk.....

Have you tried that BlueJ (not BlueJay) interactive environment
(I've never used it myself)? I seem to recall that was aimed at
beginners for interacting with stand-alone units, although I don't
really remember many details.
Chris Uppal - 10 Dec 2005 12:14 GMT
> Have you tried that BlueJ (not BlueJay) interactive environment
> (I've never used it myself)? I seem to recall that was aimed at
> beginners for interacting with stand-alone units, although I don't
> really remember many details.

I have tried it and have even recommended it.  It's important to realise that
its primarily a /teaching/ tool -- and a tool for teaching OO at that.  Some of
the ideas behind it come about as close as one can conveniently get to
"interacting with objects" rather than "writing code" being the central concept
of a good (OO) development environment.

And of course, once one can talk directly to one's objects, testing (in the
interactive sense I've been going on about) becomes easy.  Indeed there's a
sense in which that's all one ever does with them.

I have some ideas for a /fully/ interactive Java environment (needs bytecode
rewriting plus a bit of JNI) but with the layers of fluff that Sun keep adding
to the language, the gap between what's technically feasible (more-or-less
anything) and what's actaully worthwhile doing /in Java/ gets bigger and
bigger...

   -- chris
Ian Pilcher - 28 Nov 2005 14:21 GMT
> Does anyone have anything negative to say about using JUnit or a similar
> approach in the overall lifecycle of their project?

I only write code in my spare time, so take this accordingly.  My main
objection to the JUnit "philosophy" is that it does nothing to make
testing non-observable behavior easier.  Per the JUnit FAQs, they think
that only observable behavior should be unit tested most of the time.  I
simply don't agree with this.

Signature

========================================================================
Ian Pilcher                                        i.pilcher@comcast.net
========================================================================

Andrew McDonagh - 28 Nov 2005 22:19 GMT
>>Does anyone have anything negative to say about using JUnit or a similar
>>approach in the overall lifecycle of their project?
[quoted text clipped - 4 lines]
> that only observable behavior should be unit tested most of the time.  I
> simply don't agree with this.

What do you mean by 'non observable behavior'?

All code should had some effect upon the system else by definition that
code is not doing anything and should be deleted.

Confused.

Andrew
Thomas Hawtin - 29 Nov 2005 00:01 GMT
> What do you mean by 'non observable behavior'?
>
> All code should had some effect upon the system else by definition that
> code is not doing anything and should be deleted.

The behaviour may be difficult to observe. For instance, if there is a
cache of some intermediate result, you'd have to do some performance
testing to check.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Andrew McDonagh - 29 Nov 2005 01:00 GMT
>> What do you mean by 'non observable behavior'?
>>
[quoted text clipped - 6 lines]
>
> Tom Hawtin

sure it may be difficult, but its still observable therefore its has
some effect upon the system which makes it testable.

Ian was saying that non-oberveable code isn't catered for - to which I
and others say, is not  needed as non-oberveable means no effect, no
effect meaning whats the point in the code existing.
Chris Uppal - 29 Nov 2005 10:06 GMT
> What do you mean by 'non observable behavior'?
>
> All code should had some effect upon the system else by definition that
> code is not doing anything and should be deleted.

There is much behaviour which is not observable.  That is to say not legally
observable according to the laws of the Java language.  For instance:
1)    any non-public member variable
2)    any aspect of an object's state that is only reflected in
       its non-public behaviour
3)    any part of the execution state of another thread
4)    the locked/unlocked status of a monitor
There are probably others.  I would expect the first two of these to be the
most problematic in practise.

Additionally, there may be external restrictions -- e.g. it may be possible for
an application to log a message but not (without artificially boosting its
privileges) be permitted to read the resulting log.

   -- chris
Chris Uppal - 29 Nov 2005 11:35 GMT
I wrote:

> 2)    any aspect of an object's state that is only reflected in
>         its non-public behaviour

I meant to revise that before posting, and then hit the send button
prematurely.  The sentence should read "any apect [...] that is only feasibly
reflected in [...]".  If the behaviour is genuinely /never/ public then it
"doesn't matter", but there can certainly be cases where bugs could easily be
detected by examining non-public behaviour but which would be difficult or
inpractical to examine only using public behaviour.

   -- chris
Mike Schilling - 29 Nov 2005 13:21 GMT
>I wrote:
>
[quoted text clipped - 9 lines]
> detected by examining non-public behaviour but which would be difficult or
> inpractical to examine only using public behaviour.

This is the best reason I know of for C++'s "friend" feature; it allows a
test class to see the complete state of the class it's testing.
Andrew McDonagh - 05 Dec 2005 01:38 GMT
>>What do you mean by 'non observable behavior'?
>>
[quoted text clipped - 3 lines]
> There is much behaviour which is not observable.  That is to say not legally
> observable according to the laws of the Java language.  For instance:

UNit tests test the result of a call, of which there has to be some
output, else the code isn't doing any thing useful.

Note: All of the following answers rely upon normal Java access
privileges and do not assume the need to use any kind of reflection.

> 1)    any non-public member variable

If the ClassUnderTest (CUT) has a private member var that changes as a
result of the test AND its change is the result that will tell the test
if its passed, then we will need to somehow see that variable in one
form or another. In other words, the CUT would normally have some other
method that could be called to see if the private member has changed
(note not talking solely about a simple getter here - but it may be the
case).

The change may be that the private member has been nullified - in which
case, by stimulating the CUT again we can check for change.

An example here would be having a Listener reference. Our test could
give the CUT a MockListener which we verify is called when we stimulate
as necessary, then call the public method to set the listener var to
null then stimulate the CUT again and check the MockListener was NOT
called a second time.

Either or any other way, if a CUT is changing the state of a member var
and that change has no effect, then the member var is not needed - and
so delete it.

> 2)    any aspect of an object's state that is only reflected in
>         its non-public behaviour

Can you  give me an example of what you mean here, because I'd say that
state was not needed if it can't be detected from outside.

> 3)    any part of the execution state of another thread
> 4)    the locked/unlocked status of a monitor

Testing the state of execution of another thread, multi-threadness and
other threaded scenarios are not a unit tests, they are functional (ALA
Acceptance) tests.

These types of test are not what Junit was developed for and so 'out of
the box' it isn't supported very well. That being said that are add-ons
to do just those types of tests.

The main reason they were considered to be part of the unit testing
stage, is that they test functionality of the system, rather than the
behavior of a Unit (Class).  Acceptance/Functional tests are better
developed in other testing tools that support a scripting interface that
non-java developers can read, understand and use themselves to help
create tests (See FitNesse.org, Selenium, Watir, etc)

We would not normally write tests to detect monitor status itself, but
we could write tests to prove we don't get deadlocks.

Unit tests test individual classes/methods.

> There are probably others.  I would expect the first two of these to be the
> most problematic in practise.

Weird, to me they are the easiest.

> Additionally, there may be external restrictions -- e.g. it may be possible for
> an application to log a message but not (without artificially boosting its
> privileges) be permitted to read the resulting log.

A unit test is not a unit test if it relies upon external resources
and/or restrictions that can not be substituted at runtime - they are
acceptance tests.

In the example above, the unit test could very easily substitute the log
object the class (not the application - cause then we are acceptance
testing) is writing to, so it can verify the correct behavior.

This dependency injection (via constructor, setter, dynamically loaded
from resource file, retrieved from a singleton, etc) necessary for
testability results in a better more changeable & maintainable design.

>     -- chris

If this seems strange, feel free to knock up an SSCEE (or what ever its
called this week) example to which you have something that is
non-visible and so can't test and I'll show you how it could or if its
not a unit test.

Andrew
Chris Uppal - 05 Dec 2005 10:38 GMT
[choosing just this one paragraph as a representative of the whole post]

> A unit test is not a unit test if it relies upon external resources
> and/or restrictions that can not be substituted at runtime - they are
> acceptance tests.

This is simply playing with words.  I would not define "unit test" so narrowly,
and I /certainly/ would not relate the concept of "acceptance test" to external
resources in any way (they may use them, they may not).  An acceptance test has
alway (in my experience) been a test run by the /buyer/.  Anyway, if we do use
your restricted sense of "unit test" then I have never at any time indicated
any restriction of the validity of /my/ comments to "unit tests".  Indeed I
have little or no interest in them, nor in the religion that appears to
accompany the term when used so narrowly.

   -- chris
Mike Schilling - 05 Dec 2005 20:36 GMT
> [choosing just this one paragraph as a representative of the whole post]
>
[quoted text clipped - 9 lines]
> test has
> alway (in my experience) been a test run by the /buyer/.

I think you're being too specific here.  I use:

Unit test -- test that is part of a subsystem, verifying that a part of that
subsystem behaves correctly.  This may include both black- and white-box
testing.

Acceptance test -- test that is part of a subsystem's client, testing the
subsystem as called by that client.  This is black-box testing only, since
the client is allowed to know nothing of the subsystem's implementation.

To reemployment a subsystem safely, you need both unit tests and acceptance
tests from all clients.
Chris Uppal - 10 Dec 2005 14:16 GMT
> I think you're being too specific here.  I use:
>
> Unit test -- test that is part of a subsystem, verifying that a part of
> that subsystem behaves correctly.  This may include both black- and
> white-box testing.

No significant disagreement there.

Only two points I'd add.  One is that "unit testing" neither implies nor is
implied by the use of an xUnit framework.  (I doubt if you confuse the two, but
I think some people do).  The other is that given the fractal nature of
software designs, almost any test is simultaneously a unit test at one level
and an "integration test" at a lower level.

(I put "integration test" is scare quotes because that is not quite the usual
meaning of the term, but I don't know of anything closer in common usage.
Normally, in my experience, it is only used when a complete /system/ is being
tested -- full end-to-end functionality.)

> Acceptance test -- test that is part of a subsystem's client, testing the
> subsystem as called by that client.  This is black-box testing only, since
> the client is allowed to know nothing of the subsystem's implementation.

Hmm.  I would definitely call that odd use of the term.  At least in an
environment where one has genuine paying customers, the question that
"acceptance testing" addresses is not "does the code work?", but "are we going
to be paid?".  And, for all the importance of the first question, the second
has importance of a totally different order.  I think few people would want to
confuse the two ;-)

   -- chris
Mike Schilling - 10 Dec 2005 16:32 GMT
>> Acceptance test -- test that is part of a subsystem's client, testing the
>> subsystem as called by that client.  This is black-box testing only,
[quoted text clipped - 10 lines]
> want to
> confuse the two ;-)

Group A located in X that's using subsystem B written in Y back in 200Z are
customers for the group from Y, as are A's end-users.  I wish I had a full
acceptance test suite for, say, Xerces, so I'd know whether it's safe to
upgrade it.  If there were more hours in a week, I would have one.
Chris Uppal - 13 Dec 2005 09:07 GMT
> Group A located in X that's using subsystem B written in Y back in 200Z
> are customers for the group from Y, as are A's end-users.  I wish I had a
> full acceptance test suite for, say, Xerces, so I'd know whether it's
> safe to upgrade it.

Sounds as if we can at least agree that "acceptance testing" is done by the
consumer of the s/w rather than by the producer ?

   -- chris
Mike Schilling - 13 Dec 2005 16:56 GMT
>> Group A located in X that's using subsystem B written in Y back in 200Z
>> are customers for the group from Y, as are A's end-users.  I wish I had a
[quoted text clipped - 4 lines]
> the
> consumer of the s/w rather than by the producer ?

Sure; I never meant to suggest otherwise.
Andrew McDonagh - 13 Dec 2005 19:57 GMT
>>Group A located in X that's using subsystem B written in Y back in 200Z
>>are customers for the group from Y, as are A's end-users.  I wish I had a
[quoted text clipped - 5 lines]
>
>     -- chris

Who said differently?
Timbo - 12 Dec 2005 09:35 GMT
> Only two points I'd add.  One is that "unit testing" neither implies nor is
> implied by the use of an xUnit framework.  (I doubt if you confuse the two, but
[quoted text clipped - 6 lines]
> Normally, in my experience, it is only used when a complete /system/ is being
> tested -- full end-to-end functionality.)

I think you are right to use 'integration test' here. To me,
testing two units together is integration testing, and testing
full end-to-end functionality is just 'system testing'.
Andrew McDonagh - 12 Dec 2005 23:04 GMT
>> Only two points I'd add.  One is that "unit testing" neither implies
>> nor is
[quoted text clipped - 15 lines]
> units together is integration testing, and testing full end-to-end
> functionality is just 'system testing'.

but what is a unit?

To TDDers, its a Class or group of classes depending upon how the code
finally looks, nothing to do with how the code starts out.

This is because TDD is an evolutionary design technique.

We:

1) Write a failing test case.
   It doesn't compile because we haven't written the production code
yet. Write just enough to Make it compile  - stub the methods only.
Watch the test fail - cause we haven't filled the method bodies out yet.

2) Now Write Just Enough of the method bodies to make the test pass.

3) Refactor the code to remove duplication - this is the big design
improving part - easily done because we have a passing test to tell us
if we made a mistake in our refactoring.

Repeat until finished.

Whilst it true that xUnit frameworks can be and are used by teams who
don't do TDD, its authors wrote it to facilitate TDD. Currently the
majority of JUnit users are TDDers .

Andrew
Timbo - 13 Dec 2005 14:34 GMT
> but what is a unit?
>
> To TDDers, its a Class or group of classes depending upon how the code
> finally looks, nothing to do with how the code starts out.

Using OO terminology, I define a unit as a class. How to test that
unit in isolation depends on its dependencies. If it depends on
other classes from within the application, those should be stubbed
during unit testing, otherwise it is integration testing. If you
feel the CUT's dependents are simple enough, you may not feel the
need to unit test it, and will probably just use the production
classes instead of stubs, but that, in my mind, is not unit testing.

Tim
Mike Schilling - 13 Dec 2005 16:58 GMT
>> but what is a unit?
>>
[quoted text clipped - 8 lines]
> probably just use the production classes instead of stubs, but that, in my
> mind, is not unit testing.

To take this to an extreme, are you saying that  if I create a class that
represents XML QNames (i.e. that contains a namespace and a local name), and
I want to test another class that uses them, I need to stib out my QName
class to produce a true unit test?  What if I have a class that contains
only static constants?
Timbo - 14 Dec 2005 09:33 GMT
>>>but what is a unit?
>>>
[quoted text clipped - 14 lines]
> class to produce a true unit test?  What if I have a class that contains
> only static constants?

If it's only static constants, then it's really a data structure,
so no. But for your QName example, if it has getter/setter methods
for example, then unit testing would require it to have it's own
tests. I'm not saying that you should necessarily test it, but
it's not pure unit testing otherwise.
Mike Schilling - 14 Dec 2005 15:00 GMT
>>>>but what is a unit?
>>>>
[quoted text clipped - 19 lines]
> that you should necessarily test it, but it's not pure unit testing
> otherwise.

Of course QName needs its own tests.  My question is whether unit  testing
one of its clients requires stubbing it out.
Timbo - 14 Dec 2005 16:15 GMT
>>>>>but what is a unit?
>>>>>
[quoted text clipped - 25 lines]
> Of course QName needs its own tests.  My question is whether unit  testing
> one of its clients requires stubbing it out.

To be a unit test, it does. If you include it, you are not testing
the unit in isolation. However, with such a simple class,
personally I wouldn't bother stubbing it, because the stub is
likely to be just as complex as the the QName class itself. I'm
not saying there is anything wrong with this approach (I do it
quite often), but I would call that integration testing.
Mike Schilling - 14 Dec 2005 17:13 GMT
> To be a unit test, it does. If you include it, you are not testing the
> unit in isolation. However, with such a simple class, personally I
> wouldn't bother stubbing it, because the stub is likely to be just as
> complex as the the QName class itself.

Very true :-)

>I'm not saying there is anything wrong with this approach (I do it quite
>often), but I would call that integration testing.

Thanks for the response.  I think it's an odd distinction, myself, to say
"this is an integration test, because it depends on a 20-line class I wrote,
while this is a pure unit test because it depends only on the JDK classes,
the Apache Commons, and Xerces", but we can disagree about that.
Timbo - 16 Dec 2005 09:24 GMT
>>I'm not saying there is anything wrong with this approach (I do it quite
>>often), but I would call that integration testing.
[quoted text clipped - 3 lines]
> while this is a pure unit test because it depends only on the JDK classes,
> the Apache Commons, and Xerces", but we can disagree about that.

True, it is odd, but then where is the distinction? 50 lines? 100
lines? 1000? Maybe a metric related to the data structures used?
This way it is clear cut and easy to identify, and it fits with
the strict definition of 'unit testing'.

Regarding the 3rd party classes, one doesn't test them as part of
their unit/integration/system testing, so they don't come into the
picture (i.e. they are assumed correct by the fact that you are
not trying to find faults in them).
Mike Schilling - 16 Dec 2005 16:50 GMT
>>>I'm not saying there is anything wrong with this approach (I do it quite
>>>often), but I would call that integration testing.
[quoted text clipped - 7 lines]
> clear cut and easy to identify, and it fits with the strict definition of
> 'unit testing'.

Making that definition useless, IMHO.

> Regarding the 3rd party classes, one doesn't test them as part of their
> unit/integration/system testing, so they don't come into the picture (i.e.
> they are assumed correct by the fact that you are not trying to find
> faults in them).

With Xerces, at least, that's a poor assumption.
Timbo - 19 Dec 2005 10:52 GMT
>>>>I'm not saying there is anything wrong with this approach (I do it quite
>>>>often), but I would call that integration testing.
[quoted text clipped - 10 lines]
>
> Making that definition useless, IMHO.

Fair enough, but nobody can ever give me a definition of unit
testing other than this, so I'm sticking with it.

>>Regarding the 3rd party classes, one doesn't test them as part of their
>>unit/integration/system testing, so they don't come into the picture (i.e.
>>they are assumed correct by the fact that you are not trying to find
>>faults in them).
>
> With Xerces, at least, that's a poor assumption.

Do you test the Xerces libraries in your testing?
Mike Schilling - 19 Dec 2005 18:53 GMT
>>>Regarding the 3rd party classes, one doesn't test them as part of their
>>>unit/integration/system testing, so they don't come into the picture
[quoted text clipped - 4 lines]
>>
> Do you test the Xerces libraries in your testing?

Implicitly, yes, and I've certainly fixed bugs in them found by my "unit"
tests.
Timbo - 20 Dec 2005 09:45 GMT
>>>>Regarding the 3rd party classes, one doesn't test them as part of their
>>>>unit/integration/system testing, so they don't come into the picture
[quoted text clipped - 7 lines]
> Implicitly, yes, and I've certainly fixed bugs in them found by my "unit"
> tests.

Implicitly? From that I gather you mean that when you execute your
tests, some of the Xerces code is executed. That's not testing. By
testing, I mean select test cases, execute them, and compare
behaviour to the expected behaviour.

I think NOT assuming that the 3rd party libraries are correct
during testing is crazy. During debugging, by all means, you have
to keep an open mind, but not during testing. You'll end up with
test case explosion.
Andrew McDonagh - 13 Dec 2005 19:55 GMT
>> but what is a unit?
>>
[quoted text clipped - 10 lines]
>
> Tim

It depends upon how that class came into being, what it does and your
mood at the time.

In TDD we write a test, write the code, refactor.

now we normally start out by creating a class and its method we are
exercising. But after several test,code, refactor cycles we see that our
single class needs further simple refactorings because its really
several classes in one (e.g. a dispatcher type class which creates
instances of  different command classes).  but we started out with one
class and so far have one test class for it.

At this point we have a choice:

1) Leave the single test class as is - its testing our original class
and n other command classes.

2) Change the test class to test the original class, using fake/mock
Command objects.  Then move the testcase methods from the original
testclass into new test classes, one for each Command class.
Here we end up with lots of small test classes, each testing an
individual class.

Both approaches are fine - both are unit tests - thats how they started
out.

For me the point at which a Unit Test stops becoming a unit test, is
when its difficult to setup a test.  At this point the test code is
telling us - 'I'm a functional test'.

YMMV

Andrew
Timbo - 14 Dec 2005 09:44 GMT
> It depends upon how that class came into being, what it does and your
> mood at the time.
[quoted text clipped - 21 lines]
> Both approaches are fine - both are unit tests - thats how they started
> out.

I agree that both approaches are fine, but I disagree that the
first choice constitutes unit testing. Firstly, it's not testing
in isolation; and secondly, either the command classes are not
being specifically tested (and so cannot be said to be unit
tested), or they are being tested with the top-level module unit
tests, which means the tests are testing outside of the module's
boundary, so it's not unit testing.

(The word 'test' came up far too many times in that last sentence!)

Tim
Andrew McDonagh - 14 Dec 2005 19:40 GMT
>> It depends upon how that class came into being, what it does and your
>> mood at the time.
[quoted text clipped - 24 lines]
> I agree that both approaches are fine, but I disagree that the first
> choice constitutes unit testing.

Its ok to disagree.

> Firstly, it's not testing in isolation;

Its impractical to test any class in isolation, as we'd have to wrap all
Java & 3rd party libraries in order to fake/mock them to do so (never
mind about Object.class).  If your class uses a String object - you
don't stub that do you?  There's no difference between those classes and
your own.

> and secondly, either the command classes are not being specifically
> tested (and so cannot be said to be unit tested), or they are being
> tested with the top-level module unit tests, which means the tests are
> testing outside of the module's boundary, so it's not unit testing.

maybe have missed something I said.... those command classes were
*extracted* from the single class.  Every line of code within the
original single class was covered by a unit test. Every scenario for
that single class was captured as a unit test.

Its just that part of TDD is 'refactoring' where we look at the current
design and improve things.  In this case, we saw that the single class
was not conforming to Single Responsibility Principle, so we extracted
those hidden classes from within it.
The result is several small classes, where every line of code for all of
them is still covered by tests for the original class - in fact we don't
touch those tests - they create a safety net for our refactorings.

So, the choice we made was to separate the logic into discrete classes,
but we could have left them as one class - do you really think this
means the previous unit test is now an integration test?

> (The word 'test' came up far too many times in that last sentence!)

Always does ;)

> Tim
Timbo - 16 Dec 2005 09:30 GMT
>> Firstly, it's not testing in isolation;
>
[quoted text clipped - 3 lines]
> don't stub that do you?  There's no difference between those classes and
> your own.

There is a difference. Those classes are assumed to be correct for
the purpose of testing (i.e. you aren't trying to find faults in
them, so you aren't testing them). Third-party classes are not
treated as units in your code, and therefore need not be stubbed.
Similarly, if you are relying on a previously written and verified
internal library, you don't include that in the testing of a
system you are developing.

>> and secondly, either the command classes are not being specifically
>> tested (and so cannot be said to be unit tested), or they are being
[quoted text clipped - 5 lines]
> original single class was covered by a unit test. Every scenario for
> that single class was captured as a unit test.

Sorry, I didn't miss it, I just wasn't thinking about that when I
wrote that paragraph :-)  So, as I mentioned above, the
'top-level' tests are testing outside of the unit boundary, so its
not really a unit test.

> Its just that part of TDD is 'refactoring' where we look at the current
> design and improve things.  In this case, we saw that the single class
[quoted text clipped - 3 lines]
> them is still covered by tests for the original class - in fact we don't
> touch those tests - they create a safety net for our refactorings.

And doing so is a great way to perform refactoring! Whether or not
you refactor your tests after that is a decision that must be
made, and if I'm to be honest, I probably wouldn't bother.

> So, the choice we made was to separate the logic into discrete classes,
> but we could have left them as one class - do you really think this
> means the previous unit test is now an integration test?

Strictly, yes. Otherwise it becomes very difficult to make a
distinction between a unit test and an integration test.

Tim
iamfractal@hotmail.com - 15 Dec 2005 09:58 GMT
A very minor and more-or-less OT-point.

"In TDD we write a test, write the code, refactor. "

I'm a morning person. So I'm most productive in the morning. By the
time 4pm swings around, I reach a creative low-ebb, and I just want to
do something mechanical and unchallenging.

So I tend to write all my code before mid-afternoon, and only then
start writing the test classes for the morning's output.

So I'm not a TDDer by definition, but pragmatism doesn't stop me aiming
for its ideals.

As you were ...

.ed

--
www.EdmundKirwan.com - Home of The Fractal Class Composition.
Andrew McDonagh - 15 Dec 2005 11:02 GMT
> A very minor and more-or-less OT-point.
>
[quoted text clipped - 16 lines]
> --
> www.EdmundKirwan.com - Home of The Fractal Class Composition.

:) thats most definitely NOT TDD, its more akin to normal unit testing.

The times within the TDD cycle are around....

Writing the test - around 2- 3 minutes.
Write the code to make the test pass - around 1 - 2 minutes.
Refactoring - around 2 -3 minutes.

So in total the cycle take somewhere around 5 - 8 minutes.

These times are examples, but quite normal.  If you find you are
spending more than 10 minutes within each step of the cycle, then its an
indication of trying to test or implement or refactor too big a chunk,
or the code base hasn't been refactored enough.

HTH

Andrew


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.