Tsu*_*iro 9 testing unit-testing go go1.14
我想知道t.CleanupGo1.14中引入的用例。与使用 defer 相比,t.Cleanup 有什么方便之处?
https://golang.org/pkg/testing/#T.Cleanup。
例如,假设我们创建了一个临时目录,当我们测试它时,我们想删除我们创建的临时目录。
t.Cleanup可用于编写如下测试,但它也可用作defer os.RemoveAll(tempDir).
package mypkg
import (
"io/ioutil"
"os"
"testing"
)
func TestDirwalk(t *testing.T) {
tempDir, err := ioutil.TempDir(".", "temp")
if err != nil {
t.Errorf("create tempDir: %v", err)
}
t.Cleanup(func() { os.RemoveAll(tempDir) })
// something...
}
Run Code Online (Sandbox Code Playgroud)
icz*_*cza 16
如果您的测试出现恐慌,也会调用清理函数,因此在您的情况下两者都可以使用。
T.Cleanup()如果您的测试调用其他函数,使用的优势就很明显了testing.T。显然defer,这些函数中的using会在这些函数返回之前执行,但是如果您使用 注册清理函数T.Cleanup(),那么它们只会在测试结束时被调用。
可以将其T.Cleanup()视为defer. 它还记录了传递的函数用于清理目的。
小智 7
除了其他人指出的之外,t.Cleanup()在处理并行子测试时也很有用,其中清理应该仅在所有子测试完成后运行。考虑
func TestSomething(t *testing.T){
setup()
defer cleanup()
t.Run("parallel subtest 1", func(t *testing.T){
t.Parallel()
(...)
})
t.Run("parallel subtest 2", func(t *testing.T){
t.Parallel()
(...)
})
}
Run Code Online (Sandbox Code Playgroud)
这是行不通的,因为测试函数将在子测试仍在运行时返回,导致子测试所需的资源被defer cleanup().
之前t.Cleanup()解决这个问题的方法是将子测试包装在另一个测试中
func TestSomething(t *testing.T){
setup()
defer cleanup()
t.Run("parallel tests", func(t *testing.T){
t.Run("subtest 1", func(t *testing.T){
t.Parallel()
(...)
})
t.Run("subtest 2", func(t *testing.T){
t.Parallel()
(...)
})
})
}
Run Code Online (Sandbox Code Playgroud)
看起来不错,但有了t.Cleanup()它会变得更好
func TestSomething(t *testing.T){
setup()
t.Cleanup(cleanup)
t.Run("parallel subtest 1", func(t *testing.T){
t.Parallel()
(...)
})
t.Run("parallel subtest 2", func(t *testing.T){
t.Parallel()
(...)
})
}
Run Code Online (Sandbox Code Playgroud)
t.Cleanup 当测试不关心资源本身时,可用于清理辅助函数分配的资源。
考虑测试服务层。该服务使用 a*sql.DB但不创建它本身。
package testutils
import (
"testing"
"my/db"
"my/domain"
)
func NewTestSubject(t *testing.T) *domain.Service {
t.Helper()
sqldb := newDatabase(t)
s, _ := domain.NewService(sqldb)
return s
}
func newDatabase(t *testing.T) *sql.DB {
t.Helper()
d, _ := db.Create()
t.Cleanup(func() {
d.Close()
})
}
Run Code Online (Sandbox Code Playgroud)
没有t.Cleanup newTestSubject将不得不返回(*domain.Service, *sql.DB),泄漏有关domain.Service的构造的详细信息。