Technology sharing

Ite scientia Test-Exemplum Test

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Commendatur primum legere: https://blog.csdn.net/a18792721831/article/details/140062769

Ite scientia Test-Opus Mechanismum

1. Definitio

Sample test necesse est ut in test file finit cum_test.gofinem.
A test modum esse debetExampleXxxprincipium.
Documenta test in eodem indice ac fonte codice vel in directorio separato esse possunt.
Deprehendere una-linea output forma ut // Output: <expectata linea>
Forma deprehendendi multi-lineam output est // Output: n <expectata linea> n <expectata> n, unaquaeque linea expectata unam lineam occupat
Forma deprehendendi inordinata output est // output Unordered: n <expectata> n <expectata> n <expectata> linea, unaquaeque linea expectata chorda occupat.
Filum test testium sponte dissimulare characteres whitespace ante et post chorda tenebit.
Si nulla est output repraesentatio in functione test, munus test exsecutioni mandari non potest.

2. Exemplum

In chordis output, linea una, multiplex linea, vel extra ordinem.
Munus est tale;

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)
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

Tum uti exemplum test

func ExampleHello() {
	Hello()
	// Output: Hello
}

func ExampleHelloTwo() {
	HelloTwo()
	// Output:
	// Hello
	// hi
}

func ExampleHelloMore() {
	HelloMore()
	// Unordered output:
	// Hello
	// hi
	// 你好
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

ususgo test -v Examine specimen probat, -v indicat eventus consolatorium output
Insert imaginem descriptionis hic

3. Data structure

Quisque test structuram datam habet ut eam post compilationem perficiat.

type InternalExample struct {
	Name      string // 测试名称
	F         func() // 测试函数
	Output    string // 期望字符串
	Unordered bool // 输出是否无序
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Exempli causa talis:

func ExampleHelloMore() {
	HelloMore()
	// Unordered output:
	// Hello
	// hi
	// 你好
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Post compilationem, data membra structurae

InternalExample.Name = "ExampleHelloMore"
InternalExample.F = ExampleHelloMore()
InternalExample.Output = "hellonhin你好n"
InternalExample.Unordered = true
  • 1
  • 2
  • 3
  • 4

4. Processus Compilation

In articulo: Ite scientia Test-Opus Mechanismum

Ite scientia Test-Opus Mechanismum

, , , , , , Scimus , quod cum congero , vocabitursrc/cmd/go/internal/load/test.go:528
Insert imaginem descriptionis hic

In onere quattuor genera testium separatim procedentur: unitas probatio, peractio probatio, probatio principalis et specimen experimentum.
Insert imaginem descriptionis hic

Cum expediendas tabellas experiendas, reprehendo utrum commentarium contineat output
Insert imaginem descriptionis hic

Et encapsulate metadata
Insert imaginem descriptionis hic

Postquam metadata est encapsulata, metadata adhibebitur ut Formulam reddat, principalem ingressum generabit, et segmentum InternalExample simul reddet.
Insert imaginem descriptionis hic

5. Executio processus

Cum supplicium, fiettesting.M.Run, exsecutioni mandari in CurrerunExamples
Insert imaginem descriptionis hic

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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34