¿ªÔÆÌåÓý

ctrl + shift + ? for shortcuts
© 2025 Groups.io

Re: [TDD] Tests as stories


Steve Hayes
 

I think it's important for interfaces to capture the semantics of the
design (and hopefully the metaphor/problem domain as fully as possible),
because this is something that the programmers need to know.

The test

testIdentityExchange() {
Exchange bank= new Exchange();
Note result= bank.convert();
assertEquals(five, result);
}


is unsatisfying to me because the interface doesn't express everything
that the programmers need to know. A more complete expression would be:

testIdentityExchange() {
Exchange bank= new Exchange();
Note result= bank.convertToUsd();
assertEquals(five, result);
}

and I'd be completely ok with this as an interim test. When I needed
conversion to an arbitrary currency I'd discover I needed a different
protocol and I might very well decide to discard convertToUsd(), or I
might keep it as a convenience. But "convert()" doesn't tell the whole
story.

I also concur that parameters that make sense for the completeness of
the interface should be passed. If you notice during the implementation
that the parameter isn't used, that's a good opportunity to go back and
ponder the interface some more - perhaps you haven't captured the
essence of the interaction, or perhaps your understanding of the problem
domain is incomplete. The friction between the protocol and the
implementation is trying to communicate something to you - it's up to
you to understand what.

Steve Hayes

On Sat, 2002-02-16 at 06:21, Kent Beck wrote: There have been several
complaints that the tests as written in the examples
aren't minimal. There are parameters there that aren't used, methods
with a
null implementation, and so on.

When I write my first test for exchanging one currency for another, I
think
I should write:

testIdentityExchange() {
Money five= new Note(5, "USD");
Exchange bank= new Exchange();
Note result= bank.convert(five, "USD");
assertEquals(five, result);
}

Why do I write this? Because when I am writing the test, I am imagining
the
perfect API for this operation. What should the outside of this
operation
look like, in a perfect world? I know I will need a source Money and a
target currency.

Some of you have made suggestions like you could start with the
following:

testIdentityExchange() {
Exchange bank= new Exchange();
Note result= bank.convert();
assertEquals(five, result);
}

The rule being, any data you know you won't need for the implementation
you
don't bother to pass. I think two mistakes have been made:
* You've lost the opportunity to think about what the outside of the
operation should look like.
* You've already started thinking about the implementation, and let it
drive the API.

I absolute agree with criticisms that when I extract methods in the
implementation, they should have no more parameters than are actually
used.
The interplay of tests as dreams of a convenient and effective world and
implementations as reality, though, is different than the interplay of
pieces of the implementation.

It could easily be that this is too subtle a point, or that I am
altogether
wrong. Goodness knows I have learned tons about my TDD technique in the
last
month. However, I am not giving up on this without a fight. Writing
tests
like the second version above is profoundly unsatisfying to me, and I
tend
to trust that.

So, is the rule the one, the other, or something else entirely?

Kent



Yahoo! Groups Sponsor
ADVERTISEMENT


To unsubscribe from this group, send an email to:
testdrivendevelopment-unsubscribe@...



Your use of Yahoo! Groups is subject to the Yahoo! Terms of Service.

--
Steve Hayes
steve@...
Home: +61-3-9489 0860
Mobile: +61-403-902-431

Join [email protected] to automatically receive all group messages.