大家。我在合同,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>);
}
答案 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编译器的内部并强制它使用 反思。改为。
这可能会使其忽略您在评估期间注释掉的合同,从而导致误报。