Go1.17这个新特性竟然是6年前提出来的

大家好,我是 polarisxu。

Go1.17 预计在 8 月份发布。目前 tip.golang.org 可以浏览 Go1.17 的相关内容,https://tip.golang.org/doc/go1.17 也有了 Go1.17 相关改动的部分文档。这段时间,我会陆续给大家分享 Go1.17 中相关的新特性,提前学习。。。好吧,提前卷了~

今天先聊聊在测试中增加的随机化 flag:shuffle。

01 安装 tip 版本

由于 Go1.17 还未发布,因此为了体验它的新特性,我们需要安装 tip 版本。这是一个正在开发的版本,也就是仓库的 master 分支代码。因此,我们需要通过源码编译安装。

这里我使用 goup 这个管理工具进行安装:

 
 
 
 
  1. $ goup install tip 

安装成功后,查看版本信息(你看到的大概率和我的不一样):

 
 
 
 
  1. $ go version 
  2. go version devel go1.17-1607c28172 Sun May 30 02:37:38 2021 +0000 darwin/amd64 

02 新的 shuffle flag

安装完 tip 版本后,执行如下命令:

 
 
 
 
  1. $ go help testflag 

然后找到下面这个 flag:

 
 
 
 
  1. -shuffle off,on,N 
  2.         Randomize the execution order of tests and benchmarks. 
  3.         It is off by default. If -shuffle is set to on, then it will seed 
  4.         the randomizer using the system clock. If -shuffle is set to an 
  5.         integer N, then N will be used as the seed value. In both cases, 
  6.         the seed will be reported for reproducibility. 

这是 Go1.17 新增的,提交的代码见:https://golang.org/cl/310033。

从名称可以看出,这是控制测试执行顺序是否随机的 flag。它有三个值:off、on 和 N,其中默认是 off,即不启用随机,这相当于 Go1.17 版本之前的测试行为。而 on 表示启用 shuffle,那 N 是什么意思?它也表示启用随机。on 和 N 的区别解释下:

因为是随机,就涉及到随机种子(seed)问题。当值是 on 时,随机数种子使用系统时钟;如果值是 N,则直接用这个 N 当做随机数种子。注意 N 是整数。

当测试失败时,如果启用了 shuffle,这个种子会打印出来,方便你重现之前测试场景。

03 例子体验下

创建一个包 calc,增加「加减乘除」四个函数:

 
 
 
 
  1. func Add(x, y int) int { 
  2.  return x + y 
  3.  
  4. func Minus(x, y int) int { 
  5.  return x - y 
  6.  
  7. func Mul(x, y int) int { 
  8.  return x * y 
  9.  
  10. func Div(x, y int) int { 
  11.  return x / y 

并为这四个函数写好单元测试(代码太长,这里只列出 Add 的,写法不重要,按你喜欢的方式写单元测试即可):

 
 
 
 
  1. func TestAdd(t *testing.T) { 
  2.  type args struct { 
  3.   x int 
  4.   y int 
  5.  } 
  6.  tests := []struct { 
  7.   args args 
  8.   want int 
  9.  }{ 
  10.   { 
  11.    args{1, 2}, 
  12.    3, 
  13.   }, 
  14.   { 
  15.    args{-1, 3}, 
  16.    3,  // 特意构造一个 failure 的 case 
  17.   }, 
  18.  } 
  19.  for _, tt := range tests { 
  20.   if got := Add(tt.args.x, tt.args.y); got != tt.want { 
  21.    t.Errorf("Add() = %v, want %v", got, tt.want) 
  22.   } 
  23.  } 

然后运行单元测试(不加 shuffle flag):

 
 
 
 
  1. $ go test -v ./... 
  2. === RUN   TestAdd 
  3.     calc_test.go:27: Add() = 2, want 3 
  4. --- FAIL: TestAdd (0.00s) 
  5. === RUN   TestMinus 
  6. --- PASS: TestMinus (0.00s) 
  7. === RUN   TestMul 
  8. --- PASS: TestMul (0.00s) 
  9. === RUN   TestDiv 
  10. --- PASS: TestDiv (0.00s) 
  11. FAIL 
  12. FAIL test/shuffle 0.441s 
  13. FAIL 

多次运行,发现执行顺序都是你文件中写好的单元测试顺序,我这里是 Add、Minus、Mul、Div。

加上 shuffle flag 后运行:

 
 
 
 
  1. $ go test -v -shuffle=on ./... 
  2. -test.shuffle 1622383890431866000 
  3. === RUN   TestMul 
  4. --- PASS: TestMul (0.00s) 
  5. === RUN   TestDiv 
  6. --- PASS: TestDiv (0.00s) 
  7. === RUN   TestAdd 
  8.     calc_test.go:27: Add() = 2, want 3 
  9. --- FAIL: TestAdd (0.00s) 
  10. === RUN   TestMinus 
  11. --- PASS: TestMinus (0.00s) 
  12. FAIL 
  13. FAIL test/shuffle 0.177s 
  14. FAIL 

输出有两处变化:

  • 多了 -test.shuffle 1622383890431866000,即上面说到的种子。如果不是 on 而是 N,则这里的值就是 N 的值;
  • 顺序不确定。你多次运行,发现每次顺序可能不一样;

顺便提一句,对于 benchmark,shuffle 这个 flag 也是适用的。

04 有什么用

有人可能会问,这个玩意有啥用?

确实,大部分时候这个特性没啥用。但如果你不希望测试之间有依赖关系,而担心实际上依赖了,可以加上这个 flag,以便发现潜在的问题。

其实,这个 flag 早在 2015 年 bradfitz 就提 issue 建议加上,原计划在 Go1.6 加上的,但没有人写提案,因此搁置了。6 年过去了,才加上该功能,可见需求不强烈。日常工作中,你大概率也不会用到,但知晓有这么个东西还是有用处的,万一需要时,可以用上。

本文转载自微信公众号「polarisxu」,可以通过以下二维码关注。转载本文请联系polarisxu公众号。

本文题目:Go1.17这个新特性竟然是6年前提出来的
本文路径:http://www.shufengxianlan.com/qtweb/news34/437234.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联