###### tags: `GoLang` # GoLang 05. 開發工具: ### Go 專案資料夾佈局: https://github.com/golang-standards/project-layout ```bash directory ├── /api #OpenAPI/Swagger 規範,JSON 模式(schema)文件... ├── /build #專案執行檔放置處,目錄內包含機器執行所需要的檔案 ├── /cmd #如果專案編寫包含多個執行檔,將各自package main放置各目錄內 │ ├── authtest │ │ └── main.go │ ├── backend │ │ └── main.go │ └── client │ └── main.go ├── /configs #設定檔集,如預設設定.不同OS環境設定... ├── /docs #專案文檔放置處 ├── /deploy #容器化專案所需檔案放置處(選用) │ ├── add_migration.sh │ └── docker-compose.yml ├── /migrations/ #db特定操作(非標準方式) │ ├── 20190721131113_extensions.down.sql │ ├── migrations.go │ └── README.md │#vendor/internal/pkg 三者目錄可在go專案內子資料夾中出現 ├── /vendor #Go專案外部依賴包或第三方包,可由go mod vendor產生 ├── /internal #main之私用package ├── /pkg #main之公用package │ ├── api/ │ │ ├── exitus.gen.go │ │ └── gen.go │ ├── auth/ │ │ ├── scopes.go │ │ └── user.go │ ├── conf/ │ │ ├── conf.go │ │ └── conf_test.go │ ├── db/ │ │ ├── db.go │ │ ├── dbtesting.go │ │ └── sqlhooks.go │ ├── server/ │ │ └── server.go │ └── store/ │ ├── comments.go │ ├── comments_test.go │ └── store.go ├── /scripts #build相關腳本放置處(選用) ├── /website #靜態資源檔案放置處 ├── /assets #其他資源檔案放置處,如logos ├── Dockerfile ├── go.mod ├── go.sum └── README.md ``` ### Go 環境設置: #### Windwos ```ini Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\.go] @="Go.Code.Template" [HKEY_CLASSES_ROOT\.go\ShellNew] "FileName"="Template.go" [HKEY_CLASSES_ROOT\Go.Code.Template] @="Go Code Template" ``` ### Go 單元測試(Unit Test)介紹: > > #### go test 工具說明 : > Golang 官方工具包提供單元測試功能透過,``go test`` 進行單元測試: > > > 1. 單元測試檔名必須以 ``*_test.go`` 結尾命名,和被測試檔案必須在同一個包(package)中,此檔名內容僅會在 ``go test`` 下執行。 > > 2. 單元測試函式必須是 ``Test`` 或是 ``Benchmark`` 作為函式開頭名稱後面第一字必需大寫 ex: **TestExample** 、**BenchmarkExample** 。 > > 3. 單元測試函式輸入參數型別必須 ``*testing.T`` 、 ``*testing.B`` > > > > ``go test`` 工具附加命令參數設定值: > > > ``-c`` : 不運行測試,將go test編譯成為可執行檔案(二進位文件)。 > > > > ``-i`` : 不運行測試,安裝測試包依賴的package。 > > > > ``-v`` : 測試過程顯示列表所有函式(通過/不通過)。 > > > > ``-short`` : 縮短運行時間較長的測試項目。 > > > > ``-args "-TT"`` : 測試時置入命令參數 **-TT** (詳細參考flag.Args) > > > > ``-timeout 1h`` : 如果測試用例運行時間超過 **1小時**,則拋出panic。 > > > > ``-run=funcname`` : 僅測試函式包含名稱 **funcname** 。(預設值 ``.``,表示全部測試) > > > > ``-bench=funcname`` : 僅效能測試函式包含名稱 **funcname** 。(預設值 ``.``,表示全測試) > > > > ``-benchmem`` : 設置效能測試的時顯示記憶體使用資訊。 > > > > ``-benchtime 10s`` : 設置效能測試運行的時間 **10秒** (預設值**1秒**) > > > > ``-parallel 4`` : 設定效能測試並行最大CPU核心數為 **4** (預設值GOMAXPROCS) > > > > ``-cpu 1,2,3,4`` : 效能測試會依序由 **1~4** CPU核心數測試。(預設值為GOMAXPROCS) > > > > ``-cpuprofile cpu.out`` : 將測試過程CPU使用量紀錄儲存至 **cpu.out** > > > > ``-memprofile mem.out`` : 將測試過程記憶體使用量紀錄儲存至 **mem.out** > > > > ``-blockprofile block.out`` : 將測試過程中goroutine阻塞分析紀錄儲存至 **block.out** > > > > ``-blockprofilerate 2`` : 設置goroutine阻塞時候紀錄間隔時間為 **2納秒** (預設值**1納秒**) > > > #### 單元測試關鍵點 : > > 測試資料構造時要考慮這樣幾個方面: > >**正常輸入**: 驗證函式的正常邏輯是否通過 > >**邊界輸入**: 驗證在極端情況下的輸入,函式是否在有相應的容錯處理 > >**非法輸入**: 對於一些非正常輸入,看函式是否引起函式的奔潰和資料洩露等問題 > >**白盒覆蓋**: 覆蓋到函式的所有程式碼,語句覆蓋、條件覆蓋、分支覆蓋、分支/條件覆蓋、條件組合覆蓋。 > > 編寫原則與成本,效率權衡 : > > > 1. 優先編寫核心元件和邏輯模組的測試用例。 > > 2. 邏輯類似的元件如果存在多個,優先編寫其中一種邏輯元件的測試用例。 > > 3. 發現Bug時一定先編寫測試用例進行Debug(保持更新測試用例)。 > > 4. 測試使用者應該獨立一個檔案對應一個,不同的測試用例之間不要互相依賴。 > > > 原始資料出處 : https://www.itread01.com/hkpqhkxx.html ### Go 單元測試範例 - 函式輸入與期望結果對比: > ```go= > //Basic_Unit_Testing1\Basic_Unit_Testing_Example1.go > package Basic_Unit_Testing_Example1 > func fc_AddInt(vi_inputA, vi_inputB int) int { > return vi_inputA + vi_inputB > } > ``` > > ```go= > //Basic_Unit_Testing1\Basic_Unit_Testing_Example1_test.go > package Basic_Unit_Testing_Example1 > > import ( > "fmt" > "testing" > ) > > func Test_fc_AddInt(testT *testing.T) { > > var vs_theTestPanic string > defer func() { > if err_recover := recover(); err_recover != nil { > testT.Fatalf("測試過程發生panic,本測項中止 -「%v」(%v)", vs_theTestPanic, err_recover) > } > }() > > var stsl_Testers = []struct { > add1 int > add2 int > want int > }{ > {1, 1, 2}, > {2, 0, 2}, > {0, 2, 2}, > {9223372036854775807, -1, 9223372036854775806}, > {9223372036854775806, 1, 9223372036854775807}, > {9223372036854775807, 9223372036854775807, 0}, //overflows > {-1, -1, -2}, > } > > for vi_TestIndex, st_TestObject := range stsl_Testers { > vs_theTestPanic = fmt.Sprintf("stsl_Testers[%v] %v", vi_TestIndex, st_TestObject) > theTestResult := fc_AddInt(st_TestObject.add1, st_TestObject.add2) > if theTestResult == st_TestObject.want { > testT.Logf("項目測試正確 %v+%v=%v(%v)", st_TestObject.add1, st_TestObject.add2, st_TestObject.want, theTestResult) > } else { > testT.Errorf("項目測試[錯誤] %v+%v=%v(錯誤的結果:%v)", st_TestObject.add1, st_TestObject.add2, st_TestObject.want, theTestResult) > } > } > } > ``` > ```sass= > d:\單元測試\Basic_Unit_Testing1>go test -v > === RUN Test_fc_AddInt > --- FAIL: Test_fc_AddInt (0.00s) > Basic_Unit_Testing_Example1_test.go:35: 項目測試正確 1+1=2(2) > Basic_Unit_Testing_Example1_test.go:35: 項目測試正確 2+0=2(2) > Basic_Unit_Testing_Example1_test.go:35: 項目測試正確 0+2=2(2) > Basic_Unit_Testing_Example1_test.go:35: 項目測試正確 9223372036854775807+-1=9223372036854775806(9223372036854775806) > Basic_Unit_Testing_Example1_test.go:35: 項目測試正確 9223372036854775806+1=9223372036854775807(9223372036854775807) > Basic_Unit_Testing_Example1_test.go:37: 項目測試[錯誤] 9223372036854775807+9223372036854775807=0(錯誤的結果:-2) > Basic_Unit_Testing_Example1_test.go:35: 項目測試正確 -1+-1=-2(-2) > FAIL > exit status 1 > FAIL Lesson4/單元測試/Basic_Unit_Testing1 0.026s > ``` ### Go 單元測試範例 - 函式輸入與錯誤回報: > ```go= > //Basic_Unit_Testing2\Basic_Unit_Testing_Example2.go > package Basic_Unit_Testing_Example2 > import ( > "errors" > ) > > func fc_DivInt(vi_inputA, vi_inputB int) int { > return vi_inputA / vi_inputB > } > > func fc_DivIntMod(vi_inputA, vi_inputB int) (int, error) { > if vi_inputB == 0 { > return 0, errors.New("除數不得為0") > } > return vi_inputA / vi_inputB, nil > } > > ``` > > ```go= > //Basic_Unit_Testing2\Basic_Unit_Testing_Example2_test.go > package Basic_Unit_Testing_Example2 > > import ( > "errors" > "fmt" > "testing" > ) > > func Test_fc_DivIntMod(testT *testing.T) { > > var vs_theTestPanic string > defer func() { > if err_recover := recover(); err_recover != nil { > testT.Fatalf("測試過程發生panic,本測項中止 -「%v」(%v)", vs_theTestPanic, err_recover) > } > }() > > type ty_TestIndex struct { > dividend int > divisor int > want1 int > want2 error > } > > var stsl_Testers = []ty_TestIndex{ > {1, 1, 1, nil}, > {10, 2, 5, nil}, > {0, 2, 0, nil}, > {9223372036854775807, 1, 9223372036854775807, nil}, > {9223372036854775806, 3, 3074457345618258602, nil}, > {9223372036854775807, 4611686018427387903, 2, nil}, > {9223372036854775807, 0, 0, errors.New("除數不得為0")}, //除零預期錯誤 > {-1, 1, -1, nil}, > } > > for vi_TestIndex, st_TestObject := range stsl_Testers { > vs_theTestPanic = fmt.Sprintf("stsl_Testers[%v] %v", vi_TestIndex, st_TestObject) > theTestResult1, theTestResult2 := fc_DivIntMod(st_TestObject.dividend, st_TestObject.divisor) > > if theTestResult2 == nil { > theTestResult2 = errors.New("nil") > } > if st_TestObject.want2 == nil { > st_TestObject.want2 = errors.New("nil") > } > > if theTestResult1 == st_TestObject.want1 && theTestResult2.Error() == st_TestObject.want2.Error() { > testT.Logf("項目測試正確 %v/%v=%v,%v(%v,%v)", st_TestObject.dividend, st_TestObject.divisor, st_TestObject.want1, st_TestObject.want2, theTestResult1, theTestResult2) > } else { > testT.Errorf("項目測試[錯誤] %v/%v=%v,%v(錯誤的結果:%v,%v)", st_TestObject.dividend, st_TestObject.divisor, st_TestObject.want1, st_TestObject.want2, theTestResult1, theTestResult2) > } > } > > } > ``` > > ```sass= > d:\單元測試\Basic_Unit_Testing2>go test -v > === RUN Test_fc_DivIntMod > --- PASS: Test_fc_DivIntMod (0.00s) > Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 1/1=1,nil(1,nil) > Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 10/2=5,nil(5,nil) > Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 0/2=0,nil(0,nil) > Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 9223372036854775807/1=9223372036854775807,nil(9223372036854775807,nil) > Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 9223372036854775806/3=3074457345618258602,nil(3074457345618258602,nil) > Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 9223372036854775807/4611686018427387903=2,nil(2,nil) > Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 9223372036854775807/0=0,除數不得為0(0,除數不得為0) > Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 -1/1=-1,nil(-1,nil) > PASS > ok Lesson4/單元測試/Basic_Unit_Testing2 0.025s > ``` ### Go 單元測試範例 - 雙函式結果對比(隨機輸入): > ```go= > //Basic_Unit_Testing3\Basic_Unit_Testing_Example3.go > package Basic_Unit_Testing_Example3 > > func fc_SumA(via_Input ...int) int { > var vi_sum int > for i := 0; i < len(via_Input); i++ { > vi_sum += via_Input[i] > } > return vi_sum > } > > func fc_SumB(vi_sum int, via_Input ...int) int { > for i := 0; i < len(via_Input); i++ { > vi_sum += via_Input[i] > } > return vi_sum > } > ``` > > ```go= > //Basic_Unit_Testing3\Basic_Unit_Testing_Example_test3.go > package Basic_Unit_Testing_Example3 > > import ( > "math/rand" > "testing" > "time" > ) > > > func Test_fc_SumAnB(testT *testing.T) { > > var vs_theTestPanic string > defer func() { > if err_recover := recover(); err_recover != nil { > testT.Fatalf("測試過程發生panic,本測項中止 -「%v」(%v)", vs_theTestPanic, err_recover) > } > }() > > theRandSeed := time.Now().UTC().UnixNano() > rand.Seed(theRandSeed) > var vi_RandInt int > var vi_Output_fc_SumA int > var vi_Output_fc_SumB int > > for index := 0; index < 10; index++ { > vi_RandInt = rand.Int() > vi_Output_fc_SumA = fc_SumA(vi_RandInt) > vi_Output_fc_SumB = fc_SumB(vi_RandInt) > if fc_SumA(vi_RandInt) == fc_SumB(vi_RandInt) { > testT.Logf("項目測試正確 %v=%v (亂數種子:%d,亂數int:%v)", vi_Output_fc_SumA, vi_Output_fc_SumB, theRandSeed, vi_RandInt) > } else { > testT.Errorf("項目測試[錯誤] %v=%v (亂數種子:%d,亂數int:%v)", vi_Output_fc_SumA, vi_Output_fc_SumB, theRandSeed, vi_RandInt) > } > } > } > > ``` > ```sass= > d:\單元測試\Basic_Unit_Testing3>go test -v > === RUN Test_fc_SumAnB > --- PASS: Test_fc_SumAnB (0.00s) > Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 128637770004810965=128637770004810965 (亂數種子:1570086382169605200,亂數int:128637770004810965) > Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 2710904496263871649=2710904496263871649 (亂數種子:1570086382169605200,亂數int:2710904496263871649) > Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 7459572758933604767=7459572758933604767 (亂數種子:1570086382169605200,亂數int:7459572758933604767) > Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 7058483080362729371=7058483080362729371 (亂數種子:1570086382169605200,亂數int:7058483080362729371) > Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 7049057841437937710=7049057841437937710 (亂數種子:1570086382169605200,亂數int:7049057841437937710) > Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 8952472848806917481=8952472848806917481 (亂數種子:1570086382169605200,亂數int:8952472848806917481) > Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 7580769296778865075=7580769296778865075 (亂數種子:1570086382169605200,亂數int:7580769296778865075) > Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 5973232751947046394=5973232751947046394 (亂數種子:1570086382169605200,亂數int:5973232751947046394) > Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 2797291425107336826=2797291425107336826 (亂數種子:1570086382169605200,亂數int:2797291425107336826) > Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 1338551253019334488=1338551253019334488 (亂數種子:1570086382169605200,亂數int:1338551253019334488) > PASS > ok Lesson4/單元測試/Basic_Unit_Testing3 0.028s > ``` ### Go 效能測試範例 - (go test -bench=): > > ```go= > //d:\效能測試\Basic_Benchmark.go > package Basic_Benchmark > import "fmt" > func fc_SprintInt(vi_input int) string { > return fmt.Sprintf("%d", vi_input) > } > > ``` > > ```go= > //d:\效能測試\Basic_Benchmark_test.go > package Basic_Benchmark > import "testing" > func Benchmark_fc_SprintInt(benchB *testing.B) { > benchB.ResetTimer() > for i := 0; i < benchB.N; i++ { > fc_SprintInt(99999) > } > } > > ``` > go test -bench=. -cpu 1,2,3,4 -cpuprofile cpu.out -memprofile mem.out -blockprofile block.out > > ```sass= > d:\效能測試>go test -bench=. -cpu 1,2,3,4 -cpuprofile cpu.out -memprofile mem.out -blockprofile block.out > go test: missing argument for flag blockprofile > run "go help test" or "go help testflag" for more information > > d:\效能測試>go test -bench=. -cpu 1,2,3,4 -cpuprofile cpu.out -memprofile mem.out -blockprofile block.out > goos: windows > goarch: amd64 > pkg: Lesson4/效能測試 > Benchmark_fc_SprintInt 10000000 194 ns/op > Benchmark_fc_SprintInt-2 10000000 163 ns/op > Benchmark_fc_SprintInt-3 10000000 159 ns/op > Benchmark_fc_SprintInt-4 10000000 139 ns/op > PASS > ok Lesson4/效能測試 7.583s > > d:\效能測試>go tool pprof -text -nodecount=10 cpu.out > Type: cpu > Time: Sep 3, 2019 at 5:35pm (CST) > Duration: 7.45s, Total samples = 7300ms (97.99%) > Showing nodes accounting for 4490ms, 61.51% of 7300ms total > Dropped 46 nodes (cum <= 36.50ms) > Showing top 10 nodes out of 52 > flat flat% sum% cum cum% > 830ms 11.37% 11.37% 1650ms 22.60% runtime.mallocgc > 800ms 10.96% 22.33% 1470ms 20.14% fmt.(*fmt).fmtInteger > 580ms 7.95% 30.27% 2600ms 35.62% fmt.(*pp).doPrintf > 380ms 5.21% 35.48% 2020ms 27.67% fmt.(*pp).printArg > 350ms 4.79% 40.27% 640ms 8.77% sync.(*Pool).Get > 350ms 4.79% 45.07% 630ms 8.63% sync.(*Pool).Put > 330ms 4.52% 49.59% 1430ms 19.59% runtime.slicebytetostring > 290ms 3.97% 53.56% 670ms 9.18% fmt.(*fmt).pad > 290ms 3.97% 57.53% 6140ms 84.11% fmt.Sprintf > 290ms 3.97% 61.51% 290ms 3.97% runtime.memmove > > d:\效能測試>go tool pprof -text -nodecount=10 mem.out > Type: alloc_space > Time: Sep 3, 2019 at 5:35pm (CST) > Showing nodes accounting for 637.51MB, 99.50% of 640.68MB total > Dropped 17 nodes (cum <= 3.20MB) > flat flat% sum% cum cum% > 371.51MB 57.99% 57.99% 372.01MB 58.06% fmt.Sprintf > 266MB 41.52% 99.50% 638.01MB 99.58% Lesson4/%e6%95%88%e8%83%bd%e6%b8%ac%e8%a9%a6.fc_SprintInt > 0 0% 99.50% 638.01MB 99.58% Lesson4/%e6%95%88%e8%83%bd%e6%b8%ac%e8%a9%a6.Benchmark_fc_SprintInt > 0 0% 99.50% 638.01MB 99.58% testing.(*B).launch > 0 0% 99.50% 638.01MB 99.58% testing.(*B).runN > > d:\效能測試>go tool pprof -text -nodecount=10 block.out > Type: delay > Time: Sep 3, 2019 at 5:35pm (CST) > Showing nodes accounting for 7466.18ms, 100% of 7466.19ms total > Dropped 5 nodes (cum <= 37.33ms) > Showing top 10 nodes out of 17 > flat flat% sum% cum cum% > 7466.18ms 100% 100% 7466.18ms 100% runtime.chanrecv1 > 0 0% 100% 7466.19ms 100% main.main > 0 0% 100% 7466.19ms 100% runtime.main > 0 0% 100% 153.33ms 2.05% runtime/pprof.StopCPUProfile > 0 0% 100% 153.33ms 2.05% sync.(*Once).Do > 0 0% 100% 7312.85ms 97.95% testing.(*B).Run > 0 0% 100% 7311.72ms 97.93% testing.(*B).doBench > 0 0% 100% 7312.62ms 97.94% testing.(*B).run > 0 0% 100% 7312.85ms 97.95% testing.(*B).runN > 0 0% 100% 7466.19ms 100% testing.(*M).Run > > ``` ### Go 涵蓋率測試範例 - (go tool cover): > ```go= > // 涵蓋率測試/Cover_Testing_Example.go > package Cover_Testing_Example > func fc_AddInt(vi_inputA, vi_inputB int) int { > return vi_inputA + vi_inputB > } > > func fc_SubInt(vi_inputA, vi_inputB int) int { > return vi_inputA - vi_inputB > } > > func fc_SumA(via_Input ...int) int { > var vi_sum int > for i := 0; i < len(via_Input); i++ { > vi_sum += via_Input[i] > } > return vi_sum > } > > func fc_SumB(vi_sum int, via_Input ...int) int { > for i := 0; i < len(via_Input); i++ { > vi_sum += via_Input[i] > } > return vi_sum > } > ``` > > ```go= > // 涵蓋率測試/Cover_Testing_Example_test.go > package Cover_Testing_Example > import ( > "fmt" > "math/rand" > "testing" > "time" > ) > > func Test_fc_AddInt(testT *testing.T) { > > var vs_theTestPanic string > defer func() { > if err_recover := recover(); err_recover != nil { > testT.Fatalf("測試過程發生panic,本測項中止 -「%v」(%v)", vs_theTestPanic, err_recover) > } > }() > > var stsl_Testers = []struct { > add1 int > add2 int > want int > }{ > {1, 1, 2}, > {2, 0, 2}, > {0, 2, 2}, > {9223372036854775807, -1, 9223372036854775806}, > {9223372036854775806, 1, 9223372036854775807}, > {9223372036854775807, 9223372036854775807, 0}, //overflows > {-1, -1, -2}, > } > > for vi_TestIndex, st_TestObject := range stsl_Testers { > vs_theTestPanic = fmt.Sprintf("stsl_Testers[%v] %v", vi_TestIndex, st_TestObject) > theTestResult := fc_AddInt(st_TestObject.add1, st_TestObject.add2) > if theTestResult == st_TestObject.want { > testT.Logf("項目測試正確 %v+%v=%v(%v)", st_TestObject.add1, st_TestObject.add2, st_TestObject.want, theTestResult) > } else { > testT.Errorf("項目測試[錯誤] %v+%v=%v(錯誤的結果:%v)", st_TestObject.add1, st_TestObject.add2, st_TestObject.want, theTestResult) > } > } > } > > func Test_fc_SumAnB(testT *testing.T) { > > var vs_theTestPanic string > defer func() { > if err_recover := recover(); err_recover != nil { > testT.Fatalf("測試過程發生panic,本測項中止 -「%v」(%v)", vs_theTestPanic, err_recover) > } > }() > > theRandSeed := time.Now().UTC().UnixNano() > rand.Seed(theRandSeed) > var vi_RandInt int > var vi_Output_fc_SumA int > var vi_Output_fc_SumB int > > for index := 0; index < 10; index++ { > vi_RandInt = rand.Int() > vi_Output_fc_SumA = fc_SumA(vi_RandInt) > vi_Output_fc_SumB = fc_SumB(vi_RandInt) > if fc_SumA(vi_RandInt) == fc_SumB(vi_RandInt) { > testT.Logf("項目測試正確 %v=%v (亂數種子:%d,亂數int:%v)", vi_Output_fc_SumA, vi_Output_fc_SumB, theRandSeed, vi_RandInt) > } else { > testT.Errorf("項目測試[錯誤] %v=%v (亂數種子:%d,亂數int:%v)", vi_Output_fc_SumA, vi_Output_fc_SumB, theRandSeed, vi_RandInt) > } > } > } > > ``` > > ```sass= > PS D:\涵蓋率測試> go test -v -cover -coverprofile cover.out > === RUN Test_fc_AddInt > --- FAIL: Test_fc_AddInt (0.00s) > Cover_Testing_Example_test.go:37: 項目測試正確 1+1=2(2) > Cover_Testing_Example_test.go:37: 項目測試正確 2+0=2(2) > Cover_Testing_Example_test.go:37: 項目測試正確 0+2=2(2) > Cover_Testing_Example_test.go:37: 項目測試正確 9223372036854775807+-1=9223372036854775806(9223372036854775806) > Cover_Testing_Example_test.go:37: 項目測試正確 9223372036854775806+1=9223372036854775807(9223372036854775807) > Cover_Testing_Example_test.go:39: 項目測試[錯誤] 9223372036854775807+9223372036854775807=0(錯誤的結果:-2) > Cover_Testing_Example_test.go:37: 項目測試正確 -1+-1=-2(-2) > === RUN Test_fc_SumAnB > --- PASS: Test_fc_SumAnB (0.00s) > Cover_Testing_Example_test.go:64: 項目測試正確 1054791156209780183=1054791156209780183 (亂數種子:1570164062516555300,亂數int:1054791156209780183) > Cover_Testing_Example_test.go:64: 項目測試正確 1572036677946546427=1572036677946546427 (亂數種子:1570164062516555300,亂數int:1572036677946546427) > Cover_Testing_Example_test.go:64: 項目測試正確 4043804078525964286=4043804078525964286 (亂數種子:1570164062516555300,亂數int:4043804078525964286) > Cover_Testing_Example_test.go:64: 項目測試正確 4490900911252265608=4490900911252265608 (亂數種子:1570164062516555300,亂數int:4490900911252265608) > Cover_Testing_Example_test.go:64: 項目測試正確 9189757511242968573=9189757511242968573 (亂數種子:1570164062516555300,亂數int:9189757511242968573) > Cover_Testing_Example_test.go:64: 項目測試正確 8466299651324370872=8466299651324370872 (亂數種子:1570164062516555300,亂數int:8466299651324370872) > Cover_Testing_Example_test.go:64: 項目測試正確 600841189896519269=600841189896519269 (亂數種子:1570164062516555300,亂數int:600841189896519269) > Cover_Testing_Example_test.go:64: 項目測試正確 8783876916636026197=8783876916636026197 (亂數種子:1570164062516555300,亂數int:8783876916636026197) > Cover_Testing_Example_test.go:64: 項目測試正確 4035231185535482081=4035231185535482081 (亂數種子:1570164062516555300,亂數int:4035231185535482081) > Cover_Testing_Example_test.go:64: 項目測試正確 4089254982128445097=4089254982128445097 (亂數種子:1570164062516555300,亂數int:4089254982128445097) > FAIL > coverage: 77.8% of statements > exit status 1 > FAIL Lesson4/涵蓋率測試 0.029s > ``` > **go tool cover** 工具指令獲得到測試涵蓋率 **77.8%** ,可藉由下方指令分析測試過程中涵蓋的程式碼 **Cover_Testing_Example.go** : > > ```sass= > PS D:\涵蓋率測試> go tool cover -html cover.out > ``` > ![image alt](https://lh3.googleusercontent.com/xWF5qZCGn-4-CEi_I2WoXnr4pWKHtUa8hIImcQ2ccXH-2xdGnGJviL3N_7srGRAFKpyZ2uTN3dnJeDdgQMgBx3scTIC4hnw-_HdhRSX3q0AeJKvB3BCbBiQfhNSzsbL_1yl6ML_Hu-yyvC46HlKf1EiHw4LHxQlIU7EGchH2f8bajHo0oiHMMmQYcdjt1zxBb5lP2_gneppxjpGqsgtKoZzHDpaS91r-A8-4c6zMipGYWeUxOy77ssO9QkVX_v-8zUCsm_Y0_WuvKex3_G66Uwr7K1WGydBW_PY0BU0jFmzmE3lMpeOZxs29NeJgKbk98BMEQ1OW323Wpl2SNnpSiISOSYhtgeeksUaD8xD2BWIHCW3WzfekzSO2fran24nbLiJZEmhDNUA1pDX4iA48G0L-iCLXuHJVykt-SoVqhHyG6L3WPWxyk5y4Tt7uC-SXohsrWfl9bhaZNkva2zJc8BgNZLjMoz15yfvn1r12RbCWkClr_P1HEmcRne-FO2TQUuthvQIHf_AjgoFOzA3c5NSYkUjDArZJHNeH-ozg6Fj8KCZEuKaxYgcxlc-k1GMc34VVr5OO8a1OaErCrLJ4FMnhygjpA3m3ZlJWS25yO7VC_6BK0kGRutju5DiPwFO0KPjLGUwd4VPkoTdc7oRyEjZJSoB275XlnpCsue7-Vp-lWM1hGxLCcAHL=w676-h583-no "title") > * 紅色部分表示測試未涵蓋到的程式碼 ---