Pex(测试生成)真的很有用吗?

时间:2010-04-24 13:47:34

标签: .net unit-testing code-generation pex

是的,可以为“Sum”或“Divide”等函数生成边界值测试。 Pex是一个很好的工具。

但更多时候我们会针对商业行为进行测试。让我们考虑经典Beck的tdd书中的例子:

[Test]
public void ShouldRoundOnCreation()
{
  Money money = new Money(20.678);
  Assert.AreEqual(20.68,money.Amount);
  Assert.AreEqual(2068,money.Cents);
}

可以生成此测试吗?没有:)我项目中95%的测试检查业务逻辑,无法生成。

Pex(特别是与Moles配对)可以提供100%的代码覆盖率,但是测试套件的高代码覆盖率从未表明,该代码经过了充分测试 - 它只能让所有内容都经过测试。这非常危险。

所以,问题是 - Pex真的很有用吗?

2 个答案:

答案 0 :(得分:29)

我认为你应该使用Pex的方式是错误的:我们强烈建议用户在参数化单元测试中编写断言。

如果你写断言,Pex将尝试系统地使它们失效 - 这就是Pex的强大之处:你写断言的次数越多,它就越想为你找到bug。

如果您使用Pex获得高代码覆盖率测试套件而不编写断言,那么您只能获得所要求的内容:代码覆盖率和有保证的运行时异常。 Pex'only'试图覆盖分支(1断言= 1分支),如果没有分支覆盖(没有断言),它将不会产生有趣的测试用例。

通常,在参数化单元测试中编写断言更难写,因为......它们更通用。让我们从舍入行为开始:肯定有一个限制允许舍入发生,这应该自然地转换为参数化单元测试:

[PexMethod]
public void RoundInBounds(double value) 
{
    var money = new Money(value);
    // distance between value and amount should be at most 0.01/2
    Assert.AreEqual(value, money.Amount, 0.005);
}

还有许多模式可用于编写这些模式。例如,您的“Money”类可能是幂等的:如果您在Money实例中返回'Amount'的值,则会返回Amount。这优雅地转化为参数化单元测试:

[PexMethod]
public void RoundIsIdempotent(double value) 
{
     var first = new Money(value).Amount;
     var second = new Money(first).Amount;
     Assert.AreEqual(first, second, 0.0001);
}

另请注意,参数化单元测试绝对属于TDD世界。首先编写参数化单元测试,Pex将找到失败的bug,修复bug,Pex找到下一个失败的bug等等......

这是否使Pex成为有用的工具?你是法官。

答案 1 :(得分:3)

Pex中有一些有用的东西。

  1. 代码覆盖率。让我们把Pex搁置一下。通常,100%的代码覆盖率并不一定意味着您具有良好的代码覆盖率。它只意味着执行路径,但程序具有数据流,并且测试代码不同的附加输入,如果不是代码覆盖,则为您提供最佳的“测试覆盖率”。这是,我只是重申你的观点。 100%的代码覆盖率不一定是好的,但你可以肯定地说25%的代码覆盖率很差,因此代码覆盖率是如此有用。当你的代码覆盖率很低时,你肯定知道你的测试覆盖率很低。

    当您使用Pex获得100%的代码覆盖率时,它本身并不能帮助您获得更好的测试覆盖率,但它所做的是为生产代码提供一些测试,可用于调试器。实际上,作为会议的Pex演示显示了Pex用于此目的。程序员说,“哎呀,看看NHibernate中的这个方法。我想在调试器中单步执行它以查看它的作用,但是我如何通过正常的”业务入口点“调用该方法进入库?不知道库的任何内容,你不能。所以他运行了Pex,并且能够通过各种参数逐步完成代码。有趣,是的。有用,也许是这样,也许不是。

    < / LI>
  2. 除了自动创建的测试外,Pex还可用于参数化测试。创建数据驱动的单元测试要好得多。为什么要反复编写相同的代码,使用不同的参数。写一次,然后从数据源中提供参数。

  3. Pex也可用作简单的存根框架。这可能是创建模拟对象的最简单方法,使用新的lambda表达式,这比RhinoMocks等复杂框架更容易理解。使用Moles,您还可以存根不仅仅是接口,而是类中的具体非虚方法。

  4. 我也会过分关注“在业务逻辑上测试”一层。您可以轻松地进行行为驱动开发,而不是单元测试。在那里,你正在测试一个规范。如果这就是你所做的,那么你将如何测试没有商业价值的自定义数据结构等,但是整个应用程序中使用的是内部库。