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 這個管理工具進行安裝:
- $ goup install tip
安裝成功后,查看版本信息(你看到的大概率和我的不一樣):
- $ go version
- go version devel go1.17-1607c28172 Sun May 30 02:37:38 2021 +0000 darwin/amd64
02 新的 shuffle flag
安裝完 tip 版本后,執行如下命令:
- $ go help testflag
然后找到下面這個 flag:
- -shuffle off,on,N
- Randomize the execution order of tests and benchmarks.
- It is off by default. If -shuffle is set to on, then it will seed
- the randomizer using the system clock. If -shuffle is set to an
- integer N, then N will be used as the seed value. In both cases,
- 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,增加「加減乘除」四個函數:
- func Add(x, y int) int {
- return x + y
- }
- func Minus(x, y int) int {
- return x - y
- }
- func Mul(x, y int) int {
- return x * y
- }
- func Div(x, y int) int {
- return x / y
- }
并為這四個函數寫好單元測試(代碼太長,這里只列出 Add 的,寫法不重要,按你喜歡的方式寫單元測試即可):
- func TestAdd(t *testing.T) {
- type args struct {
- x int
- y int
- }
- tests := []struct {
- args args
- want int
- }{
- {
- args{1, 2},
- 3,
- },
- {
- args{-1, 3},
- 3, // 特意構造一個 failure 的 case
- },
- }
- for _, tt := range tests {
- if got := Add(tt.args.x, tt.args.y); got != tt.want {
- t.Errorf("Add() = %v, want %v", got, tt.want)
- }
- }
- }
然后運行單元測試(不加 shuffle flag):
- $ go test -v ./...
- === RUN TestAdd
- calc_test.go:27: Add() = 2, want 3
- --- FAIL: TestAdd (0.00s)
- === RUN TestMinus
- --- PASS: TestMinus (0.00s)
- === RUN TestMul
- --- PASS: TestMul (0.00s)
- === RUN TestDiv
- --- PASS: TestDiv (0.00s)
- FAIL
- FAIL test/shuffle 0.441s
- FAIL
多次運行,發現執行順序都是你文件中寫好的單元測試順序,我這里是 Add、Minus、Mul、Div。
加上 shuffle flag 后運行:
- $ go test -v -shuffle=on ./...
- -test.shuffle 1622383890431866000
- === RUN TestMul
- --- PASS: TestMul (0.00s)
- === RUN TestDiv
- --- PASS: TestDiv (0.00s)
- === RUN TestAdd
- calc_test.go:27: Add() = 2, want 3
- --- FAIL: TestAdd (0.00s)
- === RUN TestMinus
- --- PASS: TestMinus (0.00s)
- FAIL
- FAIL test/shuffle 0.177s
- FAIL
輸出有兩處變化:
- 多了 -test.shuffle 1622383890431866000,即上面說到的種子。如果不是 on 而是 N,則這里的值就是 N 的值;
- 順序不確定。你多次運行,發現每次順序可能不一樣;
順便提一句,對于 benchmark,shuffle 這個 flag 也是適用的。
04 有什么用
有人可能會問,這個玩意有啥用?
確實,大部分時候這個特性沒啥用。但如果你不希望測試之間有依賴關系,而擔心實際上依賴了,可以加上這個 flag,以便發現潛在的問題。
其實,這個 flag 早在 2015 年 bradfitz 就提 issue 建議加上,原計劃在 Go1.6 加上的,但沒有人寫提案,因此擱置了。6 年過去了,才加上該功能,可見需求不強烈。日常工作中,你大概率也不會用到,但知曉有這么個東西還是有用處的,萬一需要時,可以用上。
本文轉載自微信公眾號「polarisxu」,可以通過以下二維碼關注。轉載本文請聯系polarisxu公眾號。