Запускайте тесты программно в Go

# #go #testing

Вопрос:

У меня есть несколько тестов, которые я хотел бы запустить программно в Go. Я пытаюсь использовать testing.RunTests , но это вызывает ошибку во время выполнения. Я тоже не могу понять, что не так с кодом.

Вот как это выглядит:

 package main

import (
    "testing"
)

func TestSomething(t *testing.T) {
    if false {
        t.Error("This is a mocked failed test")
    }
}

func main() {
    testing.RunTests(func(pat, str string) (bool, error) { return true, nil },
        []testing.InternalTest{
            {"Something", TestSomething}},
    )
}
 

Ссылка на игровую площадку: https://play.golang.org/p/BC5MG8WXYGD

Ошибка, которую я получаю, заключается в том, что:

 panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4b5948]
 

Ответ №1:

Прежде всего, запуск тестов должен выполняться с помощью go test команды.

Некоторые типы и функции, экспортируемые в testing пакете, предназначены для платформы тестирования, а не для вас. Цитата из testing.RunTests() :

RunTests-это внутренняя функция, но экспортируемая, поскольку она является кросс-пакетом; она является частью реализации команды «go test».

Он «должен был» быть экспортирован, потому что он предшествовал «внутренним» пакетам.

Там. Вас предупредили.

Если вы все еще хотите это сделать, позвоните testing.Main() вместо testing.RunTests() этого .

Например:

 func TestGood(t *testing.T) {
}

func TestBad(t *testing.T) {
    t.Error("This is a mocked failed test")
}

func main() {
    testing.Main(
        nil,
        []testing.InternalTest{
            {"Good", TestGood},
            {"Bad", TestBad},
        },
        nil, nil,
    )
}
 

Который выведет (попробуйте это на игровой площадке Go):

 --- FAIL: Bad (0.00s)
    prog.go:11: This is a mocked failed test
FAIL
 

Если вы хотите зафиксировать успех тестирования, используйте функцию «новее» testing.MainStart() .

Сначала нам нужен вспомогательный тип (который реализует несообщаемый интерфейс).:

 type testDeps struct{}

func (td testDeps) MatchString(pat, str string) (bool, error)   { return true, nil }
func (td testDeps) StartCPUProfile(w io.Writer) error           { return nil }
func (td testDeps) StopCPUProfile()                             {}
func (td testDeps) WriteProfileTo(string, io.Writer, int) error { return nil }
func (td testDeps) ImportPath() string                          { return "" }
func (td testDeps) StartTestLog(io.Writer)                      {}
func (td testDeps) StopTestLog() error                          { return nil }
func (td testDeps) SetPanicOnExit0(bool)                        {}
 

И теперь пользуюсь им:

 m := testing.MainStart(testDeps{},
    []testing.InternalTest{
        {"Good", TestGood},
        {"Bad", TestBad},
    },
    nil, nil,
)

result := m.Run()
fmt.Println(result)
 

Какие выходы (попробуйте это на игровой площадке Go):

 --- FAIL: Bad (0.00s)
    prog.go:13: This is a mocked failed test
FAIL
1
 

Если все тесты пройдут, result то будут 0 .

Комментарии:

1. Спасибо, что вы имеете в виду под «если хотите зафиксировать успех тестирования»?

2. @ninesalt, если вы хотите узнать из основного приложения, прошли ли тесты или не прошли, например, вы хотите действовать по-другому в случае успеха.

3. А, ладно, понял.

4. Есть ли какой-нибудь способ, которым я могу разрешить запуск других тестов, если тест перед ними запаниковал? Кажется, этого не происходит

5. @ninesalt Функция тестирования не должна паниковать, это не обычная функция тестирования. Вы можете обернуть его в другую функцию (которая восстанавливается в случае паники), прежде чем добавлять его в []InternalTest срез.

Ответ №2:

Есть способ выполнить команду

 go test -v -json 
 

внутри кода с помощью команды exec.инициализируйте считыватель, который будет считывать данные из stdout, а затем анализировать выходные данные.

Этот ответ был дан https://github.com/AlekSi Очень благодарен, спасибо тебе, Алекси!

https://github.com/FerretDB/dance/blob/main/internal/gotest/gotest.go