簡體   English   中英

如何跳過失敗的測試

[英]How to skip a failed test

在 go 中,您是否允許跳過已經失敗的測試?

語境:

我有一個heisenbug ,我目前無法確定其原因。 它有時會導致某些測試失敗。 通過檢查各種日志,我可以確定故障模式。 我想做類似的事情:

if t.Failed() {
    if strings.Contains(string(suite.Stdout), "connection reset by peer") {
        t.Skip("Skip Test failed ")
    }
}

這些測試非常有價值,盡管存在 heisenbug,我還是想在 CI 中運行它們,所以這只是一個臨時的解決方法。

這不起作用。 如果測試失敗,有沒有辦法追溯跳過測試?

簡短的回答是否定的 您可以跳過測試或失敗,但不能兩者兼而有之。

go 的設計者認為嘗試跳過測試是在嘗試顛覆測試框架,因此您不應該嘗試這樣做:

參見例如https://github.com/golang/go/issues/16502

這是有記錄的,但很容易錯過:

如果測試失敗(參見 Error、Errorf、Fail)然后被跳過,它仍然被認為是失敗的。

如果您有檢測 heisenbug 的可靠方法,則應在進行任何測試斷言之前運行它。 所以而不是:

// execute
executeThingBeingTested()

// verify
assert.Equal(t, expected, actual)

// recover if needed
if t.Failed() {
    // detect heisenbug
    if strings.Contains(string(suite.Stdout), "connection reset by peer") {
        t.Skip("Skip Test failed ")
    }
}

相反,您應該構建您的測試,例如:

// execute
executeThingBeingTested()

// skip if needed
if strings.Contains(string(suite.Stdout), "connection reset by peer") {
    t.Skip("Skip Test failed ")
}

// verify
assert.Equal(t, expected, actual)

這意味着您不能在單個測試中的多個執行和驗證階段之間交替,但無論如何在每個測試中只有一個執行和驗證階段是一種很好的做法。 四階段測試

現在,如果你真的想這樣做,你可以去低級別的。 這可能不是一個好主意,但為了完整性而包括在內。 凝視兔子洞可能有助於表明您不想去那里。 這考慮了這個問題以及testing包是如何實現的

    t := suite.T()

    // low-level hackery - undo the failed state so we can skip a test
    pointerVal := reflect.ValueOf(t)
    val := reflect.Indirect(pointerVal)
    member := val.FieldByName("failed")
    ptrToFailedFlag := unsafe.Pointer(member.UnsafeAddr())
    realPtrToFailedFlag := (*bool)(ptrToFailedFlag)
    *realPtrToFailedFlag = false

如果這種程度的黑客還不足以說服您這是一個多么糟糕的主意,那么您可能需要在撰寫本文時注意fail()的實現:

        // Fail marks the function as having failed but continues execution.
   605  func (c *common) Fail() {
   606      if c.parent != nil {
   607          c.parent.Fail()
   608      }
   609      c.mu.Lock()
   610      defer c.mu.Unlock()
   611      // c.done needs to be locked to synchronize checks to c.done in parent tests.
   612      if c.done {
   613          panic("Fail in goroutine after " + c.name + " has completed")
   614      }
   615      c.failed = true
   616  }

您可以看到,一旦調用 Fail(),任何父測試也被標記為失敗。 所以,如果你正在使用類似作證/套件來測試組織在若干套房,到unfail一個測試,你也必須unfail父測試,但是當且僅當在套房沒有其他試驗都失敗了。 因此,更改 testing() 包以允許在失敗后發生跳過與嵌套測試的想法交互不佳。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM