亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Go單元測(cè)試工具gomonkey的使用

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

Go 單元測(cè)試工具

測(cè)試分為4個(gè)層次

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

常犯的錯(cuò)誤:

  • 沒(méi)有斷言。沒(méi)有斷言的單測(cè)是沒(méi)有靈魂的。

單測(cè)的特征:

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

單測(cè)

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

  • 提高代碼質(zhì)量

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

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

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

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

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

  • 測(cè)試異常場(chǎng)景

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

Go 單元測(cè)試工具

gomonkey

引入 gomonkey 有如下好處:

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

功能列表

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

函數(shù)打樁, 對(duì)變量的 mock 實(shí)現(xiàn)原理跟 gostub 一樣都是通過(guò) reflect 包實(shí)現(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 生成的一個(gè)函數(shù)執(zhí)行,每次調(diào)用會(huì)順序從 outputs 取出一個(gè)值返回
  • ApplyMethodSeq(target reflect.Type, methodName string, outputs []OutputCell):修改 target 的機(jī)器指令,跳轉(zhuǎn)到 gomonkey 生成的一個(gè)方法執(zhí)行,每次調(diào)用會(huì)順序從 outputs 取出一個(gè)值返回
  • ApplyFuncVarSeq(target interface{}, outputs []OutputCell):gomonkey 生成一個(gè)函數(shù)順序返回 outputs 中的值,調(diào)用 ApplyGlobalVar

gomonkey 打樁失敗的可能原因

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

goconvey

為全局變量打一個(gè)樁

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

為一個(gè)函數(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(),返回了計(jì)算結(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í)行時(shí)失敗的,mock 沒(méi)有成功。

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

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

為了減少函數(shù)調(diào)用時(shí)的堆棧等開(kāi)銷,對(duì)于簡(jiǎn)短的函數(shù),會(huì)在編譯時(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

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

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

    idea搭建go環(huán)境實(shí)現(xiàn)go語(yǔ)言開(kāi)發(fā)

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

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

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

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

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

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

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

    Go語(yǔ)言實(shí)現(xiàn)一個(gè)Http Server框架(二) Server的抽象

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

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

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

最新評(píng)論