欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

PouchContainer集成測試覆蓋率統(tǒng)計(jì)

作者| 阿里云智能事業(yè)群高級(jí)測試開發(fā)工程師 劉璐

在奎文等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì) 網(wǎng)站設(shè)計(jì)制作定制網(wǎng)站制作,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計(jì),全網(wǎng)營銷推廣,外貿(mào)營銷網(wǎng)站建設(shè),奎文網(wǎng)站建設(shè)費(fèi)用合理。

PouchContainer 是阿里巴巴開源的富容器技術(shù),已于 2018 年 9 月正式發(fā)布 GA 版本,已經(jīng)完全達(dá)到生產(chǎn)級(jí)別。PouchContainer 一直非常重視項(xiàng)目質(zhì)量,項(xiàng)目的開發(fā)者需在提交 PR 時(shí)提供與之對應(yīng)的單測與集成測試代碼。這種要求,一方面保證回歸質(zhì)量,同時(shí)也減少代碼 review 成本,提高合作效率。(更多參考:PouchContainer 開源版本及內(nèi)部版本一致性實(shí)踐)

最初,PouchContainer 結(jié)合 TravisCI 與 Codecov 工具,為每次 PR 提交運(yùn)行測試并展示單元測試覆蓋率。對于一些添加集成測試的 PR,集成測試的增減所帶來的測試覆蓋率變化并沒有納入到測試覆蓋率的統(tǒng)計(jì)中。

集成測試覆蓋率的缺失,使得開發(fā)者缺少對項(xiàng)目測試覆蓋率的更完整認(rèn)知。為了更全面的展示 PouchContainer 的測試覆蓋率,現(xiàn)在 PouchContainer 已經(jīng)加入了集成測試覆蓋率的統(tǒng)計(jì)功能。本文主要介紹集成測試覆蓋率統(tǒng)計(jì)在 PouchContainer 中的實(shí)現(xiàn)。

Go 測試覆蓋率

在介紹集成測試覆蓋率統(tǒng)計(jì)實(shí)現(xiàn)之前,我們需要了解 Golang 的覆蓋率統(tǒng)計(jì)的原理。Golang 的覆蓋率統(tǒng)計(jì),是通過在編譯之前重寫包的源代碼,加入統(tǒng)計(jì)信息,然后編譯、運(yùn)行、收集測試覆蓋率。有關(guān) Go 測試覆蓋率的原理可參考 The cover story (https://blog.golang.org/cover),接下來的內(nèi)容,主要參考上述文章,并具體列出執(zhí)行過程。

首先,給出一個(gè)待測 Size() 函數(shù),它有多個(gè) switch 分支,代碼如下:

package size
func Size(a int) string {
  switch {
  case a < 0:
    return "negative"
  case a == 0:
    return "zero"
  case a < 10:
    return "small"
  }
  return "enormous"
}

對應(yīng)的測試代碼如下:

$ cat size_test.go
package size

import (
    "testing"
    "fmt"
)

type Test struct {
    in  int
    out string
}

var tests = []Test{
    {-1, "negative"},
    {5, "small"},
}

func TestSize(t *testing.T) {
    fmt.Println("a")
    for i, test := range tests {
        size := Size(test.in)
        if size != test.out {
            t.Errorf("#%d: Size(%d)=%s; want %s", i, test.in, size, test.out)
        }
    }
}


執(zhí)行go test -x -cover -coverprofile=./size.out 命令,運(yùn)行測試并統(tǒng)計(jì)測試覆蓋率。其中,-x 參數(shù)打印上述命令的執(zhí)行過程(需注意:打印的執(zhí)行步驟信息不完整,如果手動(dòng)執(zhí)行輸出的步驟,則會(huì)運(yùn)行失敗,這是因?yàn)?go test 的一些執(zhí)行步驟并沒有打印信息),-cover 參數(shù)開啟測試覆蓋率統(tǒng)計(jì)功能,-coverprofile 參數(shù)指定存儲(chǔ)測試覆蓋率文件,運(yùn)行結(jié)果如下:


