zoukankan      html  css  js  c++  java
  • GO编程(打卡)-Task12: 单元测试

    单元测试

    go test 工具

    包目录内,所有以_test.go为后缀名的源代码文件都是go test测试的一部分,不会被go build编译到最终的可执行文件中

    单元测试函数 函数名前缀为Test 测试程序的一些逻辑行为是否正确
    基准测试函数 函数名前缀为Benchmark 测试函数的性能
    示例函数 函数名前缀为Example 为文档提供示例文档

    测试框架 testing
    测试命令 go test xxx
    测试文件 xxx_test.go

    测试函数

    • 格式

      每个测试函数必须导入testing包, 参数t用于报告测试失败和附加的日志信息

      func TestName(t *testing.T){
          //...
      }
      
    • 示例

      // split/split.go
      
      package split
      import "strings"
      
      func Split(s, sep string) (result []string) {
          i := strings.Index(s, sep)
          for i > -1 {
              result = append(result, s[:i])
              s = s[i+1:]
              // s = s[i+len(sep):] // 这里使用len(sep)获取sep的长度
              i = strings.Index(s, sep)
          }
          result = append(result, s)
          return
      }
      
      // split/split_test.go
      
      package split
      
      import (
      	"reflect"
      	"testing"
      )
      
      func TestSplit(t *testing.T) { // 测试函数名必须以Test开头,必须接收一个*testing.T类型参数
      	got := Split("a:b:c", ":")         // 程序输出的结果
      	want := []string{"a", "b", "c"}    // 期望的结果
      	if !reflect.DeepEqual(want, got) { // 因为slice不能比较直接,借助反射包中的方法比较
      		t.Errorf("excepted:%v, got:%v", want, got) // 测试失败输出错误提示
      	}
      }
      

      在split路径下运行 go test

      添加测试用例

      func TestMoreSplit(t *testing.T) {
      	got := Split("abcd", "bc")
      	want := []string{"a", "d"}
      	if !reflect.DeepEqual(want, got) {
      		t.Errorf("excepted:%v, got:%v", want, got)
      	}
      }
      

      运行指定测试用例

      修改split函数中的代码 s = s[i+1:]s = s[i+len(sep):]

    • 测试组 添加更多测试用例

      func TestSplit(t *testing.T) {
      	// 定义一个测试用例类型
      	type test struct {
      		input string
      		sep   string
      		want  []string
      	}
      	// 定义一个存储测试用例的切片
      	tests := []test{
      		{input: "a:b:c", sep: ":", want: []string{"a", "b", "c"}},
      		{input: "a:b:c", sep: ",", want: []string{"a:b:c"}},
      		{input: "abcd", sep: "bc", want: []string{"a", "d"}},
      		{input: "沙河有沙又有河", sep: "沙", want: []string{"河有", "又有河"}},
      	}
      	// 遍历切片,逐一执行测试用例
      	for _, tc := range tests {
      		got := Split(tc.input, tc.sep)
      		if !reflect.DeepEqual(got, tc.want) {
      			t.Errorf("excepted:%#v, got:%#v", tc.want, got)
      		}
      	}
      }
      

    • 子测试 便于定位测试用例是否通过

      func TestSplit(t *testing.T) {
      	type test struct { // 定义test结构体
      		input string
      		sep   string
      		want  []string
      	}
      	tests := map[string]test{ // 测试用例使用map存储
      		"simple":      {input: "a:b:c", sep: ":", want: []string{"a", "b", "c"}},
      		"wrong sep":   {input: "a:b:c", sep: ",", want: []string{"a:b:c"}},
      		"more sep":    {input: "abcd", sep: "bc", want: []string{"a", "d"}},
      		"leading sep": {input: "沙河有沙又有河", sep: "沙", want: []string{"河有", "又有河"}},
      	}
      	for name, tc := range tests {
      		t.Run(name, func(t *testing.T) { // 使用t.Run()执行子测试
      			got := Split(tc.input, tc.sep)
      			if !reflect.DeepEqual(got, tc.want) {
      				t.Errorf("excepted:%#v, got:%#v", tc.want, got)
      			}
      		})
      	}
      }
      

      运行指定子测试用例

    • 测试覆盖率

      测试覆盖率是你的代码被测试套件覆盖的百分比 go test -cover查看覆盖率

    基准函数

    • 格式

      基准测试必须要执行b.N

      func BenchmarkName(b *testing.B){
          // ...
      }
      
    • 示例

      func BenchmarkSplit(b *testing.B) {
        for i := 0; i < b.N; i++ {
        	Split("沙河有沙又有河", "沙")
        }
      }
      

      go test -bench=Split

      -benchmem参数,来获得内存分配的统计数据

    示例函数

    • 格式

      基准测试必须要执行b.N

      func ExampleName(b *testing.B){
          // ...
      }
      
    • 示例

      func ExampleSplit() {
        fmt.Println(Split("a:b:c", ":"))
        fmt.Println(Split("沙河有沙又有河", "沙"))
        // Output:
        // [a b c]
        // [ 河有 又有河]
      }
      

    参考

    https://github.com/datawhalechina/go-talent/blob/master/10.反射机制.md
    https://www.cnblogs.com/nickchen121/p/11517443.html

  • 相关阅读:
    python基础31[常用模块介绍]
    在Linux下编写Daemon
    python实例31[文件夹清理]
    GDB调试器用法
    python实例31[自动挂载虚拟盘]
    LDAP基础
    Windows上使用Linux shell
    python语法31[iterator和generator+yield]
    python类库31[logging]
    python实例26[验证用户是否存在于LDAP Server]
  • 原文地址:https://www.cnblogs.com/rn-05181226-rw/p/14170973.html
Copyright © 2011-2022 走看看