I have some questions about the TDD
(test driven development): a method has already have some tests, and the requirement changes, what should I do?
Say there is a Taximeter, which has a init fare $6
for 2km
, and then $0.8
for each extra kilometer, and $0.25
for every waiting minute. I have writen several tests like this:
public class TaximeterTest {
@Test public void testInitFare() {
assertEquals(new Taximeter().calcuate(2), 6.0, 0.00001);
}
@Test public void test3km() {
assertEquals(new Taximeter().calcuate(3), 6.8, 0.00001);
}
@Test public void test8km() {
assertEquals(new Taximeter().calcuate(8), 9.2, 0.00001);
}
@Test public void test3kmWaiting1Minute() {
assertEquals(new Taximeter().calcuate(3, 1), 7.05, 0.00001);
}
@Test public void test8kmWaiting10Minutes() {
assertEquals(new Taximeter().calcuate(8, 10), 11.7, 0.00001);
}
}
Then the requirement changes: the Taximeter should round off the price, so the 3km
, it should be $7
, and for 8km
, it should be $9
.
What should I do now? I have 2 options:
1. Modify all affected existing tests
public class TaximeterTest {
@Test public void testInitFare() {
assertEquals(new Taximeter().calcuate(2), 6.0, 0.00001);
}
@Test public void test3km() {
assertEquals(new Taximeter().calcuate(3), 7.0 /*rounded*/, 0.00001);
}
@Test public void test8km() {
assertEquals(new Taximeter().calcuate(8), 9.0 /*rounded*/, 0.00001);
}
@Test public void test3kmWaiting1Minute() {
assertEquals(new Taximeter().calcuate(3, 1), 7.0 /*rounded*/, 0.00001);
}
@Test public void test8kmWaiting10Minutes() {
assertEquals(new Taximeter().calcuate(8, 10), 12.0 /*rounded*/, 0.00001);
}
}
Seems work OK if there are only a few tests, but if there rules are complex enough, maybe there dozens of tests need to be changed.
I also want to know the real fare beforing rounding, I don't feel safe if I only know the rounded price.
So I'm considering the option 2
2. add concepts of internalPrice
and finalPrice
The internalPrice
is the price before rounding, and the finalPrice
is rounded of internalPrice
.
First I need to rename the calculate
method to internalPrice
, and the class name of the test is changing to TaximeterinternalPriceTest
, but all the data in the tests are not changed:
public class TaximeterinternalPriceTest {
@Test public void testInitFare() {
assertEquals(new Taximeter().internalPrice(2), 6.0, 0.00001);
}
@Test public void test3km() {
assertEquals(new Taximeter().internalPrice(3), 6.8, 0.00001);
}
@Test public void test8km() {
assertEquals(new Taximeter().internalPrice(8), 9.2, 0.00001);
}
@Test public void test3kmWaiting1Minute() {
assertEquals(new Taximeter().internalPrice(3, 1), 7.05, 0.00001);
}
@Test public void test8kmWaiting10Minutes() {
assertEquals(new Taximeter().internalPrice(8, 10), 11.7, 0.00001);
}
}
Then create new tests for finalPrice
:
public class TaximeterFinalPriceTest {
@Test public void testInitFare() {
assertEquals(new Taximeter().finalPrice(2), 6.0, 0.00001);
}
@Test public void test3kmWaiting1Minute() {
assertEquals(new Taximeter().finalPrice(3, 1), 7.0 /*rounded*/, 0.00001);
}
@Test public void test8kmWaiting10Minutes() {
assertEquals(new Taximeter().finalPrice(8, 10), 12.0 /*rounded*/, 0.00001);
}
}
But the problem is the internalPrice
is actually only used in finalPrice
, but it should be non-private if I want to test it:
double internalPrice()
public double finalPrice()
I'm puzzled now and not sure which option is better, or there is even better options. Any help?
Aucun commentaire:
Enregistrer un commentaire