最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang單元測(cè)試與斷言編寫(xiě)流程詳解

 更新時(shí)間:2022年12月14日 08:55:02   作者:夢(mèng)想畫(huà)家  
這篇文章主要介紹了Golang單元測(cè)試與斷言編寫(xiě)流程,單元測(cè)試也是一個(gè)很重要的事情。單元測(cè)試是指在開(kāi)發(fā)中,對(duì)一個(gè)函數(shù)或模塊的測(cè)試。其強(qiáng)調(diào)的是對(duì)單元進(jìn)行測(cè)試

Go 在testing包中內(nèi)置測(cè)試命令go test,提供了最小化但完整的測(cè)試體驗(yàn)。標(biāo)準(zhǔn)工具鏈還包括基準(zhǔn)測(cè)試和基于代碼覆蓋的語(yǔ)句,類(lèi)似于NCover(.NET)或Istanbul(Node.js)。本文詳細(xì)講解go編寫(xiě)單元測(cè)試的過(guò)程,包括性能測(cè)試及測(cè)試工具的使用,另外還介紹第三方斷言庫(kù)的使用。

編寫(xiě)單元測(cè)試

go中單元測(cè)試與語(yǔ)言中其他特性一樣具有獨(dú)特見(jiàn)解,如格式化、命名規(guī)范。語(yǔ)法有意避免使用斷言,并將檢查值和行為的責(zé)任留給開(kāi)發(fā)人員。

下面通過(guò)示例進(jìn)行說(shuō)明。我們編寫(xiě)Sum函數(shù),實(shí)現(xiàn)數(shù)據(jù)求和功能:

package main
func Sum(x int, y int) int {
    return x + y
}
func main() {
    Sum(5, 5)
}

然后在單獨(dú)的文件中編寫(xiě)測(cè)試代碼,測(cè)試文件可以在相同包中,或不同包中。測(cè)試代碼如下:

package main
import "testing"
func TestSum(t *testing.T) {
    total := Sum(5, 5)
    if total != 10 {
       t.Errorf("Sum was incorrect, got: %d, want: %d.", total, 10)
    }
}

Golang測(cè)試功能特性:

  • 僅需要一個(gè)參數(shù),必須是t *testing.T
  • 以Test開(kāi)頭,接著單詞或詞組,采用駱駝命名法,舉例:TestValidateClient
  • 調(diào)用t.Errort.Fail 表明失敗(當(dāng)然也可以使用t.Errorf提供更多細(xì)節(jié))
  • t.Log用于提供非失敗的debug信息輸出
  • 測(cè)試文件必須命名為something_test.go ,舉例: addition_test.go

批量測(cè)試(test tables)

test tables概念是一組(slice數(shù)組)測(cè)試輸入、輸出值:

func TestSum(t *testing.T) {
	tables := []struct {
		x int
		y int
		n int
	}{
		{1, 1, 2},
		{1, 2, 3},
		{2, 2, 4},
		{5, 2, 7},
	}
	for _, table := range tables {
		total := Sum(table.x, table.y)
		if total != table.n {
			t.Errorf("Sum of (%d+%d) was incorrect, got: %d, want: %d.", table.x, table.y, total, table.n)
		}
	}
}

如果需要觸發(fā)錯(cuò)誤,我們可以修改測(cè)試數(shù)據(jù),或修改代碼。這里修改代碼return x*y, 輸出如下:

=== RUN   TestSum
    math_test.go:61: Sum of (1+1) was incorrect, got: 1, want: 2.
    math_test.go:61: Sum of (1+2) was incorrect, got: 2, want: 3.
    math_test.go:61: Sum of (5+2) was incorrect, got: 10, want: 7.
--- FAIL: TestSum (0.00s)

FAIL

單元測(cè)試不僅要正向測(cè)試,更要進(jìn)行負(fù)向測(cè)試。

執(zhí)行測(cè)試

執(zhí)行測(cè)試有兩種方法:

在相同目錄下運(yùn)行命令:

go test 

這會(huì)匹配任何packagename_test.go的任何文件。

使用完整的包名

go test

現(xiàn)在我們可以運(yùn)行單元測(cè)試了,還可以增加參數(shù)go test -v獲得更多輸出結(jié)果。

單元測(cè)試和集成測(cè)試的區(qū)別在于單元測(cè)試通常不依賴(lài)網(wǎng)絡(luò)、磁盤(pán)等,僅測(cè)試一個(gè)功能,如函數(shù)。

另外還可以查看測(cè)試語(yǔ)句覆蓋率,增加-cover選項(xiàng)。但高覆蓋率未必總是比低覆蓋率好,關(guān)鍵是功能正確。

