【问题标题】:Retry a Visual Studio C# TestMethod重试 Visual Studio C# 测试方法
【发布时间】:2010-07-30 18:48:39
【问题描述】:

我很想知道在 C# 的 Visual Studio 2008 单元测试框架中是否有任何内置机制可以重试测试。 举个例子,我有一个 C# 单元测试,它看起来像:

[TestMethod]
public void MyMethod() {
    DoSomething();
    Assert.Something();
}

现在,DoSomething() 偶尔表现不佳;在这种情况下,我想在到达断言之前重新运行 DoSomething() 方法。显然我可以这样做:

...
do {
    Initialization();
    DoSomething();
} while (PerformedOK() == false);
Assert.Something();
...

虽然这有点麻烦,因为添加了循环并重复测试初始化​​,否则将完全由其他方法/类构造函数处理。

我的问题是是否有更方便的重试机制,例如:

DoSomething();
if (PerformedOK() == false) Retry();
else Assert.Something();

它将自动重试测试而不将其注册为失败,同时照常执行所有常规初始化代码。

【问题讨论】:

  • 为什么有时表现不佳?
  • @Lasse:在这种情况下,它并不是“表现不佳”,因为它只是失去了与另一个组件的同步,而导致它失去同步的方面与这个特定的测试用例无关。无论如何,我的问题更笼统,并不真正关心为什么需要重试。
  • 测试实际失败时会发生什么?你会“重试10次然后停止”吗?如果其他组件处于必须重试 11 次的状态怎么办?让我重新表述我的问题。如果你完全删除你的测试会发生什么?脆弱的测试是单元测试的祸根“哦,那个测试,是的,我们知道,它总是失败,忽略它,它会消失的”。
  • @Lasse“测试失败时会发生什么” - 我希望有一个重试机制(如果存在)允许我指定何时应该重试,什么时候不应该......就像在伪- 上面的语法。
  • 如果可能的话,我强烈建议只重试特定的已知异常。这样一来,您的测试方法就不会永远运行或每次都通过——它至少会在一些错误上失败。

标签: c# visual-studio unit-testing


【解决方案1】:

说真的……

偶尔 DoSomething() 执行 很糟糕

每次测试都应该是绿色的。如果测试的代码有时执行“糟糕”,那么您需要修复您的代码,隔离不同的行为。您应该进行两项测试,一项在 DoSomething 失败(并且应该失败)时断言正确,另一项在 DoSomething 正常(并且应该正常)时断言正确。

在测试中使用重试逻辑是错误的。您应该始终断言预期的结果,并且应该能够隔离和检测您的代码以返回您期望的结果。

[编辑 - 添加了一些可用于重试循环的代码]

你可以创建一个循环包装器,它接受任何方法并调用它 X 次,或者直到它成功。您还可以让 Loop 函数调用您的 init,或将其作为单独的参数传递。如果成功,该方法也可以返回一个布尔值。更改签名以满足您的需要。

[TestMethod]
public void something()
{
   Loop.LoopMe(TestMethod,3);            
   Assert.Something();
}

class Loop
{
    public static void LoopMe(Action action, int maxRetry)
    {
        Exception lastException = null;
        while (maxRetry > 0)
        {
            try
            {
                action();
                return;
            }
            catch (Exception e)
            {
                lastException = e;
                maxRetry--;                    
            }                
        }
        throw lastException;
    }
}

【讨论】:

  • 我理解您的意见并感谢您的建议,但有时还有其他考虑因素。
  • @Oak:您在哪些方面依赖第三方系统?如果是集成测试,重试逻辑可能没问题,但我仍然认为它应该在您的代码库中,而不是在您的测试中。
  • 如果“其他考虑”确实是第三方,请考虑使用模拟和/或存根。不要想出更好的方法来做错事。
  • @lotsoffreetime:“做错事的更好方法”,我可以引用你的话吗?
  • @oak:它告诉您重试循环应该在 DoSomething 内部或在一些处理触发重试的异常的包装库代码中,而不是在测试中,因为您希望它只要您工作就可以工作重试。您如何在生产中处理它?
【解决方案2】:

您的第二个示例几乎是相同的代码行和相同的复杂性。有很多方法可以剥皮,你可以不是我提倡使用递归。

[TestMethod]
public void MyMethod() {
   bool success = DoSomething();
   Assert.IsTrue(success);
}

public boolean DoSomething(){
    //Do whatever

    if(performedOk){
       return true;
    }else{
        //find a way to stop it.
    }

}

但关键是它是一个单元测试。如果某些事情导致它出错,您需要找到一种方法隔离您的测试,以便它处于受控环境中。

除非您有要求,否则测试最终应该通过。您应该使用的最佳重试逻辑是在它失败之后。点击测试并再次点击运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    • 2017-08-13
    • 1970-01-01
    • 2013-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多