如果方法的要求(已经进行了大量测试)发生变化,我该怎么办?

时间:2015-11-06 11:37:05

标签: testing tdd

我对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

我现在该怎么办?我有两个选择:

1。修改所有受影响的现有测试,不涉及新方法

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

2。添加internalPricefinalPrice

的概念

internalPrice是四舍五入前的价格,finalPriceinternalPrice的四舍五入。

首先,我需要将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)

我现在很困惑,不确定哪个选项更好,或者有更好的选择。有什么帮助吗?

1 个答案:

答案 0 :(得分:2)

你可以破坏对象。例如:

  • 一个需要一段距离的对象,并返回给定距离的价格。
  • 一个需要等待时间并返回等待价格的对象。
  • 一个是计程器,它采用每个规则并将它们组合起来并返回最终价格。

每个距离对象的价格可以单独测试,而不用担心等待时间或最终价格的逻辑变化。 每个等待对象的价格可以单独测试,而不用担心距离或最终价格的逻辑变化。 可以使用存根来测试计程器,以便可以在不影响其单元测试的情况下对规则进行更改。