如果執(zhí)行下面命令,可以生成html文件,以可視化方式查看覆蓋率:

go test -cover -coverprofile=c.out
go tool cover -html=c.out -o coverage.html 

性能測(cè)試

benchmark 測(cè)試衡量程序性能,可以比較不同實(shí)現(xiàn)差異,理解影響性能原因。

go性能測(cè)試也有一定規(guī)范:

性能測(cè)試函數(shù)名必須以Benchmark開(kāi)頭,之后大寫(xiě)字母或下劃線。因此BenchmarkFunctionName()Benchmark_functionName()都是合法的,但Benchmarkfunctionname()不合法。這與單元測(cè)試以Test開(kāi)頭規(guī)則一致。

雖然可以把單元測(cè)試和性能測(cè)試代碼放在相同文件,但盡量避免,文件命名仍然以_test.go結(jié)尾。如單元測(cè)試文件為simple_test.go,性能測(cè)試為benchmark_test.go。

下面通過(guò)示例進(jìn)行說(shuō)明,首先定義函數(shù):

func IsPalindrome(s string) bool {
	for i := range s {
		if s[i] != s[len(s)-1-i] {
			return false
		}
	}
	return true
}

先編寫(xiě)單元測(cè)試,分別編寫(xiě)正向測(cè)試和負(fù)向測(cè)試:

func TestPalindrome(t *testing.T) {
	if !IsPalindrome("detartrated") {
		t.Error(`IsPalindrome("detartrated") = false`)
	}
	if !IsPalindrome("kayak") {
		t.Error(`IsPalindrome("kayak") = false`)
	}
}
func TestNonPalindrome(t *testing.T) {
	if IsPalindrome("palindrome") {
		t.Error(`IsPalindrome("palindrome") = true`)
	}
}

接著編寫(xiě)基準(zhǔn)測(cè)試(性能測(cè)試):

func BenchmarkIsPalindrome(b *testing.B) {
	for i := 0; i < b.N; i++ {
		IsPalindrome("A man, a plan, a canal: Panama")
	}
}

執(zhí)行性能測(cè)試

go test -bench . -run notest

-bench參數(shù)執(zhí)行所有性能測(cè)試,也可以使用正則代替. ,默認(rèn)情況單元測(cè)試也會(huì)執(zhí)行,因?yàn)閱卧獪y(cè)試種有錯(cuò)誤,可以通過(guò)-run 參數(shù)指定值不匹配任何測(cè)試函數(shù)名稱(chēng),從而僅執(zhí)行性能測(cè)試。

我們還可以指定其他參數(shù),下面示例指定count為2,表示對(duì)現(xiàn)有測(cè)試執(zhí)行兩次分析。設(shè)置GOMAXPROCS為4,查看測(cè)試的內(nèi)存情況,執(zhí)行這些請(qǐng)求時(shí)間為2秒,而不是默認(rèn)的1秒執(zhí)行時(shí)間。命令如下:

$ go test -bench=. -benchtime 2s -count 2 -benchmem -cpu 4 -run notest
goos: windows
goarch: amd64
pkg: gin01/math
cpu: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
BenchmarkIsPalindrome
BenchmarkIsPalindrome-4         1000000000               1.349 ns/op           0 B/op          0 allocs/op
BenchmarkIsPalindrome-4         1000000000               1.356 ns/op           0 B/op          0 allocs/op
PASS
ok      gin01/math      3.234s

  • -4 : 執(zhí)行測(cè)試的GOMAXPROCS數(shù)量
  • 1000000000 :為收集必要數(shù)據(jù)而運(yùn)行的次數(shù)
  • 1.349 ns/op :測(cè)試每個(gè)循環(huán)執(zhí)行速度
  • PASS:指示基準(zhǔn)測(cè)試運(yùn)行的結(jié)束狀態(tài)。

配置計(jì)算時(shí)間

定義函數(shù):

func sortAndTotal(vals []int) (sorted []int, total int) {
	sorted = make([]int, len(vals))
	copy(sorted, vals)
	sort.Ints(sorted)
	for _, val := range sorted {
		total += val
		total++
	}
	return
}

對(duì)應(yīng)單元測(cè)試如下:

func BenchmarkSort(b *testing.B) {
	rand.Seed(time.Now().UnixNano())
	size := 250
	data := make([]int, size)
	for i := 0; i < b.N; i++ {
		for j := 0; j < size; j++ {
			data[j] = rand.Int()
		}
		sortAndTotal(data)
	}
}

每次執(zhí)行前,隨機(jī)生成數(shù)組,造成性能測(cè)試不準(zhǔn)確。

