Чем полезен t.Cleanup? - PullRequest
3 голосов
/ 05 мая 2020

Вопросы

Я хотел бы знать вариант использования t.Cleanup, представленный в Go1.14. В чем преимущество t.Cleanup по сравнению с использованием defer?

https://golang.org/pkg/testing/#T .Cleanup .

  • Sample

Например, предположим, что мы создаем временный каталог, и при его тестировании мы хотим удалить созданный нами временный каталог.

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...
}

Например, в отличной статье ниже описывается проблема, когда возникает пани c, но defer вызывается даже при возникновении пани c, я думаю . Итак, я так и не понял, что может пригодиться.

https://www.gopherguides.com/articles/test-cleanup-in-go-1-14/

Чем полезен t.Cleanup?

Ответы [ 2 ]

8 голосов
/ 05 мая 2020

Функции очистки также вызываются, если ваш тест вызывает панику, поэтому в вашем случае оба будут работать.

Преимущество использования T.Cleanup() становится очевидным, если ваш тест вызывает другие функции, передавая testing.T вместе. Очевидно, что использование defer в этих функциях будет выполняться до возврата из этих функций, но если вы зарегистрируете функции очистки с помощью T.Cleanup(), они будут вызываться только в конце вашего теста.

Подумайте о T.Cleanup() как «улучшенная» и расширенная версия defer. Он также документирует, что переданные функции предназначены для очистки.

3 голосов
/ 05 мая 2020

t.Cleanup полезно для очистки ресурсов, выделенных вспомогательной функцией, когда тест не заботится о самом ресурсе.

Пример

Рассмотрите возможность тестирования уровня сервиса. Служба использует *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()
  })
}

Без t.Cleanup newTestSubject придется возвращать (*domain.Service, *sql.DB), что приводит к утечке информации о конструкции domain.Service.

...