$ go test -x -cover -coverprofile=./size.out
WORK=/var/folders/d2/0gxc6wf16hb6t8ng0w00czpm0000gn/T/go-build982568783
mkdir -p $WORK/test/_test/
mkdir -p $WORK/test/_test/_obj_test/
cd $WORK/test/_test/_obj_test/
/usr/local/go/pkg/tool/darwin_amd64/cover -mode set -var GoCover_0 -o .size.go /Users/letty/work/code/go/src/test/size.go
cd /Users/letty/work/code/go/src/test
/usr/local/go/pkg/tool/darwin_amd64/compile -o $WORK/test/_test/test.a -trimpath $WORK -p test -complete -buildid 6033df309978241f19d83a0e6bad252ee3ba376e -D _/Users/letty/work/code/go/src/test -I $WORK -pack $WORK/test/_test/_obj_test/size.go ./size_test.go
cd $WORK/test/_test
/usr/local/go/pkg/tool/darwin_amd64/compile -o ./main.a -trimpath $WORK -p main -complete -D "" -I . -I $WORK -pack ./_testmain.go
cd .
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/test/_test/test.test -L $WORK/test/_test -L $WORK -w -extld=clang -buildmode=exe $WORK/test/_test/main.a
$WORK/test/_test/test.test -test.coverprofile=./size.out -test.outputdir /Users/letty/work/code/go/src/test
a
PASS
coverage: 60.0% of statements
ok      test    0.006s

