单元测试中断言的最佳实践

Posted

技术标签:

【中文标题】单元测试中断言的最佳实践【英文标题】:Best practices for assertions in Unit Testing 【发布时间】:2012-01-05 12:39:59 【问题描述】:

我正在尝试测试一个应用程序,该应用程序将三个参数作为输入(A 面、B 面、C 面)并计算三角形是等腰(两条边相等)、不等边(没有一条边相等)或等边(所有边相等)。

以下是我正在进行的单元测试的一些代码。在这种情况下,我正在测试应用程序是否告诉用户三角形是等腰的,我的问题是在这种情况下,我应该在 Assert 之后拥有什么? AreNotSame 适用于 scalene,AreSame 适用于等边,但这里有什么用?提前致谢。

    public void isIsoscelesTest()
    
        Triangle target = new Triangle(5.0, 5.0, 2.0); // TODO: Initialize to an appropriate value
        bool expected = true; // TODO: Initialize to an appropriate value
        bool actual;
        actual = target.isIsosceles();
        Assert.AreNotSame(expected, actual);
    

// 来自应用程序...

    public bool isIsosceles() 
      if(uniqueSides()==2)
        return true;
      return false;
    

【问题讨论】:

您使用的是哪个单元测试框架?根据所使用的框架,可能会有不同的方法。 我正在使用 MSTest (Visual Studio) 【参考方案1】:

理想情况下,您应该为每个测试用例创建一个测试,因此在您的示例中,我可能会有

[Test]
public void isIsoscelesTest()     
 
    var triangle = new Triangle(5.0, 5.0, 2.0); 
    Assert.That(triangle.isIsoceles(), Is.True);
    Assert.That(triangle.isEquilateral(), Is.False);
    Assert.That(triangle.isScalene(), Is.False);

还有

[Test]
public void isScaleneTest()     
 
    var triangle = new Triangle(3.9, 5.0, 2.0); 
    Assert.That(triangle.isIsoceles(), Is.False);
    Assert.That(triangle.isEquilateral(), Is.False);
    Assert.That(triangle.isScalene(), Is.True);

[Test]
public void isEquilateralTest()     
 
    var triangle = new Triangle(3.9, 3.9, 3.9); 
    Assert.That(triangle.isIsoceles(), Is.False);
    Assert.That(triangle.isEquilateral(), Is.True);
    Assert.That(triangle.isScalene(), Is.False);

我个人会在每个测试中断言它是一个特定类型,而不是其他两种类型,但是您也可以将它们分成单独的测试用例(然后它会变得冗长)。

在上面的示例中,我们有一些(几乎)重复的代码,如果需要,可以将其分解为辅助方法。此外,我们只测试三个单独的变量组合(边长)。但是,如果您在其中放入任何其他值怎么办?好的,我们无法测试所有内容,但它可以让您大致了解带有数值的单元测试的缺点。

最后,请注意 == 运算符在使用双精度或浮点精度时并不总是产生 true。例如,试试这个代码:

[Test]
public void DoublePrecisionRoundingTest()

   double aValue = 1.2345678;
   Assert.That(aValue + double.Epsilon, Is.EqualTo(aValue)); // passes! Should fail

这样做的原因是,在双精度中,舍入误差会导致一些数值运算被湮没。作为一种解决方法(这会影响您的三角形代码),您应该始终使用双精度或浮点变量测试“足够接近”。

例如而不是在您的 Triangle.uniqueSides 方法中:

if (aDouble == otherDouble) 

建议(但并非总是必要)使用它

if(Math.Abs(aDouble - otherDouble) < EPSILON)

其中 EPSILON 是一个非常小的值。

最好的问候,

【讨论】:

非常感谢!但是,Visual Basic (2010) 无法识别“那个”(Assert.That),这很奇怪。 没问题,很高兴为您提供帮助。回复:Assert.That 不在 VB 中,这很奇怪吗?您是否必须在 VB 和 C# 中执行相同的代码?因为这个问题看起来像一个 C# 问题。最好的问候, 对不起,代码是 C#。我的意思是 Visual Studio(不是 Visual Basic)。但是,当我运行测试时,编译器会抱怨“那个”(不包含“那个”的定义)。 @JasonCraig 哦,对了!抱歉,您使用的是 MSTest,而不是 NUnit。我的代码假设您使用 NUnit 作为测试框架。是的,您必须使用 Assert.AreSame / Assert.IsTrue 语法而不是 Assert.That(x, Is.EqualTo(y))。 好吧,我明白了。再次感谢!

以上是关于单元测试中断言的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

是否有设置 golang 单元测试参数的最佳实践?

MongoDB / Mongoose 单元测试 - 最佳实践? [关闭]

使用 Paypal REST SDK 最佳实践进行单元/模拟测试

类型断言的最佳实践

单元测试最佳实践:如何最大程度地利用测试自动化

Sencha Touch 单元测试最佳实践?