单元测试中的不确定性

时间:2010-02-23 01:38:31

标签: c# unit-testing

似乎在许多单元测试中,参数化测试的值要么自己烘焙到测试中,要么以预定的方式声明。

例如,这是从nUnit的单元测试(EqualsFixture.cs)中进行的测试:

[Test]
public void Int() 
{
    int val = 1;
    int expected = val;
    int actual = val;

    Assert.IsTrue(expected == actual);
    Assert.AreEqual(expected, actual);
}

这具有确定性的优点;如果您运行一次测试,并且它失败,它将继续失败,直到代码被修复。但是,您最终只会测试一组有限的值。

但是,我不禁觉得这是浪费;完全相同的测试可能在项目的整个生命周期中使用完全相同的参数运行数百次甚至数千次。

如何尽可能多地将所有单元测试的输入随机化,以便每次运行都能揭示新的内容?

在前面的例子中,或许是:

[Test]
public void Int() 
{
    Random rnd = new Random();
    int val = rnd.Next();
    int expected = val;
    int actual = val;
    Console.WriteLine("val is {0}", val);
    Assert.IsTrue(expected == actual);
    Assert.AreEqual(expected, actual);
}

(如果代码需要一个字符串,可能每次都可以使用已知对特定函数有效的随机字符串)

好处是你运行测试的次数越多,你知道它可以正确处理的更大的可能值集。

这有用吗?邪恶?这有缺点吗?我是否完全忽略了单元测试的重点?

感谢您的想法。

6 个答案:

答案 0 :(得分:7)

您希望您的单元测试可重复,以便除非代码更改,否则它们将始终以相同的方式运行。然后,如果代码更改并导致单元测试失败,则可以修复代码并且单元测试已达到其目的。此外,您知道在单元测试再次通过时代码[可能]已修复。

进行随机单元测试可能会发现异常错误,但这不是必需的。如果您知道代码是如何工作的(比较白盒和黑盒方法来测试),使用随机值不应该显示任何非常随机的单元测试。我不想被告知“多次运行测试,这个错误应该出现”。

答案 1 :(得分:4)

如果你正确地做了,你提出的建议很有意义。你并不一定总是只听取传统的智慧,即你的测试中决不会有非决定论。

真正重要的是每个测试必须始终使用相同的代码路径。这不是一回事。

您可以在单元测试中采用我称之为Constrained Non-Determinism的内容。这可以促使您采用更Specification-Oriented的方式编写测试。

答案 2 :(得分:3)

测试应该涵盖您的使用案例,不再需要。

查看PEX

答案 3 :(得分:2)

我遇到的一个大问题是,由于这是随机的,因此在测试运行200,2000,3000或更多次之前,它可能不会导致失败。如果在案件写完后6007个月或几年内尝试失败,那基本上就意味着你有几个月或几年的错误而且从来不知道。

相反,我认为了解你的角落案例并特别测试它们会更有用。换句话说,想想哪些数据可能会破坏您的代码并对其进行测试。

答案 4 :(得分:0)

您是在测试Random还是相等运算符?

在我看来,您会选择典型值加边界条件,或者强制整个整数集。简单地选择随机整数对这两种方法都没有帮助。

为了回答你的最后一个问题,单元测试的重点是什么,我的感觉是:证明可重复结果的价值超过了编写测试的成本。

答案 5 :(得分:0)

如果您的申请是非确定性的,那么您就是在浪费时间进行测试,除非它是一个非常小的应用程序。