欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go單元測試工具gomonkey的使用

 更新時間:2022年06月23日 10:11:34   作者:banjming  
本文主要介紹了Go單元測試工具gomonkey的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

Go 單元測試工具

測試分為4個層次

  • 單元測試:對代碼進(jìn)行測試
  • 集成測試:對一個服務(wù)的接口測試
  • 端到端測試(鏈路測試):從一個鏈路的入口輸入測試用例,驗證輸出的系統(tǒng)的結(jié)果
  • UI測試

常犯的錯誤:

  • 沒有斷言。沒有斷言的單測是沒有靈魂的。

單測的特征:

  • A:(Automatic,自動化):單元測試應(yīng)該是全自動執(zhí)行的,并且非交互式的
  • I:(Independent,獨立性):為了保證單元測試穩(wěn)定可靠且便于維護(hù),單元測試用例之間決不能互相調(diào)用,也不能依賴執(zhí)行的先后次序。
  • R:(Repeatable,可重復(fù)):單元測試通常會被放到持續(xù)集成中,每次有代碼 check in 時單元測試都會被執(zhí)行。

單測

代碼 bug 總是在所難免, 越早發(fā)現(xiàn)問題解決成本越低, 單測可以盡早的暴露錯誤。提高代碼之路,使得項目更高質(zhì)量的交付。 起碼有三個優(yōu)點:

  • 提高代碼質(zhì)量

編寫單測是自測的一部分,編寫新代碼時增加相應(yīng)的單測,可以幫助我們發(fā)現(xiàn)大部分的bug,有助于減少聯(lián)調(diào)時的調(diào)整,提高聯(lián)調(diào)效率。

  • 花更少的時間進(jìn)行功能測試

功能測試成本相對較高,因為經(jīng)常需要執(zhí)行一系列操作以驗證結(jié)果是否符合預(yù)期。如果問題如果發(fā)現(xiàn)了問題,溝通和復(fù)測往往要花費很多的時間。

  • 花更少的時間進(jìn)行回歸測試

回歸測試是為了避免在對應(yīng)用程序進(jìn)行更改時引入bug。測試人員不僅要測試他們的新特性,還要測試以前存在的特性,以驗證之前實現(xiàn)的特性是否仍然像預(yù)期的那樣運(yùn)行。 通過單元測試,可以在每次構(gòu)建之后,重新運(yùn)行整個測試流程,以確保新代碼不會破壞已有功能

  • 測試異常場景

一些異常的場景QA不好構(gòu)造,比如并發(fā)出款是否資金安全,事務(wù)異常相關(guān)測試等等。而問題經(jīng)常出現(xiàn)在這些異常的場景,可能引發(fā)線上問題甚至是事故。 而單元測試可通過mock的方式方便的模擬各種異常場景。

Go 單元測試工具

gomonkey

引入 gomonkey 有如下好處:

  • 隔離被測代碼
  • 加速執(zhí)行測試
  • 使執(zhí)行變得確定
  • 模擬特殊情況

功能列表

  • 支持為一個函數(shù)打一個樁
  • 支持為一個函數(shù)打一個特定的樁序列
  • 支持為一個成員方法打一個樁
  • 支持為一個成員方法打一個特定的樁序列
  • 支持為一個函數(shù)變量打一個樁
  • 支持為一個函數(shù)變量打一個特定的樁序列
  • 支持為一個接口打樁
  • 支持為一個接口打一個特定的樁序列
  • 支持為一個全局變量打一個樁

函數(shù)打樁, 對變量的 mock 實現(xiàn)原理跟 gostub 一樣都是通過 reflect 包實現(xiàn)的。除了 mock 變量,gomonkey 還可以直接 mock 導(dǎo)出函數(shù)/方法、mock 代碼所在包的非導(dǎo)出函數(shù)

Go monkey Permission Denied 解決方案:https://github.com/eisenxp/macos-golink-wrapper

mv $GOROOT/pkg/tool/darwin_amd64/link $GOROOT/pkg/tool/darwin_amd64/original_link
cp https://github.com/eisenxp/macos-golink-wrapper/link $GOROOT/pkg/tool/darwin_amd64/link

下載文件,然后再 cp

wget https://raw.githubusercontent.com/eisenxp/macos-golink-wrapper/main/link  

