代码之家  ›  专栏  ›  技术社区  ›  devoured elysium

关于单元测试的几个问题

  •  1
  • devoured elysium  · 技术社区  · 14 年前

    假设我们首先设计一个堆栈类测试(TDD):

    public class Stack<T> {
        private T[] elements = new T[16];
        private int size = 0;
        ...
    }
    

    此堆栈使用大小为16的内部数组来存储其元素。在需要添加第17个元素之前,它可以正常工作。因为我可能需要第17个元素,所以我决定将该功能添加到我的堆栈中,所以我开始考虑我可以给测试起什么名字来添加该功能。那将是我的主题 第一个问题 .

    我首先选择了以下形式:

    Should_Be_Able_To_Correctly_Increase_Its_Inner_Array_Size()
    

    然后

    Should_Handle_More_Items_Than_The_Default_Internal_Array_Size()
    

    但经过一番思考,我得出了这样一个结论:也许像下面这样的事情更合适:

    Should_Double_Its_Size_Every_Time_Its_Full()
    

    在第一种情况下,我的推理必须这样做,我只是在说它做了什么,而不是什么时候。 在第二部分中,我说的是何时添加更多的项目,但我也说了我如何(在内部)实现它,这可能是不正确的。在我看来(我不确定自己是否正确),我的测试应该是我的SUT与外部可能的交互,而不是关于内部如何实现它。我说的对吗?

    在我看来,第三个选项是最好的,因为它清楚地说明了它的功能(大小增长——实际上是它的两倍大小),它的功能(当它满时),并且不将我与任何特定的实现联系在一起(我可能稍后会想将其更改为内部数组列表!).

    这让我 第二个问题 :假设我对在内部使用数组的堆栈类进行了所有单元测试,并且它运行良好,并且如预期的那样,如果以后我想重构数组并将其更改为arraylist或任何其他类型的数据结构,我的测试是否应保持完整?或者测试应该以任何方式反映这一点?我想不会,但我不确定。

    4 回复  |  直到 14 年前
        1
  •  3
  •   Bernard    14 年前

    在我看来(我不确定 正确),我的测试应该 我的SUT与 外观,而不是外观 内部实施。我说的对吗?

    你说得对。如果更改类的内部实现,则单元测试应该保持不变。如果您在外部公开任何新的东西,您应该创建新的单元测试来解释这些更改。

    请记住,在设计类时,您不希望公开指示如何实现类的任何内容。该类的公共成员指示如何与之交互,现在指示如何在幕后工作。

        2
  •  2
  •   Timo Westkämper    14 年前

    我不确定如何通过单元测试来测试内部列表或数组大小。您不能通过堆栈接口访问它。单元测试用于测试外部合同。如果要测试实现细节,请尝试其他方法。

    第二个问题的答案是“是”,如果是单元测试,测试仍然应该通过。

        3
  •  2
  •   Jeff Sternal    14 年前

    问问自己,你愿意为这门课付出什么。

    您或班级的消费者真的关心容量是加倍、增加一倍还是增加一千倍?如果是这样,您应该修改接口,以便它们可以指定用于增加容量的策略:

    public Stack<T>(CapacityGrowthStyle capacityGrowthStyle) { ... }
    

    如果没有,只需编写测试来记录容量,并将其保留在该位置(其中 X 以下是基础数据结构的限制):

    [Test]
    public void Can_Handle_X_Items() { ... }
    
    [Test]
    [ExpectedException(typeof(InvalidOperationException))]
    public void Cannot_Handle_More_Than_X_Items() { ... }
    

    我也会回答你的第二个问题:如果你的类的用户关心的话,你的测试应该只反映基础数据结构。

        4
  •  1
  •   Brian Stinar    14 年前

    我不确定你是否 应该 通过单元测试测试内部列表或数组大小,因为您不能通过堆栈接口访问它。实现堆栈的方法有很多种,有些好,有些坏,但是正如Bernard所说,这些都是内部实现。单元测试旨在测试面向外部的功能。