使用Pex,Contracts和QuickGraph进行假阴性单元测试

时间:2011-01-30 20:05:31

标签: unit-testing c#-4.0 pex contracts quickgraph

大家。我在合同,pex和quickgraph之间有一种令人困惑的互动,并且非常感谢更有见识的人的建议。我把它归结为一个责备案例,其中评论一个合同使得假负面消失,但我无法在允许的时间内使用调试器对其进行诊断,因为主题代码(quickgraph)在属性中有副作用 - getters,意味着调试器在显示属性的值时执行副作用,干扰实际的执行顺序。

首先是一个小背景,然后是具体细节,然后是指向要下载和试用的项目的指针,如果你倾向于深入挖掘!

我安装了Pex&鼹鼠

http://research.microsoft.com/en-us/projects/pex/downloads.aspx

和.NET 4.0的CodeContracts

http://research.microsoft.com/en-us/projects/contracts/

我通过nuget下载了最新版本的QuickGraph,它全部是为.NET 3.5构建的。我把它修剪到我需要的最小值,进入所有项目属性,从.NET 3.5 Client Profile更新到.NET 4.0,修复了一个来源的破坏变化(这很简单,非常,非常不可能与我的任何连接问题)。然后,我转到每个项目页面上的Code Contracts选项卡,并启用所有静态和动态选项。

http://quickgraph.codeplex.com/releases/view/55262

该项目有192个单元测试,其中许多是Pex生成的(非常好!)。要运行测试,请从

获取我的项目zip文件

http://dl.dropbox.com/u/1997638/QuickGraph.zip

确保你有Pex&来自上述链接的摩尔和合同。打开解决方案,重建所有内容,然后在解决方案级别“运行所有测试解决方案”(control-R,A)。一切都会过去的。然后转到IImplicitUndirectedGraphContracts.cs的第49行,并在大评论(由我插入)下取消注释合同。一次测试,Prim12240WithDelegate将失败。

该测试练习一个图形构造函数,通过在Edges和EdgeCount的property-getters中调用用户提供的委托来即时构建边缘。可爱。但是IImplicitUndirecteGraphContracts.cs第49行的合同出了问题。

这是假阴性,因为如果我注释掉这个合同,测试就会通过。在调试器中试图遵循这一点时,它与在属性getter中创建边缘的时间有关。然而,我无法解开这个问题,因为调试器会调用这些getter,主题代码会调用它们,合同代码会调用它们,也许是静态的,也许是动态的,我只是很想丢失试图跟随它,并且认为我将问题提交给那些比我更了解合同执行细节的人。

这是违规合同;评论它使单元测试成功:

[Pure]
  IEnumerable<TEdge> IImplicitUndirectedGraph<TVertex, TEdge>.AdjacentEdges(TVertex v)
  {
    IImplicitUndirectedGraph<TVertex, TEdge> ithis = this;
    Contract.Requires(v != null);
    Contract.Requires(ithis.ContainsVertex(v));
    Contract.Ensures(Contract.Result<IEnumerable<TEdge>>() != null);
~~~~~~> Contract.Ensures(
      Enumerable.All(
        Contract.Result<IEnumerable<TEdge>>(),
        edge => 
          edge != null && 
          ithis.ContainsEdge(edge.Source, edge.Target) && 
          (edge.Source.Equals(v) || edge.Target.Equals(v))
        )
      );
    return default(IEnumerable<TEdge>);
  }

1 个答案:

答案 0 :(得分:1)

Pex在.NET 4.0运行时中处理LINQ表达式时遇到问题。来自first answer on this MSDN forum post for more details

  

我们的Linq支持适用于.NET 2.0 / 3.5,但我们似乎有一个   .NET4.0的回归。如果您运行4.0,那将解释原因   Pex无法生成有趣的测试用例 - 我们不会使用Linq   正确。

     

为什么Pex仍然与Linq斗争:简而言之,Linq使用   DynamicMethod用于生成代码。 DynamicMethod方法不是   在他们被jitted时向分析者报告。因为我们的探查器   无法在DynamicMethod中注入回调,Pex无法跟踪   数据流通过Linq查询。我们有一个拦截的解决方法   Linq to Object编译器的内部并强制它使用   反思。改为。

这可能会使其忽略您在评估期间注释掉的合同,从而导致误报。