<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Golang 語言的單元測試和性能測試(也叫 壓力測試)

      Golang單元測試對文件名和方法名,參數都有很嚴格的要求。
      例如:
        1、文件名必須以xx_test.go命名
        2、方法必須是Test[^a-z]開頭(T必須大寫),func TestXxx (t *testing.T),Xxx部分可以為任意的字母數字的組合,但是首字母不能是小寫字母[a-z],例如Testintdiv是錯誤的函數名。
        3、方法參數必須 t *testing.T

             4、測試用例會按照源代碼中寫的順序依次執行

             5、函數中通過調用testing.TErrorErrorfFailNowFatalFatalIf方法,說明測試不通過,調用Log方法用來記錄測試的信息。

      test的運行方式:

      go test -v github.com/welhzh/dago/test

      其中后面的test為test目錄

      Go 提供了 TestMain(*testing.M) 的函數,它在需要的時候代替運行所有的測試。使用 TestMain() 函數時,您有機會在測試運行之前或之后插入所需的任何自定義代碼,但唯一需要注意的是必須處理 flag 解析并使用測試結果調用 os.Exit()。這聽起來可能很復雜,但實際上只有兩行代碼。

       

      測試的覆蓋率

      go tool命令可以報告測試覆蓋率統計。使用 go test -cover 測試覆蓋率。

      可視化查看覆蓋率:

      執行go tool cover -html=cover.out命令,會在/tmp目錄下生成目錄coverxxxxxxx,比如/tmp/cover404256298。目錄下有一個 coverage.html文件。用瀏覽器打開coverage.html,即可以可視化的查看代碼的測試覆蓋情況。

       

      從內部測試

      golang中大多數測試代碼都是被測試包的源碼的一部分。這意味著測試代碼可以訪問包種未導出的符號以及內部邏輯。就像我們之前看到的那樣。

      注:比如$GOROOT/src/pkg/path/path_test.go與path.go都在path這個包下。

      從外部測試

      有些時候,你需要從被測包的外部對被測包進行測試,比如測試代碼在package foo_test下,而不是在package foo下。這樣可以打破依賴循環。

       

      1、功能測試

      上一個完整的例子:

      // how to run: go test -v github.com/welhzh/dago/test
      package client
      
      import (
          "flag"
          "fmt"
          "os"
          "testing"
      
          "github.com/welhzh/dago/client"
      )
      
      func initTest() {
      }
      
      func destroyTest() {
      }
      // test example func TestSum(t *testing.T) { // 任選一種測試方式進行測試 // ================= test 方式一 ==================== var testInputs = []struct { slice []int // other inputs expect int }{ {[]int{1, 2, 3, 4, 5}, 15}, {[]int{1, 2, 3, 4, -5}, 5}, } for _, oneInput := range testInputs { actual := oneInput.slice[2] if actual != oneInput.expect { t.Errorf("Sum(%q, %q) = %v; want %v", oneInput, oneInput, actual, oneInput.expect) } } // ================================================= // ================= test 方式二 ==================== t.Run("[1,2,3,4,5]", testSumFunc(testInputs[0].slice, testInputs[0].expect)) t.Run("[1,2,3,4,-5]", testSumFunc(testInputs[1].slice, testInputs[1].expect)) // ================================================= } func testSumFunc(numbers []int, expected int) func(*testing.T) { return func(t *testing.T) { actual := numbers[4] if actual != expected { t.Error(fmt.Sprintf("Expected the sum of %v to be %d but instead got %d!", numbers, expected, actual)) } } } func TestMain(m *testing.M) { fmt.Println("test begin ...") initTest() flag.Parse() exitCode := m.Run() destroyTest() fmt.Println("test end ...") // Exit os.Exit(exitCode) }

       

      格式形如:

       

      go test [-c] [-i] [build flags] [packages] [flags for test binary]

      參數解讀:

      -c : 編譯go test成為可執行的二進制文件,但是不運行測試。

      -i : 安裝測試包依賴的package,但是不運行測試。

      關于build flags,調用go help build,這些是編譯運行過程中需要使用到的參數,一般設置為空

      關于packages,調用go help packages,這些是關于包的管理,一般設置為空

      關于flags for test binary,調用go help testflag,這些是go test過程中經常使用到的參數

      -test.v : 是否輸出全部的單元測試用例(不管成功或者失?。J沒有加上,所以只輸出失敗的單元測試用例。

      -test.run pattern: 只跑哪些單元測試用例

      -test.bench patten: 只跑那些性能測試用例

      -test.benchmem : 是否在性能測試的時候輸出內存情況

      -test.benchtime t : 性能測試運行的時間,默認是1s

      -test.cpuprofile cpu.out : 是否輸出cpu性能分析文件

      -test.memprofile mem.out : 是否輸出內存性能分析文件

      -test.blockprofile block.out : 是否輸出內部goroutine阻塞的性能分析文件

      -test.memprofilerate n : 內存性能分析的時候有一個分配了多少的時候才打點記錄的問題。這個參數就是設置打點的內存分配間隔,也就是profile中一個sample代表的內存大小。默認是設置為512 * 1024的。如果你將它設置為1,則每分配一個內存塊就會在profile中有個打點,那么生成的profile的sample就會非常多。如果你設置為0,那就是不做打點了。

      你可以通過設置memprofilerate=1和GOGC=off來關閉內存回收,并且對每個內存塊的分配進行觀察。

      -test.blockprofilerate n: 基本同上,控制的是goroutine阻塞時候打點的納秒數。默認不設置就相當于-test.blockprofilerate=1,每一納秒都打點記錄一下

      -test.parallel n : 性能測試的程序并行cpu數,默認等于GOMAXPROCS。

      -test.timeout t : 如果測試用例運行時間超過t,則拋出panic

      -test.cpu 1,2,4 : 程序運行在哪些CPU上面,使用二進制的1所在位代表,和nginx的nginx_worker_cpu_affinity是一個道理

      -test.short : 將那些運行時間較長的測試用例運行時間縮短

       

      2、性能測試

      如果需要進行性能測試,則函數開頭使用Benchmark就可以了。

      //性能測試
      func BenchmarkFibonacci(b *testing.B) {
          for i := 0; i < b.N; i++ {
              Fibonacci(10)
          }
      }

      接下來執行這個性能測試:

      $ go test -bench=. lib
       PASS
       BenchmarkFibonacci 5000000 436 ns/op
       ok lib 2.608s

      其中第二行輸出表示這個函數運行了5000000次,平均運行一次的時間是436ns。

      這個性能測試只測試參數為10的情況。如果有需要可以測試多個參數:

      //測試參數為5的性能
      func BenchmarkFibonacci5(b *testing.B) {
          for i := 0; i < b.N; i++ {
              Fibonacci(5)
          }
      }
       
      //測試參數為20的性能
      func BenchmarkFibonacci20(b *testing.B) {
          for i := 0; i < b.N; i++ {
              Fibonacci(20)
          }
      }

      運行一下:

      $ go test -bench=. lib
       PASS
       BenchmarkFibonacci 5000000 357 ns/op
       BenchmarkFibonacci5 100000000 29.5 ns/op
       BenchmarkFibonacci20 50000 44688 ns/op
       ok lib 7.824s

      如果性能測試的方法非常多,那需要的時間就會比較久。可以通過-bench=參數設置需要運行的性能測試的函數:

      $ go test -bench=Fibonacci20 lib
       PASS
       BenchmarkFibonacci20 50000 44367 ns/op
       ok lib 2.677s

       

       

      3、IO相關測試 (高級測試技術)

      testing/iotest包中實現了常用的出錯的Reader和Writer,可供我們在io相關的測試中使用。主要有:

      觸發數據錯誤dataErrReader,通過DataErrReader()函數創建

      讀取一半內容的halfReader,通過HalfReader()函數創建

      讀取一個byte的oneByteReader,通過OneByteReader()函數創建

      觸發超時錯誤的timeoutReader,通過TimeoutReader()函數創建

      寫入指定位數內容后停止的truncateWriter,通過TruncateWriter()函數創建

      讀取時記錄日志的readLogger,通過NewReadLogger()函數創建

      寫入時記錄日志的writeLogger,通過NewWriteLogger()函數創建

       

      4、黑盒測試 (高級測試技術)

      testing/quick包實現了幫助黑盒測試的實用函數 Check和CheckEqual。

      Check函數的第1個參數是要測試的只返回bool值的黑盒函數f,Check會為f的每個參數設置任意值并多次調用,如果f返回false,Check函數會返回錯誤值 *CheckError。Check函數的第2個參數 可以指定一個quick.Config類型的config,傳nil則會默認使用quick.defaultConfig。quick.Config結構體包含了測試運行的選項。

      # /usr/local/go/src/math/big/int_test.go
      func checkMul(a, b []byte) bool {
       var x, y, z1 Int
       x.SetBytes(a)
       y.SetBytes(b)
       z1.Mul(&x, &y)
       
       var z2 Int
       z2.SetBytes(mulBytes(a, b))
       
       return z1.Cmp(&z2) == 0
      }
       
      func TestMul(t *testing.T) {
       if err := quick.Check(checkMul, nil); err != nil {
        t.Error(err)
       }
      }

      CheckEqual函數是比較給定的兩個黑盒函數是否相等,函數原型如下:

      func CheckEqual(f, g interface{}, config *Config) (err error)

       

      5、http測試 (高級測試技術)

      net/http/httptest包提供了HTTP相關代碼的工具,我們的測試代碼中可以創建一個臨時的httptest.Server來測試發送HTTP請求的代碼:

      ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
       fmt.Fprintln(w, "Hello, client")
      }))
      defer ts.Close()
       
      res, err := http.Get(ts.URL)
      if err != nil {
       log.Fatal(err)
      }
       
      greeting, err := ioutil.ReadAll(res.Body)
      res.Body.Close()
      if err != nil {
       log.Fatal(err)
      }
       
      fmt.Printf("%s", greeting)

      還可以創建一個應答的記錄器httptest.ResponseRecorder來檢測應答的內容:

      handler := func(w http.ResponseWriter, r *http.Request) {
       http.Error(w, "something failed", http.StatusInternalServerError)
      }
       
      req, err := http.NewRequest("GET", "http://example.com/foo", nil)
      if err != nil {
       log.Fatal(err)
      }
       
      w := httptest.NewRecorder()
      handler(w, req)
       
      fmt.Printf("%d - %s", w.Code, w.Body.String())

       

      6、在進程里測試 (高級測試技術)

      當我們被測函數有操作進程的行為,可以將被測程序作為一個子進程執行測試。下面是一個例子:

      //被測試的進程退出函數
      func Crasher() {
       fmt.Println("Going down in flames!")
       os.Exit(1)
      }
       
      //測試進程退出函數的測試函數
      func TestCrasher(t *testing.T) {
       if os.Getenv("BE_CRASHER") == "1" {
        Crasher()
        return
       }
       cmd := exec.Command(os.Args[0], "-test.run=TestCrasher")
       cmd.Env = append(os.Environ(), "BE_CRASHER=1")
       err := cmd.Run()
       if e, ok := err.(*exec.ExitError); ok && !e.Success() {
        return
       }
       t.Fatalf(

       

      7、競爭檢測 (高級測試技術)

      當兩個goroutine并發訪問同一個變量,且至少一個goroutine對變量進行寫操作時,就會發生數據競爭(data race)。

      為了協助診斷這種bug,Go提供了一個內置的數據競爭檢測工具。

      通過傳入-race選項,go tool就可以啟動競爭檢測。

      $ go test -race mypkg // to test the package
      $ go run -race mysrc.go // to run the source file
      $ go build -race mycmd // to build the command
      $ go install -race mypkg // to install the package

      一個數據競爭檢測的例子:

      //testrace.go
      
      package main
      
      import “fmt” 
      import “time”
      
      func main() {
      
      var i int = 0
          go func() {
                  for {
                          i++
                          fmt.Println("subroutine: i = ", i)
                          time.Sleep(1 * time.Second)
                  }
          }()
      
          for {
                  i++
                  fmt.Println("mainroutine: i = ", i)
                  time.Sleep(1 * time.Second)
          }
      }

      運行:

      $ go run -race testrace.go

       

      8、并發測試 (高級測試技術)testing with concurrency

      當測試并發代碼時,總會有一種使用sleep的沖動。大多時間里,使用sleep既簡單又有效。

      但大多數時間不是”總是“。

      我們可以使用Go的并發原語讓那些奇怪不靠譜的sleep驅動的測試更加值得信賴。

       

      9、靜態分析工具vet查找錯誤 (高級測試技術)

      vet工具用于檢測代碼中程序員犯的常見錯誤:

      – 錯誤的printf格式
      – 錯誤的構建tag
      – 在閉包中使用錯誤的range循環變量
      – 無用的賦值操作
      – 無法到達的代碼
      – 錯誤使用mutex
      等等。

      使用方法:

      go vet [package]

       

      10、Mocks和fakes (高級測試技術)

      通過在代碼中使用interface,Go可以避免使用mock和fake測試機制。

      例如,如果你正在編寫一個文件格式解析器,不要這樣設計函數:

      func Parser(f *os.File) error

      作為替代,你可以編寫一個接受interface類型的函數:

      func Parser(r io.Reader) error

      和bytes.Buffer、strings.Reader一樣,*os.File也實現了io.Reader接口。

       

      posted @ 2018-04-23 14:05  微信公眾號--共鳴圈  閱讀(1113)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精品久久久久不卡绿巨人 | 国产成人精品免费视频app软件 | 亚洲欧美日韩第一页| 精品中文人妻在线不卡| 四虎永久免费精品视频| 亚洲日本欧美日韩中文字幕| 亚洲男人电影天堂无码| 别揉我奶头~嗯~啊~的视频| 亚洲成人av在线高清| 日韩一区日韩二区日韩三区| 综合色天天久久| 欧美中文亚洲v在线| 国产精品色内内在线播放| 武装少女在线观看高清完整版免费| 99久久久无码国产麻豆| a国产一区二区免费入口| 成人精品一区日本无码网| 日韩欧美人妻一区二区三区| 久久99久国产麻精品66| 国产 一区二区三区视频| 亚洲永久精品日本久精品| 亚洲精品不卡av在线播放 | 国产乱对白刺激视频| 亚洲国产高清精品线久久| 高清自拍亚洲精品二区| 久久精品国产88精品久久| 福利视频一区二区在线| 无码伊人66久久大杳蕉网站谷歌| 国产蜜臀视频一区二区三区| 非会员区试看120秒6次| 高级艳妇交换俱乐部小说| 国内精品免费久久久久电影院97| 久久在线视频免费观看| 亚洲 另类 小说 国产精品无码| AV老司机色爱区综合| 男女性杂交内射女bbwxz| 国产精品一区二区三区四区 | 人妻少妇久久中文字幕| 久久精品a亚洲国产v高清不卡 | 色欲综合久久中文字幕网| 精品婷婷色一区二区三区|