【问题标题】:How do you write tests for code that requires duplicating the code under test?您如何为需要复制被测代码的代码编写测试?
【发布时间】:2009-06-01 17:29:30
【问题描述】:

我正在努力将尽可能多的逻辑从自定义控件中移出,以便对其进行单元测试以减少手动测试的负担。我遇到了被测方法产生复杂结果的情况;编写一个计算结果的测试用例将涉及将本质上是被测代码的内容写入测试本身。

例如,我有一个 GeometryGenerator 类,它根据类的属性创建 WPF 几何图形。在一种配置中,会生成一个由ArcSegment 组成的PathGeometry。我可以根据测试参数计算弧的属性应该是什么,但这个计算与我试图测试的代码相同。这似乎会使测试无效;如果计算中有错误,则测试中也会有错误,如果计算方法发生变化,则可能必须在测试中进行更改。

遇到这种情况我该怎么办?我想出的唯一方法是手动计算我的测试用例的结果并将这些值硬编码到测试中。这是一种可以接受的方法吗(如果我在实现之前编写测试,我会这样做)?

【问题讨论】:

    标签: unit-testing


    【解决方案1】:

    我想出的唯一方法是手动计算我的测试用例的结果并将这些值硬编码到测试中。这是一种可接受的方法吗(如果我在实施之前编写测试,我会做的事情)?

    是的,这是典型的。出于单元测试的目的,您必须假设您用来计算结果的公式 是正确的。这是您正在测试的软件实现。

    您预先计算了一些手动计算的结果,以确保您没有使用被测代码来生成测试数据(单元测试中的一个非常糟糕的罪过)。只需确保记录测试用例,以便了解预期值代表什么以及它们来自何处。

    【讨论】:

      【解决方案2】:

      手工计算和硬编码在生产代码中不好,但对良好的单元测试至关重要。

      您通常希望为代码的每个“状态”编写一个测试。例如,我经常使用正输入、负输入和零输入编写测试,以确保代码按预期工作。

      【讨论】:

        【解决方案3】:

        通常,我会创建一个可以自行记录但硬编码的幻数,例如

        const int expectedResult = 2*4/someConstant; // 也许是评论。

        测试的读者可以推断出这些值是什么,或者您可以根据需要添加额外的 cmets。

        【讨论】:

          【解决方案4】:

          “单元测试”实际上应该只是测试单个单元。因此,理想情况下,您将为GeometryGenerator 进行单独的单元测试,为您的PathGeometry 类进行另一个单元测试,为您的ArcSegment 进行第三个单元测试,等等。

          通过分别测试每个单元,您可以对使用给定输入集调用给定操作时它们的行为方式获得某种信心(当ArcSegment 中的字段时GeometryGenerator 的行为方式)设置为 1,与将同一字段设置为 0 时的行为方式等)。

          如果您的单元测试开始看起来像是在复制现有代码来测试某个功能,那么恐怕您在进行单元测试时出错了,并且有一个更简单、更有效的解决方案可供您使用。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-02-24
            • 2019-08-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多