從上述輸出的倒數(shù)第二行可知,測試覆蓋率為 60%。分析go test 的執(zhí)行步驟,第五行調(diào)用/usr/local/go/pkg/tool/darwin_amd64/cover 工具,這個(gè)工具重寫待測源碼,在代碼中加入計(jì)數(shù)點(diǎn),用以統(tǒng)計(jì)測試覆蓋率。第 8-13 行編譯待測文件和_testmain.go 文件(這個(gè)文件是go test 工具生成的,具體實(shí)現(xiàn)細(xì)節(jié)可以參見https://github.com/golang/go/blob/3f150934e274f9ce167e1ed565fb3e60b8ea8223/src/cmd/go/internal/test/test.go#L1887),生成test.test 測試執(zhí)行文件。第 13 行,執(zhí)行test.test 測試文件,傳入測試相關(guān)參數(shù),即可運(yùn)行測試。

查看cover 命令的幫助信息,再次執(zhí)行cover 命令,可以查看被重寫后的測試代碼:

$ cat .size.go
package size

func Size(a int) string {
    GoCover_0.Count[0] = 1
    switch {
    case a < 0:
        GoCover_0.Count[2] = 1
        return "negative"
    case a == 0:
        GoCover_0.Count[3] = 1
        return "zero"
    case a < 10:
        GoCover_0.Count[4] = 1
        return "small"
    }
    GoCover_0.Count[1] = 1
    return "enormous"
}

var GoCover_0 = struct {
    Count     [5]uint32
    Pos       [3 * 5]uint32
    NumStmt   [5]uint16
} {
    Pos: [3 * 5]uint32{
        3, 4, 0x9001a, // [0]
        12, 12, 0x130002, // [1]
        5, 6, 0x14000d, // [2]
        7, 8, 0x10000e, // [3]
        9, 10, 0x11000e, // [4]
    },
    NumStmt: [5]uint16{
        1, // 0
        1, // 1
        1, // 2
        1, // 3
        1, // 4
    },
}

查看go test 運(yùn)行測試后的覆蓋率統(tǒng)計(jì)文件,信息如下:

$ cat size.out
mode: set
test/size.go:3.26,4.9 1 1
test/size.go:12.2,12.19 1 0
test/size.go:5.13,6.20 1 1
test/size.go:7.14,8.16 1 0
test/size.go:9.14,10.17 1 1

文件的第一行標(biāo)識(shí)覆蓋率統(tǒng)計(jì)模式為setgo test 提供 set、count、atomic 三種模式:

  • set 模式僅統(tǒng)計(jì)語句是否運(yùn)行;

  • count 模式統(tǒng)計(jì)語句運(yùn)行的次數(shù);

  • atomic 模式與count 類似,統(tǒng)計(jì)語句運(yùn)行次數(shù),適用于多線程測試。

第二行開始的格式為:name.go:line.column,line.column numberOfStatements count,即文件名、代碼的起始位置、語句的行數(shù)以及被運(yùn)行的次數(shù)。本次示例代碼中,待統(tǒng)計(jì)的語句共 5 行,統(tǒng)計(jì)模式為set,共有 3 個(gè) count 被置為 1(讀者可以將 covermode 設(shè)置為 count,觀察 count 輸出有何變化),所以最終的測試覆蓋率結(jié)果為 60%。

PouchContainer 測試覆蓋率

PouchContainer 集成 CodeCov 工具,每次運(yùn)行 TravisCI 會(huì)將測試覆蓋率文件上傳至 CodeCov 網(wǎng)站,完成覆蓋率的可視化展示與持續(xù)追蹤。

TravisCI 與 CodeCov 可以很容易的集成,只需在測試路徑下生成一個(gè) coverage.txt 名字的覆蓋率統(tǒng)計(jì)文件,并在.tarvis.yml 文件中調(diào)用 CodeCov 的腳本,即可上傳覆蓋率統(tǒng)計(jì)文件,具體命令可以參考 Makefile 中 TEST_FLAGS= make build-integration-test 里面的實(shí)現(xiàn),感興趣的同學(xué)也可以直接查看 CodeCov 腳本,了解其實(shí)現(xiàn)細(xì)節(jié)。

接下來,我們從單測和集成測試覆蓋率統(tǒng)計(jì)兩方面展開,詳細(xì)闡述 PouchContainer 的實(shí)現(xiàn)細(xì)節(jié)。

單測覆蓋率統(tǒng)計(jì)

PouchContianer 收集單測覆蓋率相對簡單,只需要執(zhí)行make unit-test 命令,即可實(shí)現(xiàn)覆蓋率統(tǒng)計(jì)收集。單測覆蓋率統(tǒng)計(jì)的實(shí)現(xiàn)可以可以參考 Makefile。需要注意的是,覆蓋率統(tǒng)計(jì)時(shí)需要排除一些無關(guān) package,例如 vendor 目錄、types 目錄等,否則會(huì)影響測試覆蓋率的準(zhǔn)確性。

集成測試覆蓋率統(tǒng)計(jì)

PouchContainer 集成測試,是通過啟動(dòng) pouch daemon,然后執(zhí)行 pouch 命令行或者直接發(fā)送 API 請求,實(shí)現(xiàn)對 daemon API 和命令行的測試。正常情況下,待測試 pouch daemon 是通過go build編譯,源碼中沒有插入計(jì)數(shù)器,無法統(tǒng)計(jì)測試覆蓋率。

實(shí)現(xiàn)統(tǒng)計(jì) pouch daemon 的測試覆蓋率的 PR 參見https://github.com/alibaba/pouch/pull/1338),這個(gè) PR(由于代碼的不斷迭代,最新的代碼位置已改變,請讀者參照本文所對應(yīng)的 commit 代碼)中,我們做了如下工作:

  1. 根目錄下新增 main_test.go 測試文件

  2. hack/build 腳本中,新增 testserver 函數(shù)用于編譯 main package,生成可執(zhí)行測試文件

  3. hack/make.sh 腳本中,后臺(tái)啟動(dòng)步驟 2 生成的測試文件,并運(yùn)行 API 和命令行測試

  4. 測試結(jié)束后,給測試進(jìn)程發(fā)送信號(hào),并收集測試覆蓋率

接下來將詳細(xì)講述實(shí)現(xiàn)細(xì)節(jié),首先,新增 main_test.go 測試文件,并在文件中定義一個(gè)測試函數(shù)TestMain,代碼如下:

package main

import (
    "os"
    "os/signal"
    "strings"
    "syscall"
    "testing"
)

func TestMain(t *testing.T) {
    var (
        args []string
    )

    for _, arg := range os.Args {
        switch {
        case strings.HasPrefix(arg, "DEVEL"):
        case strings.HasPrefix(arg, "-test"):
        default:
            args = append(args, arg)
        }
    }

    waitCh := make(chan int, 1)

    os.Args = args
    go func() {
        main()
        close(waitCh)
    }()

    signalCh := make(chan os.Signal, 1)
    signal.Notify(signalCh, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGHUP)
    select {
    case <-signalCh:
        return
    case <-waitCh:
        return
    }
}

通過添加main_test.go 文件,可以使我們使用現(xiàn)有的go test 工具編譯pouch daemon ,當(dāng)運(yùn)行如下命令時(shí),go test 將編譯當(dāng)前路徑下以_test 結(jié)尾的文件所屬的 package,即我們需要的main package,然后鏈接到go test 提供的測試主程序中(即前面提到的_testmain.go  文件),生成測試可執(zhí)行文件:

# go test -c -race -cover -covermode=atomic -o pouchd-test -coverpkg $pkgs

其中 \$pkg 指定需要統(tǒng)計(jì)測試覆蓋率的包名,go test 調(diào)用cover 工具對指定的 package 源碼重寫,加入測試覆蓋率計(jì)數(shù)器;-o 參數(shù)指示僅編譯不運(yùn)行,且指定測試二進(jìn)制名為pouchd-test。執(zhí)行上述命令后,即可得到一個(gè)調(diào)用main() 函數(shù)的測試二進(jìn)制文件。

第三步,啟動(dòng)pouch-test 運(yùn)行測試代碼,由于測試代碼中調(diào)用pouch daemon 的入口main() 函數(shù),即可達(dá)到啟動(dòng)pouch daemon 并提供服務(wù)的目的。具體命令如下:

# pouchd-test -test.coverprofile=$DIR/integrationcover.out DEVEL --debug

其中,-test 前綴的參數(shù)由go test 處理,DEVEL 之后的參數(shù),則會(huì)傳遞給main() 函數(shù)。此時(shí),正常執(zhí)行測試用例,測試結(jié)束后殺掉pouchd-test 進(jìn)程,go test 工具會(huì)打印出測試覆蓋率,并生成覆蓋率文件,完成集成測試覆蓋率的統(tǒng)計(jì)。

從上述步驟可以看到,統(tǒng)計(jì)集成測試覆蓋率的主要工作在于提供一個(gè)main_test.go 文件,接下來我們分析一下這個(gè)文件做了哪些工作。

首先,文件中定義了一個(gè)測試函數(shù)TestMain() ,這是入口函數(shù),執(zhí)行測試可執(zhí)行文件時(shí),會(huì)調(diào)用這個(gè)函數(shù)。

函數(shù)中 16-27 行進(jìn)行了參數(shù)處理,過濾-test 開頭以及DEVEL 參數(shù),并將余下參數(shù)全部賦值給os.Args 。這是因?yàn)?code>go test 默認(rèn)將第一個(gè)非破折號(hào)- 開頭的參數(shù),交由測試函數(shù)處理,main_test.go 代碼中,過濾參數(shù)并重新賦值os.Args,將參數(shù)傳給main() 函數(shù),使得我們可以如常使用 daemon 參數(shù)。

