如何使用 Intellitest 测试浮点输出?

How do I use Intellitest to test floating point output?

我对 VS 2015 中的 Intellitest(以及一般的单元测试)相当陌生,我正在尝试使用它来测试一种在英寸和毫米之间进行转换的简单方法。

我了解 Intellitest 在浮点测试方面存在局限性。我该如何解决这些问题,最好不要完全脱离框架?我在其余代码中成功地使用了它,所以我想找到一个尽可能匹配相同方法的解决方法。

我在 class 上有两个属性:

public double CutLengthInInches
{
    get;
    set;
}

public double CutLengthInMM
{
    get
    {
        return CutLengthInInches * 25.4;
    }
    set
    {
        CutLengthInInches = value / 25.4;
    }
}

然后我使用 Intellitest 创建一个存根,我填写如下:

[PexMethod]
public void CutLengthInMMSet([PexAssumeUnderTest]CutPiece target, double value)
{
    target.CutLengthInMM = value;
    PexAssert.AreEqual(value, target.CutLengthInMM);
    PexAssert.AreEqual(value, target.CutLengthInInches * 25.4);
}

当我 运行 这样做时,Intellitest 会报错:

The following operation was involved in a branch condition:

floating point equality

This operation causes testability problems, and inputs cannot be generated to cover the code following the call.

它指向的行是第一个 AreEqual() 调用。最简洁的解决方法是什么?

您的断言是在对浮点值进行精确比较。无论您是否使用 IntelliTest,都应避免此类比较。应用程序依赖精确的浮点比较是不安全的;四舍五入的细微变化可能会改变此类比较的结果,从而导致意外行为(例如,测试用例失败!)。

相反,应在与计算的预期精度相关的某个公差范围内进行浮点数相等性测试(即比较值是否 "equal enough")。

例如如果您使用 double.Epsilon 作为您的公差,请像这样更新比较:(Math.Abs(value - target.CutLengthInMM) < double.Epsilon).

现在,开始使用 IntelliTest: 当 IntelliTest 观察到执行此类精确比较的代码时,它会用可测试性警告标记它们。 继续上述公差值,更新您的断言如下:

PexAssert.IsTrue(Math.Abs(value - target.CutLengthInMM) < double.Epsilon);

您将看到一条警告,指出对 Math.Abs 的调用未被检测。没关系(因为我们对测试该方法不感兴趣)。在确保您已解决任何其他此类问题后,您可以 select 警告并抑制它(通过单击探索结果 window 工具栏上的抑制按钮)。