2011-01-24 56 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)

的地方肯定会有动作之间的延迟解决了这个。问题已修复。

相关问题