みんな。私は契約、ペックス、クイックグラフの間で困惑する相互作用を持っており、より知識のある人からのアドバイスに非常に感謝しています。1つの契約をコメントアウトするとフォールスネガティブがなくなるという再現ケースに要約しましたが、サブジェクトコード(クイックグラフ)のプロパティに副作用があるため、許可された時間内にデバッガーで診断できませんでした- gettersは、プロパティの値を表示するときにデバッガーが副作用を実行し、実際の実行順序を妨げることを意味します。
最初に少し背景を説明し、次に詳細を説明し、次にダウンロードして試してみるプロジェクトへのポインタを紹介します。
Pex&Molesをインストールしました
http://research.microsoft.com/en-us/projects/pex/downloads.aspx
およびCodeContractsfor.NET 4.0
http://research.microsoft.com/en-us/projects/contracts/
nugetを介して、すべて.NET3.5用に構築された最新バージョンのQuickGraphをダウンロードしました。私はそれを必要最小限に剪定し、すべてのプロジェクトプロパティに移動し、それらすべてを.NET3.5クライアントプロファイルから.NET4.0に更新し、1つのソースを壊す変更を修正しました(これは些細なことであり、私の接続がほとんどない可能性があります)問題)。次に、すべてのプロジェクトページの[コードコントラクト]タブに移動し、すべての静的および動的オプションを有効にしました。
http://quickgraph.codeplex.com/releases/view/55262
プロジェクトには192の単体テストがあり、その多くはPexで生成されています(非常に素晴らしいです!)。テストを実行するには、プロジェクトのzipファイルを次の場所から取得します。
http://dl.dropbox.com/u/1997638/QuickGraph.zip
上記のリンクからPex&MolesとContractsがあることを確認してください。ソリューションを開き、すべてを再構築してから、ソリューションレベルで、「ソリューションですべてのテストを実行」(control-R、A)を実行します。すべて合格します。次に、IImplicitUndirectedGraphContracts.csの49行目に移動し、大きなコメント(私が挿入)の下でコントラクトのコメントを解除します。1つのテスト、Prim12240WithDelegateは失敗します。
このテストでは、EdgesとEdgeCountのプロパティゲッターでユーザー指定のデリゲートを呼び出すことにより、オンザフライでエッジを構築するグラフコンストラクターを実行します。かわいい。しかし、IImplicitUndirecteGraphContracts.csの49行目のコントラクトに問題があります。
この契約をコメントアウトすると、テストに合格するため、これはフォールスネガティブです。デバッガーでこれを追跡しようとすると、プロパティゲッターでのエッジの作成のタイミングと関係があります。私はこれを解きほぐすことができませんでしたが、デバッガーがこれらのゲッターを呼び出し、サブジェクトコードがそれらを呼び出し、コントラクトコードがそれらを呼び出すため、おそらく静的に、おそらく動的に、私はそれに従うことを試みて迷子になり、私は思った契約執行の詳細を私よりよく理解している人に質問を投げかけます。
これが問題のある契約です。コメントアウトすると、単体テストが成功します。
[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>);
}