為了更準(zhǔn)確計(jì)算時(shí)間,可以使用下面函數(shù)進(jìn)行控制:

-StopTimer() : 停止計(jì)時(shí)器方法.

-StartTimer() : 啟動(dòng)計(jì)時(shí)器方法.

-ResetTimer() : 重置計(jì)時(shí)器方法.

最終性能測(cè)試函數(shù)如下:

func BenchmarkSort(b *testing.B) {
	rand.Seed(time.Now().UnixNano())
	size := 250
	data := make([]int, size)
    // 開(kāi)始前先重置
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
        // 準(zhǔn)備數(shù)據(jù)時(shí)停止計(jì)時(shí)
		b.StopTimer()
		for j := 0; j < size; j++ {
			data[j] = rand.Int()
		}
        // 調(diào)用函數(shù)時(shí)啟動(dòng)計(jì)時(shí)
		b.StartTimer()
		sortAndTotal(data)
	}
}

斷言(assertion)

go測(cè)試沒(méi)有提供斷言,對(duì)于java開(kāi)發(fā)人員來(lái)說(shuō)有點(diǎn)不習(xí)慣。這里介紹第三方庫(kù) github.com/stretchr/testify/assert.它提供了一組易理解的測(cè)試工具。

assert示例

assert子庫(kù)提供了便捷的斷言函數(shù),可以大大簡(jiǎn)化測(cè)試代碼的編寫(xiě)??偟膩?lái)說(shuō),它將之前需要判斷 + 信息輸出的模式:

import (
  "testing"
  "github.com/stretchr/testify/assert"
)
func TestSomething(t *testing.T) {
  var a string = "Hello"
  var b string = "Hello"
  assert.Equal(t, a, b, "The two words should be the same.")
}

觀察到上面的斷言都是以TestingT為第一個(gè)參數(shù),需要大量使用時(shí)比較麻煩。testify提供了一種方便的方式。先以testing.T創(chuàng)建一個(gè)Assertions對(duì)象,Assertions定義了前面所有的斷言方法,只是不需要再傳入TestingT參數(shù)了。

func TestEqual(t *testing.T) {
  assertions := assert.New(t)
  assertion.Equal(a, b, "")
  // ...
}

TestingT類(lèi)型定義如下,就是對(duì)*testing.T做了一個(gè)簡(jiǎn)單的包裝:

// TestingT is an interface wrapper around *testing.T
type TestingT interface {
	Errorf(format string, args ...interface{})
}

下面引用官網(wǎng)的一個(gè)示例。

首先定義功能函數(shù)Addition:

func Addition(a, b int) int {
	return a + b
}

測(cè)試代碼:

import (
	"github.com/stretchr/testify/assert"
	"testing"
)
// 定義比較函數(shù)類(lèi)型,方便后面批量準(zhǔn)備測(cè)試數(shù)據(jù)
type ComparisonAssertionFunc func(assert.TestingT, interface{}, interface{}, ...interface{}) bool
// 測(cè)試參數(shù)類(lèi)型
type args struct {
	x int
	y int
}
func TestAddition(t *testing.T) {
	tests := []struct {
		name      string
		args      args
		expect    int
		assertion ComparisonAssertionFunc
	}{
		{"2+2=4", args{2, 2}, 4, assert.Equal},
		{"2+2!=5", args{2, 2}, 5, assert.NotEqual},
		{"2+3==5", args{2, 3}, 5, assert.Exactly},
	}
	for _, tt := range tests {
        // 動(dòng)態(tài)執(zhí)行斷言函數(shù)
		t.Run(tt.name, func(t *testing.T) {
			tt.assertion(t, tt.expect, Addition(tt.args.x, tt.args.y))
		})
	}
	assert.Equal(t, 2, Addition(1, 1), "sum result is equal")
}

