2011-01-30 40 views
1

。我在合同,pex和quickgraph之間存在着令人困惑的相互作用,並且非常感激來自知識更豐富的人的建議。我已經把它歸結爲一個重複的案例,其中註釋掉一個合約使得虛假的消極消失,但是我一直無法用調試器在允許的時間內對它進行診斷,因爲主題代碼(quickgraph)在屬性中有副作用 - 這意味着調試器在顯示屬性值時執行副作用,干擾執行的實際順序。每個人都有Pex,Contracts和QuickGraph的假陰性單元測試

首先有一點背景,然後是具體情況,然後指向一個項目下載並嘗試,如果你傾向於挖掘!

我安裝的Pex &痣

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

和CodeContracts用於.NET 4.0

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

我下載了,通過的NuGet,最近QuickGraph的版本,這是全部建成對於.NET 3.5。我將它修剪到了我需要的最小值,進入了Project Properties for all,從.NET 3.5客戶端配置文件全部更新到.NET 4.0,修復了一個源代碼重大更改(這是微不足道的,非常非常不可能與我的任何連接問題)。然後,我轉到每個項目頁面上的代碼合同選項卡,並啓用所有靜態和動態選項。

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

該項目有192次單元測試,其中不乏PEX-產生的(很漂亮!)。要運行測試,從

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

得到我的項目的zip文件請確保您有Pex的&痣和合同從上面的鏈接。打開解決方案,重新構建所有內容,然後在解決方案級別,「在解決方案中運行所有測試」(control-R,A)。一切都會過去。然後轉到IImplicitUndirectedGraphContracts.cs的第49行,並在大評論(由我插入)下取消合同註釋。一個測試,Prim12240WithDelegate將失敗。

該測試將執行一個圖構造函數,該函數通過在屬性獲取器中爲Edges和EdgeCount調用用戶提供的委託來即時創建邊。可愛。但是IImplicitUndirecteGraphContracts.cs的第49行的合同出了問題。

這是一個錯誤的否定,因爲如果我評論這個合同,測試通過。在試圖在調試器中遵循這一點時,它與在屬性獲取器中創建邊的時間有關。然而,我還沒有弄清楚這一點,因爲調試器會調用這些getter,主題代碼會調用它們,合同代碼會調用它們,或許是靜態的,也可能是動態的,我只是簡單地迷失了試圖遵循它,並且認爲我'd將這個問題帶給瞭解合同執行細節優於我的人。

這裏是違規合同;評論它使得單元測試成功:

[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

Pex在.NET 4.0運行時有處理LINQ表達式的問題。從first answer on this MSDN forum post for more details

用於.NET 2.0/3.5我們的支持LINQ的作品,但我們似乎有一個 迴歸的.NET4.0。如果您運行的是4.0,這就可以解釋爲什麼 Pex無法生成Interresting測試用例 - 我們沒有正確測試Linq 。

爲什麼Pex無論如何與Linq糾纏在一起:簡而言之,Linq使用 DynamicMethod來生成代碼。動態方法方法不是 當它們被分析時報告給分析器。由於我們的配置文件 無法在DynamicMethod中注入回調,Pex無法跟蹤通過Linq查詢的 數據流。我們有一個解決方法,攔截Linq to Object編譯器的內部結構,並強制它使用 Reflection.Emit。

這可能會使其忽略您評估期間評論過的合同,從而導致錯誤的否定。