在Release模式和调试模式下运行时,我们有一些单元测试失败。如果我在发布模式下附加调试器,则测试通过。有太多的代码要在这里发布,所以我真的只是在寻找调试发布模式问题的最佳实践。我检查过:
解决方案:在这种情况下,这是因为我在比较浮点变量是否相等。在没有重大重构的情况下,我无法将浮点数更改为十进制数,因此我添加了一个扩展方法:
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;
}
}
答案 0 :(得分:8)
可能导致您看到的行为的一件事是导致race condition的错误。附加调试器可以更改代码的时间,以便不再触发竞争条件。
要修复它,只要有多个线程访问数据,就适当使用同步。
我正在比较IsEqual方法中的一些浮点值。
这听起来像个坏主意。您不应该将浮点数比较为相等,因为浮点计算不是100%精确,您可以获得表示和舍入错误。比较看它们是否足够接近。对于涉及金钱的计算,您可能希望改为使用decimal
类型。
答案 1 :(得分:3)
由于它似乎是浮点相关的,所以有很多东西可能出错。看到: C# - Inconsistent math operation result on 32-bit and 64-bit 和 Double precision problems on .NET
有很多东西可以用浮点来破坏。比较花车的平等是一般的禁忌。你可以检查差异小于合理的epsilon。
答案 2 :(得分:2)
你应该问自己的问题 -
在这种情况下,3号很可能是坏孩子。在调试和发布时,垃圾收集可能会有很大的不同,您可能会发现当对象被垃圾收集时会影响后续单元测试的结果。
如果您使用的是NUnit和TestDriven.NET,我们将在不同的订单中进行两次测试。
答案 3 :(得分:2)
这通常就是这种情况,因为默认情况下调试版本没有优化,即使你启用它,调试时的行为也会大不相同。您可以在Properties-&gt; Build选项卡上禁用所有程序集的项目设置中的“Optimize code”。
肯定有其他可能导致差异的变化,就像你提到的条件方法一样。这些我发现很少是问题的原因,对我而言,它几乎总是优化者。
优化器的经典问题包括“内联”的方法,以便它们无法出现在调用堆栈中。当使用System.Diagnostics.StackFrame类来确定当前执行点时,这会导致问题。类似地,这将影响MethodBase.GetCurrentMethod的结果或依赖于执行方法的其他函数/行为。
然后当然有许多我看过优化器的事情,我根本无法解释。一个这样的例子被记录并在一篇文章“HashDerivedBytes - replacing Rfc2898DeriveBytes, but why?”中进行了讨论,但我从未解开过这个谜团。我只知道优化器只是在用于生成一系列派生字节时破坏了Rfc2898DeriveBytes。奇怪的是,只有当生成的字节不能被所使用的散列算法的大小整除时(20)才会破坏,并且只会在前20个字节之后产生不正确的结果。
事实上,对代码产生负面影响的优化不是编译器的新事物。大多数老式的C ++开发人员会立即告诉你,然后就像我一样,进入一些关于他们如何解决它的长篇故事;)
答案 4 :(得分:0)
正如马克所说,这通常是与时间相关的问题的结果,通常是竞争条件或同步问题。
处理此类问题的一种常见方法是在受影响的区域使用“打印”语句来向您显示正在发生的事情。如果打印语句(Console.WriteLine
,Response.Write
,日志记录或其他任何内容)使问题消失,请将值存储在全局变量中,并在问题出现后打印全局变量。
最近发生在我身上的时间是从串口读取的代码。调试活动导致时序变化足以影响串口的字节缓冲方式,这改变了缓冲区的解析方式。由于print语句改变了时序,我不得不将数据存储到输出中。
答案 5 :(得分:0)
为了加上我的两分钱,我最近发现我在测试调用的sql过程中进行了日期比较。这些日期都是在测试过程之前自动生成的,并且值被插入到DB中,因此有时它们完全相同(使用RunTests时),导致在表连接上返回null。不是我所期待的。显然,在调试模式下,由于我正在慢慢地进行调试,因此自动生成时间会有所不同,这意味着我从未遇到错误。我通过插入
解决了这个问题Threading.Thread.Sleep(520)
行动之间肯定存在延迟。问题已解决。