每个人。我在合同、pex 和 quickgraph 之间有一个令人困惑的交互,非常感谢知识渊博的人提供的建议。我把它归结为一个复制案例,其中注释掉一个合同会使假阴性消失,但我无法在允许的时间内用调试器诊断它,因为主题代码(快速图)对属性有副作用- getters,意味着调试器在显示属性值时执行副作用,干扰实际执行顺序。
首先是一点背景,然后是细节,然后是一个可以下载和试用的项目的指针,如果您愿意深入研究的话!
我安装了 Pex & Moles
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 客户端配置文件更新到 .NET 4.0,修复了一个源中断更改(这是微不足道的,非常非常不可能与我的问题)。然后我转到每个项目页面上的 Code Contracts 选项卡并启用所有静态和动态选项。
http://quickgraph.codeplex.com/releases/view/55262
该项目有 192 个单元测试,其中许多是 Pex 生成的(非常好!)。要运行测试,请从
http://dl.dropbox.com/u/1997638/QuickGraph.zip
确保您有来自上述链接的 Pex & Moles 和 Contracts。打开解决方案,重建所有内容,然后在解决方案级别,“在解决方案中运行所有测试”(control-R,A)。一切都会过去的。然后转到 IImplicitUndirectedGraphContracts.cs 的第 49 行并取消注释大注释下的合同(由我插入)。一项测试 Prim12240WithDelegate 将失败。
该测试通过在 Edges 和 EdgeCount 的属性获取器中调用用户提供的委托来运行图形构造函数。可爱的。但是 IImplicitUndirecteGraphContracts.cs 第 49 行的 Contract 出了点问题。
这是一个假阴性,因为如果我注释掉这个合同,测试就通过了。在调试器中尝试遵循这一点时,它与在属性 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>);
}