第 28-31 行調(diào)用 main 函數(shù),啟動(dòng) daemon 服務(wù)。第 33-40 行,接收指定信號(hào)并直接退出。注意,我們還定義了一個(gè)waitCh channel ,用于main  函數(shù)退出時(shí),通知測試函數(shù)退出,以防止出現(xiàn)main  函數(shù)調(diào)用自身而其引起的程序永不退出問題。

有關(guān)集成測試覆蓋率統(tǒng)計(jì)的實(shí)現(xiàn)方法,還可以參考這篇文章 《Generating Coverage Profiles for Golang Integration Tests》(https://www.cyphar.com/blog/post/20170412-golang-integration-coverage)。

結(jié)語

集成測試覆蓋率的統(tǒng)計(jì),需要靈活運(yùn)用 Golang 提供的工具,并根據(jù)自身項(xiàng)目代碼特點(diǎn)適配測試文件。加入集成測試覆蓋率統(tǒng)計(jì)后,PouchContainer 的覆蓋率從僅統(tǒng)計(jì)單測時(shí)的 18% 提升至 60%,這將更準(zhǔn)確展示測試現(xiàn)狀。

網(wǎng)站名稱:PouchContainer集成測試覆蓋率統(tǒng)計(jì)
網(wǎng)站URL:http://aaarwkj.com/article16/ggpjdg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、網(wǎng)站內(nèi)鏈、域名注冊、網(wǎng)站收錄網(wǎng)站營銷、ChatGPT

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計(jì)公司
三级视频一区二区三区| 日韩精品亚洲专区在线观看 | av手机天堂网免费观看| 欧美激情一区二区三区蜜桃| 东京男人的天堂国产av| 在线最新亚洲日本韩国| 日韩一区二区三级在线| 免费av在线观看日韩| 黑丝美女国产精品久久久| 一区二区久久精品视频| 天天躁人人躁夜夜躁狠狠躁| 国产精品白丝一区二区三区| 亚洲国产在线一区二区| 亚洲午夜精品日韩乱码| 正在播放蜜臀av在线| 日本特黄特色三级在线观看| 人妻日韩精品综合一二三四| 成人免费视频观看国产| 国产三级传媒视频在线观看| 欧美日韩在线不卡成人| 日本人妻免费在线观看| 国产精品av国产精华液| 激情一区二区三区视频| 伊在人天堂亚洲香蕉精品区| 蜜桃av在线播放视频| 91在线播放国产视频| 国产不卡的视频在线观看| 亚洲中文有码在线播放| 日韩av高清在线播放| 精品三级黄色国产片| 男女做爰高清免费视频| 国产精品亚洲伦理在线| 欧美日韩国产一区二区三区在线观看| 欧美一区二区三区久久束缚| 91在线观看高清免费| 亚洲av天堂免费在线观看| 亚洲天堂国产成人精品| 全黄性性激高免费放视频| 天天天干夜夜添狠操美女| 在线免费观看国产黄色av| 日韩女优中文字幕在线播放|