gomonkey 提供了如下 mock 方法:

  • ApplyGlobalVar(target, double interface{}):使用 reflect 包,將 target 的值修改為 double
  • ApplyFuncVar(target, double interface{}):檢查 target 是否為指針類型,與 double 函數(shù)聲明是否相同,最后調(diào)用 ApplyGlobalVar
  • ApplyFunc(target, double interface{}):修改 target 的機(jī)器指令,跳轉(zhuǎn)到 double 執(zhí)行
  • ApplyMethod(target reflect.Type, methodName string, double interface{}):修改 method 的機(jī)器指令,跳轉(zhuǎn)到 double 執(zhí)行
  • ApplyFuncSeq(target interface{}, outputs []OutputCell):修改 target 的機(jī)器指令,跳轉(zhuǎn)到 gomonkey 生成的一個函數(shù)執(zhí)行,每次調(diào)用會順序從 outputs 取出一個值返回
  • ApplyMethodSeq(target reflect.Type, methodName string, outputs []OutputCell):修改 target 的機(jī)器指令,跳轉(zhuǎn)到 gomonkey 生成的一個方法執(zhí)行,每次調(diào)用會順序從 outputs 取出一個值返回
  • ApplyFuncVarSeq(target interface{}, outputs []OutputCell):gomonkey 生成一個函數(shù)順序返回 outputs 中的值,調(diào)用 ApplyGlobalVar

gomonkey 打樁失敗的可能原因

  • gomonkey 不是并發(fā)安全的。如果有多協(xié)程并發(fā)對同一個目標(biāo)的打樁的情況,則需要將之前的協(xié)程先優(yōu)雅退出。
  • 打樁目標(biāo)為內(nèi)聯(lián)的函數(shù)或成員方法。可通過命令行參數(shù) -gcflags=-l (go1.10 版本之前)或-gcflags=all=-l(go1.10 版本及之后)關(guān)閉內(nèi)聯(lián)優(yōu)化。
  • gomonkey 對于私有成員方法的打樁失敗。go1.6 版本的反射機(jī)制支持私有成員方法的查詢,而 go1.7 及之后的版本卻不支持,所以當(dāng)用戶使用 go1.7 及之后的版本時,gomonkey 對于私有成員方法的打樁會觸發(fā)異常。

goconvey

為全局變量打一個樁

package unittest

import (
	"testing"

	"github.com/agiledragon/gomonkey"
	"github.com/smartystreets/goconvey/convey"
)

var num = 10 //全局變量

func TestApplyGlobalVar(t *testing.T) {
	convey.Convey("TestApplyGlobalVar", t, func() {
		convey.Convey("change", func() {
			patches := gomonkey.ApplyGlobalVar(&num, 150)
			defer patches.Reset()
			convey.So(num, convey.ShouldEqual, 150)
		})

		convey.Convey("recover", func() {
			convey.So(num, convey.ShouldEqual, 10)
		})
	})
}

執(zhí)行結(jié)果:

=== RUN   TestApplyGlobalVar
..
2 total assertions

--- PASS: TestApplyGlobalVar (0.00s)
PASS

為一個函數(shù)打樁

func networkCompute(a, b int) (int, error) {
	// do something in remote computer
	c := a + b

	return c, nil
}

func Compute(a, b int) (int, error) {
	sum, err := networkCompute(a, b)
	return sum, err
}

func TestFunc(t *testing.T) {
	// mock 了 networkCompute(),返回了計算結(jié)果2
	patches := gomonkey.ApplyFunc(networkCompute, func(a, b int) (int, error) {
		return 2, nil
	})

	defer patches.Reset()

	sum, err := Compute(1, 2)
	println("expected %v, got %v", 2, sum)
	if sum != 2 || err != nil {
		t.Errorf("expected %v, got %v", 2, sum)
	}
}

結(jié)果:

=== RUN   TestFunc
expected %v, got %v 2 3
    mock_func_test.go:91: expected 2, got 3
--- FAIL: TestFunc (0.00s)

FAIL

可以看到上面的結(jié)果,執(zhí)行時失敗的,mock 沒有成功。

有時會遇到mock失效的情況,這個問題一般是內(nèi)聯(lián)導(dǎo)致的。

什么是內(nèi)聯(lián)?

為了減少函數(shù)調(diào)用時的堆棧等開銷,對于簡短的函數(shù),會在編譯時,直接內(nèi)嵌調(diào)用的代碼。

我們禁用下內(nèi)聯(lián),然后執(zhí)行, go test -v -gcflags=-l mock_func_test.go

執(zhí)行結(jié)果:

=== RUN   TestFunc
expected %v, got %v 2 2
--- PASS: TestFunc (0.00s)
PASS

