Golang学习实战笔记-基础 > golang代码性能优化
编写go 测试用例-使用goland快速生成测试方法

方式1 :使用goland 开速生成测试用例

1. 在想要测试的方法下面点击鼠标右键 在弹出框选择Generate (快捷键 Alt+Insert)

2. 选择 Test for selecttion


3. goland 会在当前目录下面 生产一个 cache_test.go 的文件并且 ,自动写好测试方法 ,我们需要填充测试数据。

    tests 是一个结构体数组包含了我们的测试用例, 每一个测试用例 包含 

        name(测试用例名称) ,

        args(测试方法传入的参数) ,

        wantErr (预期结果是否报错)

    这个tests 结构根据测试方法不同会有一些差别,但是大体就是 xx_name 测试用例 输入参数是 args,预期输出结果是xxx这样的测试逻辑来的。

func TestGetCache(t *testing.T) {
type args struct {
client Cache
key    string
out    interface{}
call   func() (interface{}, error)
}

option := redis.Options{Addr: "127.0.0.1:6379", DB: 0, Password: ""}

g := &Group{}
tests := []struct {
name    string
args    args
wantErr bool
}{
{
"loacl",
args{
NewRedisCache(redis.NewClient(&option), ""),
"group:2",
g,
func() (i interface{}, e error) {
return &Group{Title: "title"}, nil
},
},
false,
},
{
"loacl",
args{
NewRedisCache(redis.NewClient(&option), ""),
"group:2",
nil,
func() (i interface{}, e error) {
return &Group{Title: "title"}, nil
},
},
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := GetCache(tt.args.client, tt.args.key, tt.args.out,
        time.Second*5, tt.args.call);
         (err != nil) != tt.wantErr {
t.Errorf("GetCache() error = %v, wantErr %v", err, tt.wantErr)
}
if g, ok := tt.args.out.(*Group); ok {
if g.Title != "title" {
t.Error(g)
}
}
})
}
}


cache.go源代码:

type Cache interface {
	Get(key string) (interface{}, error)
	Set(key string, value interface{}, expiration time.Duration) error
	Del(key string) error
	Incr(key string) error
}

//先从缓存读取数据,如果不存在调用 call方法获取后在存放到数据库中
func GetCache(client Cache, key string, out interface{}, expiration time.Duration, call func() (interface{}, error)) ( error) {
	if out == nil {
		return errors.New("out can not  be nil")
	}
	isOK := false
	val, err := client.Get(key)
	//是否需要重新刷新缓存
	if err == nil && val != "" {
		if v, ok := val.(string); ok {
			err := json.Unmarshal([]byte(v), out)
			if err != nil {
				isOK = false
			} else {
				isOK = true
			}
		}
	}

	if val == "" || !isOK {
		{
			//记录没有命中的缓存次数, 方便后面优化代码
			client.Incr(CacheStatisticsPrefix + key)
		}
		newVal, err := call()
		if err != nil {
			return err
		}
		data, err := json.Marshal(newVal)
		if err != nil {
			return err
		}
		if err := client.Set(key, data, expiration); err != nil {
			return err
		}
		err = json.Unmarshal(data, out)
		if err != nil {
			return err
		}
		return nil
	}
	return nil
}

点击执行按钮就可以测试这个方法了。


方式二 : 自己写测试用例 

直接在要测试代码目录下面新建一个 xx_test.go 文件。

package 名字和其他文件一致。 

写上测试方法 注意方法签名 t 是指针类型。

func TestXX (t  *testing.T){
   if  something {
       t.Fail()
   }
}


执行测试方法。

go test -v --run functionName    xx_test.go   testfile.go  ....go

-v   打印详细输出日志

--run  指定要测试的方法名(如果不输入这个 则执行所有的测试方法)

xx_test.go 测试代码所在的文件

testfile.go  依赖的被测试的文件 (要加上否则找不到被测试的方法)



总结: 给自己写的代码加上测试用例 ,如果测试用例不好写说明方法太复杂或者依赖过多 ,所以我们在写代码的时候要考虑这段代码如何被测试。写测试用例有个好处就是可以初步保证 ,某个单元是可用的,在业务逻辑比较复杂的情况下不会因为一些小的失误而导致严重的问题。千里之堤溃于蚁穴 有时候一个系统的崩溃可能就是一个参数没有处理好的问题。


最好扯淡一下 ,大家都听说过 千里之堤溃于蚁穴 的语句,但是他的来历你了解吗?

    战国时期,魏国相国白圭在防洪方面很有成绩,他善于筑堤防洪,并勤查勤补,经常巡视,一发现小洞即使是极小的蚂蚁洞也立即派人填补,不让它漏水,以免小洞逐渐扩大、决口,造成大灾害。白圭任魏相期间,魏国没有闹过水灾。

   这个典故来着:《韩非子.喻老》:“千丈之堤,以蝼蚁之穴溃;百尺之室,以突隙之烟焚。”突:烟囱。烟:“熛”字之误写;熛( ㄅㄧㄠ biāo 标),进飞的火焰。

  看来bug这个东西是从古代就存在的。。。。