Цель
Чтобы записать fmt.Println в тестах, чтобы я мог быть уверен, что моя программа выводит правильные данные на консоль.
Попытка1
Использование пользовательских писателей для замены os.Stdout, как это предлагается здесь . Он работает для одного теста.
Проблема для попытки 1
Когда я объявляю несколько тестов для проверки выходных данных по различным функциям, некоторые из них работают, а некоторые -не удается захватить выходные данные (выходные данные по-прежнему поступают из стандартного вывода).
Гипотеза
Как указывалось в приведенном выше блоге, это не является потокобезопасным. Некоторые из захватов будут завершены и сбрасывают стандартный вывод, в то время как другие все еще работают, предотвращая захват некоторых выходов.
Попытка решения
Чтобы установить os.Stdout вПользовательский писатель в TestMain и сбросить его в конце TestMain.
Больше проблем
Когда я пытаюсь установить os.Stdout в TestMain, программа завершается со статусом 1без сообщения об ошибке вообще. Я закомментирую код, он запускается (просто, чтобы выходные данные не были захвачены), но когда я отсоединяю их, он ломается.
Код для попытки 1 из https://medium.com/@hau12a1/golang-capturing-log-println-and-fmt-println-output-770209c791b4
func captureOutput(f func()) string {
reader, writer, err := os.Pipe()
if err != nil {
panic(err)
}
stdout := os.Stdout
stderr := os.Stderr
defer func() {
os.Stdout = stdout
os.Stderr = stderr
log.SetOutput(os.Stderr)
}()
os.Stdout = writer
os.Stderr = writer
log.SetOutput(writer)
out := make(chan string)
wg := new(sync.WaitGroup)
wg.Add(1)
go func() {
var buf bytes.Buffer
wg.Done()
io.Copy(&buf, reader)
out <- buf.String()
}()
wg.Wait()
f()
writer.Close()
return <-out
}
Код для попытки 2 только для TestMain, фактическая функция захвата опущена
func TestMain(m *testing.M) {
var err error
reader, writer, err = os.Pipe()
if err != nil {
panic(err)
}
stdout := os.Stdout
stderr := os.Stderr
os.Stdout = writer // These two lines
os.Stderr = writer // are causing problems
log.SetOutput(writer)
// Create and open test database
db, err = sql.Open("sqlite3", "test.db")
if err != nil {
log.Fatal(err)
}
Init()
// Initialize fixtures
fixtures, err = testfixtures.NewFolder(db, &testfixtures.SQLite{}, "testdata/fixtures")
if err != nil {
log.Fatal(err)
}
result := m.Run()
os.Stdout = stdout
os.Stderr = stderr
log.SetOutput(os.Stderr)
// Delete test database
CloseDB()
if err != nil {
log.Fatal(err)
}
err = os.Remove("./test.db")
if err != nil {
log.Fatal(err)
}
os.Exit(result)
}
Вывод ошибки для попытки два вообще не полезен
exit status 1
FAIL gitlab.com/haowenl/diary/cmd 0.320s
Так как мне поступить об этом?
Спасибо!