亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何使用 golang 中的并行子測試處理父測試拆解

如何使用 golang 中的并行子測試處理父測試拆解

Go
qq_笑_17 2023-05-22 17:08:55
概述如果我有一個帶有設置和拆卸邏輯的父測試,我如何在其中并行運行子測試而不會遇到帶有拆卸邏輯的競爭條件?func TestFoo(t *testing.T) {    // setup logic    t.Run("a", func(t *testing.T) {        t.Parallel()        // test code    })    // teardown logic}例子作為一個人為的例子:假設測試需要創建一個 tmp 文件,所有子測試都將使用該文件,并在測試結束時將其刪除。例如,父測試也調用t.Parallel(),因為這是我最終想要的。但是我的問題和下面的輸出是一樣的,即使父母不打電話t.Parallel()。序貫子測驗如果我按順序運行子測試,它們將毫無問題地通過:package mainimport (    "fmt"    "io/ioutil"    "os"    "testing")func setup(t *testing.T) (tmpFile string) {    f, err := ioutil.TempFile("/tmp", "subtests")    if err != nil {        t.Fatalf("could not setup tmp file: %+v", err)    }    f.Close()    return f.Name()}var ncase = 2func TestSeqSubtest(t *testing.T) {    t.Parallel()    // setup test variables    fname := setup(t)    // cleanup test variables    defer func() {        os.Remove(fname)    }()    for i := 0; i < ncase; i++ {        t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {            if _, err := os.Stat(fname); os.IsNotExist(err) {                t.Fatalf("file was removed before subtest finished")            }        })    }}  輸出:$ go test subtests  ok      subtests        0.001s平行分測驗但是,如果我并行運行子測試,那么父測試的拆卸邏輯最終會在子測試有機會運行之前被調用,從而使子測試無法正確運行。這種行為雖然不幸,但符合“使用子測試和子基準” go 博客所說的內容:如果測試函數在其 testing.T 實例上調用 Parallel 方法,則該測試稱為并行測試。并行測試永遠不會與順序測試同時運行,并且它的執行會暫停,直到它的調用測試函數(父測試的調用函數)返回為止。func TestParallelSubtest(t *testing.T) {    t.Parallel()    // setup test variables    fname := setup(t)    // cleanup test variables    defer func() {        os.Remove(fname)    }()    for i := 0; i < ncase; i++ {        t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {            t.Parallel() // the change that breaks things            if _, err := os.Stat(fname); os.IsNotExist(err) {                t.Fatalf("file was removed before subtest finished")            }        })    }}
查看完整描述

2 回答

?
富國滬深

TA貢獻1790條經驗 獲得超9個贊

如何執行此操作:

func TestParallelSubtest(t *testing.T) {

? ? // setup test variables

? ? fname := setup(t)


? ? t.Run("group", func(t *testing.T) {

? ? ? ? for i := 0; i < ncase; i++ {

? ? ? ? ? ? t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {

? ? ? ? ? ? ? ? t.Parallel()

? ? ? ? ? ? ? ? if _, err := os.Stat(fname); os.IsNotExist(err) {

? ? ? ? ? ? ? ? ? ? t.Fatalf("file was removed before subtest finished")

? ? ? ? ? ? ? ? }

? ? ? ? ? ? })

? ? ? ? }

? ? })

? ??

? ? os.Remove(fname)

}

博客文章的相關部分位于Control of Parallelism:


每個測試都與一個測試函數相關聯。如果一個測試的測試函數在其testing.T. 并行測試永遠不會與順序測試同時運行,并且它的執行會暫停,直到它的調用測試函數(父測試的調用函數)返回為止。[...]


一個測試會阻塞,直到它的測試函數返回并且它的所有子測試都已經完成。這意味著由順序測試運行的并行測試將在運行任何其他連續順序測試之前完成。


您的問題的具體解決方案可以在參考資料部分找到Cleaning up after a group of parallel tests。


查看完整回答
反對 回復 2023-05-22
?
心有法竹

TA貢獻1866條經驗 獲得超5個贊

從 Go 1.14 開始,testing.T有了允許注冊拆卸回調的方法testing.B。Cleanup

t.Cleanup(func()?{
????os.Remove(fname)
})


查看完整回答
反對 回復 2023-05-22
  • 2 回答
  • 0 關注
  • 145 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號