Go-知识测试-示例测试

07-17 926阅读

Go-知识测试-示例测试

  • 1. 定义
  • 2. 例子
  • 3. 数据结构
  • 4. 编译过程
  • 5. 执行过程

    建议先看:https://blog.csdn.net/a18792721831/article/details/140062769

    Go-知识测试-工作机制

    1. 定义

    示例测试要保证测试文件以_test.go结尾。

    测试方法必须以ExampleXxx开头。

    测试文件可以与源码处于同一目录,也可以处于单独的目录。

    检测单行输出格式为 // Output:

    检测多行输出格式为 // Output: \n \n \n,每个期望字符串占一行

    检测无序输出格式为 // Unordered output: \n \n \n ,每个期望字符串占一行

    测试字符串会自动忽略字符串前后的空白字符

    如果测试函数中没有Output表示,则测试函数不会被执行

    2. 例子

    在字符串输出中,可能是一行,可能是多行,也有可能是乱序

    函数如下:

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

    接着使用示例测试

    func ExampleHello() {
    	Hello()
    	// Output: Hello
    }
    func ExampleHelloTwo() {
    	HelloTwo()
    	// Output:
    	// Hello
    	// hi
    }
    func ExampleHelloMore() {
    	HelloMore()
    	// Unordered output:
    	// Hello
    	// hi
    	// 你好
    }
    

    使用go test -v 执行示例测试,-v 表示控制台输出结果

    Go-知识测试-示例测试

    3. 数据结构

    每个测试经过编译后都有一个数据结构来承载,对于示例测试就是InternalExample:

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

    比如如下case:

    func ExampleHelloMore() {
    	HelloMore()
    	// Unordered output:
    	// Hello
    	// hi
    	// 你好
    }
    

    编译后,数据结构成员

    InternalExample.Name = "ExampleHelloMore"
    InternalExample.F = ExampleHelloMore()
    InternalExample.Output = "hello\nhi\n你好\n"
    InternalExample.Unordered = true
    

    4. 编译过程

    在文章: Go-知识测试-工作机制

    Go-知识测试-工作机制

    中,我们知道编译的时候,会调用src/cmd/go/internal/load/test.go:528

    Go-知识测试-示例测试

    在 load 里面会对四种测试进行分别处理:单元测试,性能测试,Main测试和示例测试

    Go-知识测试-示例测试

    在对测试文件进行处理时,会查看注释中是否包含 output

    Go-知识测试-示例测试

    并且封装好元数据

    Go-知识测试-示例测试

    封装好元数据后,会使用元数据渲染模板,生成Main入口,并同时渲染InternalExample切片

    Go-知识测试-示例测试

    5. 执行过程

    在执行的时候,会执行testing.M.Run,在Run里面会执行runExamples

    Go-知识测试-示例测试

    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: %s\n", 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   %s\n", 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: %v\n", err)
    			os.Exit(1)
    		}
    		outC 
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]