informasi kontak saya
Surat[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Disarankan untuk membaca terlebih dahulu: https://blog.csdn.net/a18792721831/article/details/140062769
Mekanisme Kerja Tes Go-Knowledge
Tes sampel harus memastikan bahwa file tes diakhiri dengan_test.go
akhir.
Metode pengujiannya harusExampleXxx
awal.
File pengujian bisa berada di direktori yang sama dengan kode sumber atau di direktori terpisah.
Deteksi format keluaran satu baris sebagai // Output: <string yang diharapkan>
Format pendeteksian keluaran multi-baris adalah // Keluaran: n <string yang diharapkan> n <string yang diharapkan> n, setiap string yang diharapkan menempati satu baris
Format pendeteksian keluaran tidak berurutan adalah // Keluaran tidak berurutan: n <string yang diharapkan> n <string yang diharapkan> n <string yang diharapkan>, setiap string yang diharapkan menempati satu baris
String pengujian akan secara otomatis mengabaikan karakter spasi sebelum dan sesudah string.
Jika tidak ada representasi Output dalam fungsi pengujian, fungsi pengujian tidak akan dijalankan.
Dalam keluaran string, mungkin satu baris, mungkin beberapa baris, atau mungkin rusak.
Fungsinya adalah sebagai berikut:
func Hello() {
fmt.Println("Hello")
}
func HelloTwo() {
fmt.Println("Hello")
fmt.Println("hi")
}
func HelloMore() {
m := make(map[string]string)
m["hello"] = "Hello"
m["hi"] = "hi"
m["你好"] = "你好"
for _, v := range m {
fmt.Println(v)
}
}
Kemudian gunakan contoh tes
func ExampleHello() {
Hello()
// Output: Hello
}
func ExampleHelloTwo() {
HelloTwo()
// Output:
// Hello
// hi
}
func ExampleHelloMore() {
HelloMore()
// Unordered output:
// Hello
// hi
// 你好
}
menggunakango test -v
Jalankan pengujian sampel, -v menunjukkan hasil keluaran konsol
Setiap pengujian memiliki struktur data untuk membawanya setelah kompilasi. Untuk contoh pengujian, ini adalah InternalExample:
type InternalExample struct {
Name string // 测试名称
F func() // 测试函数
Output string // 期望字符串
Unordered bool // 输出是否无序
}
Misalnya kasus berikut:
func ExampleHelloMore() {
HelloMore()
// Unordered output:
// Hello
// hi
// 你好
}
Setelah kompilasi, anggota struktur data
InternalExample.Name = "ExampleHelloMore"
InternalExample.F = ExampleHelloMore()
InternalExample.Output = "hellonhin你好n"
InternalExample.Unordered = true
Di dalam artikel: Mekanisme Kerja Tes Go-Knowledge
, kita tahu bahwa saat kompilasi, itu akan dipanggilsrc/cmd/go/internal/load/test.go:528
Dalam beban, empat jenis pengujian akan diproses secara terpisah: pengujian unit, pengujian kinerja, pengujian utama, dan pengujian sampel.
Saat memproses file pengujian, periksa apakah komentar berisi keluaran
Dan merangkum metadata
Setelah metadata dienkapsulasi, metadata akan digunakan untuk merender templat, menghasilkan entri Utama, dan merender potongan InternalExample secara bersamaan.
Ketika dieksekusi, itu akan dieksekusitesting.M.Run
, akan dieksekusi di RunrunExamples
func runExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ran, ok bool) {
ok = true
var eg InternalExample
// 对每个实例测试进行执行
for _, eg = range examples {
// 是否匹配
matched, err := matchString(*match, eg.Name)
if err != nil {
fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %sn", err)
os.Exit(1)
}
if !matched {
continue
}
ran = true
// 执行
if !runExample(eg) {
ok = false
}
}
return ran, ok
}
func runExample(eg InternalExample) (ok bool) {
// 附加输出
if *chatty {
fmt.Printf("=== RUN %sn", eg.Name)
}
// 获取标准输出
stdout := os.Stdout
// 新建管道,将标准输出拷贝一份
r, w, err := os.Pipe()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
os.Stdout = w
// 创建一个管道,用于接收标准输出返回的字符串
outC := make(chan string)
// 在一个单独的 goroutine 中处理拷贝的输出
go func() {
var buf strings.Builder
_, err := io.Copy(&buf, r)
r.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "testing: copying pipe: %vn", err)
os.Exit(1)
}
outC <- buf.String()
}()
finished := false
start := time.Now()
// 在延迟函数中,读取管道中的数据
defer func() {
timeSpent := time.Since(start)
w.Close()
os.Stdout = stdout
// 获取标准输出
out := <-outC
err := recover()
// 调用 processRunResult 进行比较
ok = eg.processRunResult(out, timeSpent, finished, err)
}()
// 执行示例函数,也就是目标函数
eg.F()
finished = true
return
}
func (eg *InternalExample) processRunResult(stdout string, timeSpent time.Duration, finished bool, recovered interface{}) (passed bool) {
passed = true
dstr := fmtDuration(timeSpent)
var fail string
// 标准输出,去除空字符,这也是为何实例测试中会忽略空白字符
got := strings.TrimSpace(stdout)
// 期望输出
want := strings.TrimSpace(eg.Output)
// 是否乱序
if eg.Unordered {
// 先排序,然后字符串比较
if sortLines(got) != sortLines(want) && recovered == nil {
fail = fmt.Sprintf("got:n%snwant (unordered):n%sn", stdout, eg.Output)
}
} else {
if got != want && recovered == nil {
fail = fmt.Sprintf("got:n%snwant:n%sn", got, want)
}
}
if fail != "" || !finished || recovered != nil {
fmt.Printf("--- FAIL: %s (%s)n%s", eg.Name, dstr, fail)
passed = false
} else if *chatty {
fmt.Printf("--- PASS: %s (%s)n", eg.Name, dstr)
}
if recovered != nil {
// Propagate the previously recovered result, by panicking.
panic(recovered)
}
if !finished && recovered == nil {
panic(errNilPanicOrGoexit)
}
return
}