我对TDD
(测试驱动开发)有一些疑问:一个方法已经有了一些测试,并且需求发生了变化,我应该怎么做?
假设有一个计程器,其$6
的初始费用为2km
,每增加一公里则为$0.8
,每等待一分钟为$0.25
。我写了几个这样的测试:
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);
}
}
然后需求发生变化:计价器应该对价格进行四舍五入,因此3km
应该是$7
,而对于8km
,它应该是$9
。
我现在该怎么办?我有两个选择:
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);
}
}
似乎工作正常如果只有少数测试,但如果规则足够复杂,可能需要更改几十个测试。
我也想在四舍五入之前知道真正的票价,如果我只知道四舍五入的价格,我觉得不安全。
所以我正在考虑选项2
internalPrice
和finalPrice
internalPrice
是四舍五入前的价格,finalPrice
是internalPrice
的四舍五入。
首先,我需要将calculate
方法重命名为internalPrice
,并且测试的类名称将更改为TaximeterInternalPriceTest
,但测试中的所有数据都不会更改:< / p>
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);
}
}
然后为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);
}
}
但问题是internalPrice
实际上只在finalPrice
中使用并且应该是私有的,但如果我想测试它,则它是非私有的:
double internalPrice(int km, int waitingMinutes)
public double finalPrice(int km, int waitingMinutes)
我现在很困惑,不确定哪个选项更好,或者有更好的选择。有什么帮助吗?
答案 0 :(得分:2)
你可以破坏对象。例如:
每个距离对象的价格可以单独测试,而不用担心等待时间或最终价格的逻辑变化。 每个等待对象的价格可以单独测试,而不用担心距离或最终价格的逻辑变化。 可以使用存根来测试计程器,以便可以在不影响其单元测试的情况下对规则进行更改。