1

みんな。私は契約、ペックス、クイックグラフの間で困惑する相互作用を持っており、より知識のある人からのアドバイスに非常に感謝しています。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>);
  }
4

1 に答える 1

1

Pex には、.NET 4.0 ランタイムでの LINQ 式の処理に関する問題があります。詳細については、この MSDN フォーラムの投稿の最初の回答から:

Linq サポートは .NET 2.0/3.5 で機能しますが、.NET4.0 ではリグレッションがあるようです。4.0 を実行している場合は、Pex が興味深いテスト ケースを生成できない理由を説明できます。Linq が正しく計測されていません。

とにかく Pex が Linq と格闘する理由: 一言で言えば、Linq は DynamicMethod を使用してコードを生成します。DynamicMethod メソッドは、jit されたときにプロファイラーに報告されません。プロファイラーは DynamicMethod にコールバックを挿入できないため、Pex は Linq クエリを介してデータ フローを追跡できません。Linq to Object コンパイラの内部をインターセプトし、代わりに Reflection.Emit を使用するように強制する回避策があります。

これにより、評価中にコメントアウトした契約が無視され、誤検知が発生する可能性がありました。

于 2011-07-24T21:08:18.617 に答える