到此這篇關(guān)于Golang單元測(cè)試與斷言編寫(xiě)流程詳解的文章就介紹到這了,更多相關(guān)Go單元測(cè)試內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang 刪除切片的某個(gè)元素及剔除切片內(nèi)的零值方式

    golang 刪除切片的某個(gè)元素及剔除切片內(nèi)的零值方式

    這篇文章主要介紹了golang 刪除切片的某個(gè)元素及剔除切片內(nèi)的零值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • Golang 讀取并解析SQL文件的實(shí)現(xiàn)方法

    Golang 讀取并解析SQL文件的實(shí)現(xiàn)方法

    本文介紹了如何使用Go語(yǔ)言編寫(xiě)一個(gè)簡(jiǎn)單的函數(shù),用于讀取并解析SQL文件,通過(guò)一個(gè)函數(shù),我們可以輕松地將SQL文件中的語(yǔ)句提取出來(lái),進(jìn)行后續(xù)的操作,感興趣的朋友跟隨小編一起看看吧
    2024-12-12
  • Go項(xiàng)目分層下的最佳error處理方式分享

    Go項(xiàng)目分層下的最佳error處理方式分享

    這篇文章主要來(lái)和大家一起探討?Go?項(xiàng)目分層下的最佳?error?處理方式,準(zhǔn)備好了嗎?準(zhǔn)備一杯你最喜歡的飲料或茶,隨著本文一探究竟吧
    2023-06-06
  • golang sudog指的是什么

    golang sudog指的是什么

    sudog代表在等待隊(duì)列中的goroutine,比如channel發(fā)送接受,由于goroutine和同步對(duì)象的關(guān)系是多對(duì)多,因此需要sudog映射,本文重點(diǎn)介紹golang sudog指的是什么,感興趣的朋友一起看看吧
    2024-02-02
  • Go語(yǔ)言使用對(duì)稱(chēng)加密的示例詳解

    Go語(yǔ)言使用對(duì)稱(chēng)加密的示例詳解

    在項(xiàng)目開(kāi)發(fā)中,我們經(jīng)常會(huì)遇到需要使用對(duì)稱(chēng)密鑰加密的場(chǎng)景,比如客戶端調(diào)用接口時(shí),參數(shù)包含手機(jī)號(hào)、身份證號(hào)或銀行卡號(hào)等。本文將詳細(xì)講解Go語(yǔ)言使用對(duì)稱(chēng)加密的方法,需要的可以參考一下
    2022-06-06
  • golang使用RSA加密和解密的實(shí)現(xiàn)示例

    golang使用RSA加密和解密的實(shí)現(xiàn)示例

    在Golang中RSA加密和解密是一個(gè)常見(jiàn)的操作,本文主要介紹了golang使用RSA加密和解密的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-03-03
  • Go語(yǔ)言crypto包創(chuàng)建自己的密碼加密工具實(shí)現(xiàn)示例

    Go語(yǔ)言crypto包創(chuàng)建自己的密碼加密工具實(shí)現(xiàn)示例

    Go語(yǔ)言借助它的簡(jiǎn)單性和強(qiáng)大的標(biāo)準(zhǔn)庫(kù),實(shí)現(xiàn)一個(gè)自己的密碼加密工具,本文將會(huì)結(jié)合代碼示例深入探討如何使用Go語(yǔ)言的crypto包來(lái)實(shí)現(xiàn)自己的加密工具
    2023-11-11
  • Go語(yǔ)言中的字符串處理方法示例詳解

    Go語(yǔ)言中的字符串處理方法示例詳解

    Go語(yǔ)言的字符串是使用UTF-8編碼的。UTF-8是Unicode的實(shí)現(xiàn)方式之一。這篇文章主要介紹了Go語(yǔ)言中的字符串處理方法,需要的朋友可以參考下
    2018-10-10
  • 使用Go語(yǔ)言編寫(xiě)一個(gè)簡(jiǎn)單的Web框架

    使用Go語(yǔ)言編寫(xiě)一個(gè)簡(jiǎn)單的Web框架

    Go語(yǔ)言(又稱(chēng)Golang)因其高效的性能和簡(jiǎn)潔的語(yǔ)法,在編寫(xiě)Web框架方面表現(xiàn)出色,下面將詳細(xì)介紹如何使用Go語(yǔ)言編寫(xiě)一個(gè)簡(jiǎn)單的Web框架,文中有詳細(xì)的代碼供大家參考,需要的朋友可以參考下
    2024-05-05
  • Golang 實(shí)現(xiàn)分片讀取http超大文件流和并發(fā)控制

    Golang 實(shí)現(xiàn)分片讀取http超大文件流和并發(fā)控制

    這篇文章主要介紹了Golang 實(shí)現(xiàn)分片讀取http超大文件流和并發(fā)控制,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12

最新評(píng)論

登封市| 托克逊县| 顺义区| 察隅县| 于都县| 绵竹市| 中卫市| 桦川县| 郎溪县| 丘北县| 长治市| 瑞安市| 奉贤区| 龙海市| 武平县| 舒城县| 苏尼特左旗| 伽师县| 扎囊县| 黄平县| 资兴市| 常宁市| 永城市| 舟山市| 顺平县| 松潘县| 株洲县| 常熟市| 景泰县| 武功县| 茌平县| 克山县| 榕江县| 天台县| 合作市| 大英县| 泽州县| 临武县| 桃园市| 开江县| 吴桥县|