2011-01-24 101 views
8

在發佈模式與調試模式下運行時,我們有一些單元測試失敗。如果我在釋放模式下附加調試器,則測試通過。有太多的代碼可以在這裏發佈,所以我只是在調試發佈模式問題時尋找最佳實踐。我已檢查:在發佈模式與調試模式下代碼的行爲有所不同

解決方案:在這種情況下,它是因爲我比較浮點變量是否相等。我無法改變的花車爲十進制沒有大規模的重構,所以我增加了一個擴展方法:

可能導致您看到的行爲
public static class FloatExtension 
{ 
    public static bool AlmostEquals(this float f1, float f2, float precision) 
    { 
     return (Math.Abs(f1 - f2) <= precision); 
    } 

    public static bool AlmostEquals(this float f1, float f2) 
    { 
     return AlmostEquals(f1, f2, .00001f); 
    } 

    public static bool AlmostEquals(this float? f1, float? f2) 
    { 
     if (f1.HasValue && f2.HasValue) 
     { 
      return AlmostEquals(f1.Value, f2.Value); 
     } 
     else if (f1 == null && f2 == null) 
     { 
      return true; 
     } 
     return false; 
    } 
} 
+1

幾個問題。 1.你給這個問題帶來了些什麼樣的失誤? 2.你檢查了條件方法嗎? – 2011-01-24 20:59:39

+0

主要問題是Equals方法返回false。但是,如果我分別採取每一個陳述,他們都會返回true。如果我嘗試附加一個調試器,問題就會消失。 – 2011-01-24 21:02:07

+0

是否與浮點相關(數據類型double等)? – stefan 2011-01-24 21:04:00

回答

8

的一件事是導致race condition錯誤。附加一個調試器可以改變代碼的時間,使競爭條件不再被觸發。

要解決此問題,只要您有多個線程訪問數據,請適當使用同步。


我在ISEQUAL方法相比一些浮點值。

這聽起來像一個非常糟糕的主意。你不應該比較浮點數是否相等,因爲浮點數計算不是100%精確的,你可以得到表示和舍入錯誤。比較一下它們是否足夠靠近在一起。對於涉及金錢的計算,您可能需要使用decimal類型。

0

正如馬克所說,這通常是與時間有關的問題的結果,通常是競態條件或同步問題。

處理這類問題的一種常見方法是在受影響的區域使用「打印」語句來向您顯示正在發生的事情。如果打印語句(Console.WriteLine,Response.Write,日誌記錄或其他)使問題消失,請將值存儲在全局變量中,並在問題出現後打印全局變量。

發生在我身上的最近一次是在從串口讀取的代碼中。調試活動引起的時間變化足以影響串行端口的字節被緩衝的方式,這改變了緩衝區被解析的方式。由於打印語句改變了時間,我必須將數據存儲到稍後輸出。

2

問題你應該問自己 -

  1. 是我的代碼線程?時間差異會影響輸出
  2. 是否有人用帶副作用的表達式調用Debug.Assert()?
  3. 什麼對象實現IDisposable(),並做一些這樣做,以改變狀態?
  4. 你是P /調用到非託管代碼?

3號在這種情況下很可能是壞男孩。垃圾收集在調試和發佈時可能會有很大的不同,您可能會發現,當垃圾收集對象影響稍後單元測試的結果時。

和FYI,如果您使用的是NUnit和TestDriven.NET--兩個運行測試不同的訂單。

2

這通常是這種情況,因爲調試版本在默認情況下並未優化,即使啓用它,調試時的行爲也非常不同。您可以在Properties-> Build選項卡上禁用所有組件的項目設置中的「優化代碼」。

當然還有其他可能導致差異的變化,就像你提到的條件方法一樣。這些我很少成爲問題的原因,對我來說,它幾乎總是優化器。

優化器的經典問題包括獲取「內聯」的方法,以使它們無法顯示在調用堆棧上。這在使用System.Diagnostics.StackFrame類來確定當前執行點時會導致問題。同樣,這將影響MethodBase.GetCurrentMethod或依賴執行方法的其他函數/行爲的結果。

然後當然有許多事情我看到了優化器的做法,我根本無法解釋。其中一個例子在文章'HashDerivedBytes - replacing Rfc2898DeriveBytes, but why?'中被記錄和討論,但我從未解決過這個謎。我只知道當用於生成一系列派生字節時,優化器恰好平分了Rfc2898DeriveBytes。奇怪的是,只有當生成的字節不能被所使用的哈希算法的大小(20)均勻分割並且僅在前20個字節後產生不正確的結果時纔會中斷。

事實上,對代碼產生負面影響的優化對編譯器來說不是一件新事物。大多數老派的C++開發人員會馬上告訴你,然後就像我一樣,進入一個很長的故事,講述他們如何解決它;)

0

只是爲了增加我的兩分錢,最近發現,我在一個SQL過程中進行了日期比較,測試稱爲。這些日期都是在測試過程之前自動生成的,並且值被插入到數據庫中,所以偶爾它們完全相同(使用RunTests時)會導致表連接返回一個空值。不是我期待的。顯然,在調試模式下,由於我正在緩慢地進行調試,所以自動生成時間會有所不同,這意味着我從來沒有碰到過錯誤。我通過插入

Threading.Thread.Sleep(520)

的地方肯定會有動作之間的延遲解決了這個。問題已修復。

相關問題