對于 go 1.10以下版本,可使用-gcflags=-l禁用內(nèi)聯(lián),對于go 1.10及以上版本,可以使用-gcflags=all=-l。但目前使用下來,都可以。 關(guān)于gcflags的用法,可以使用 go tool compile --help 查看 gcflags 各參數(shù)含義

到此這篇關(guān)于Go單元測試工具gomonkey的使用的文章就介紹到這了,更多相關(guān)Go gomonkey內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入理解Go gin框架中Context的Request和Writer對象

    深入理解Go gin框架中Context的Request和Writer對象

    這篇文章主要為大家詳細(xì)介紹了Go語言的gin框架中Context的Request和Writer對象,文中的示例代碼講解詳細(xì),對我們深入了解Go語言有一定的幫助,快跟隨小編一起學(xué)習(xí)一下吧
    2023-04-04
  • Web框架Gin中間件實現(xiàn)原理步驟解析

    Web框架Gin中間件實現(xiàn)原理步驟解析

    這篇文章主要為大家介紹了Web框架Gin中間件實現(xiàn)原理步驟解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • Go高級特性探究之穩(wěn)定排序詳解

    Go高級特性探究之穩(wěn)定排序詳解

    Go 語言提供了 sort 包,其中最常用的一種是 sort.Slice() 函數(shù),本篇文章將為大家介紹如何使用 sort.SliceStable() 對結(jié)構(gòu)體數(shù)組的某個字段進(jìn)行穩(wěn)定排序,感興趣的可以了解一下
    2023-06-06
  • go語言限制協(xié)程并發(fā)數(shù)的方案詳情

    go語言限制協(xié)程并發(fā)數(shù)的方案詳情

    一個線程中可以有任意多個協(xié)程,但某一時刻只能有一個協(xié)程在運(yùn)行,多個協(xié)程分享該線程分配到的計算機(jī)資源,接下來通過本文給大家介紹go語言限制協(xié)程的并發(fā)數(shù)的方案詳情,感興趣的朋友一起看看吧
    2022-01-01
  • idea搭建go環(huán)境實現(xiàn)go語言開發(fā)

    idea搭建go環(huán)境實現(xiàn)go語言開發(fā)

    這篇文章主要給大家介紹了關(guān)于idea搭建go環(huán)境實現(xiàn)go語言開發(fā)的相關(guān)資料,文中通過圖文介紹以及代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用go具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-01-01
  • Go語言入門之函數(shù)的定義與使用

    Go語言入門之函數(shù)的定義與使用

    函數(shù)是一段代碼的片段,包含連續(xù)的執(zhí)行語句,它可以將零個或多個輸入?yún)?shù)映射到零個或多個參數(shù)輸出。本文將通過示例和大家詳細(xì)聊聊Go語言中函數(shù)的定義與使用,感興趣的可以了解一下
    2022-11-11
  • 使用golang開發(fā)一個curl命令行工具

    使用golang開發(fā)一個curl命令行工具

    這篇文章主要為大家詳細(xì)介紹了如何使用golang開發(fā)一個簡單的curl命令行工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11
  • Go學(xué)習(xí)筆記之map的聲明和初始化

    Go學(xué)習(xí)筆記之map的聲明和初始化

    map底層是由哈希表實現(xiàn)的,Go使用鏈地址法來解決鍵沖突,下面這篇文章主要給大家介紹了關(guān)于Go學(xué)習(xí)筆記之map的聲明和初始化的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • Go語言實現(xiàn)一個Http Server框架(二) Server的抽象

    Go語言實現(xiàn)一個Http Server框架(二) Server的抽象

    上一篇文章對http庫的基本使用做了說明,這篇文章主要介紹了如何實現(xiàn)一個簡單地httpServer,文中代碼示例非常詳細(xì),感興趣的朋友可以參考下
    2023-04-04
  • Golang 實現(xiàn) Redis系列(六)如何實現(xiàn) pipeline 模式的 redis 客戶端

    Golang 實現(xiàn) Redis系列(六)如何實現(xiàn) pipeline 模式的 redis 客戶端

    pipeline 模式的 redis 客戶端需要有兩個后臺協(xié)程負(fù)責(zé) tcp 通信,調(diào)用方通過 channel 向后臺協(xié)程發(fā)送指令,并阻塞等待直到收到響應(yīng),本文是使用 golang 實現(xiàn) redis 系列的第六篇, 將介紹如何實現(xiàn)一個 Pipeline 模式的 Redis 客戶端。
    2021-07-07

最新評論