前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Golang——测试与调试

Golang——测试与调试

作者头像
羊羽shine
发布2019-05-29 16:41:23
1.5K0
发布2019-05-29 16:41:23
举报
文章被收录于专栏:Golang开发Golang开发
testing包

testing包提供了自动化测试相关的框架,测试源码文件的主名称通常已被测试源码文件的名字作为开头,文件名必须以xx_test.go结尾,例如我们的被测试源码文件名称是demo.go 那么我们测试源码文件名称应该是demo_test.go

功能测试test

1测试方法样式是func Testxxx(t *testing.T),方法名词必须以Test开头,xxx首字母需要大写,func TestFoo(t *testing.T) 2测试方法参数必须 t *testing.T,函数中通过调用testing.T的Error, Errorf和FailNow, Fatal, FatalIf等方法说明测试不通过,以error 打印函数不会终止测试,Fatal类型会造成该单元测试终止。 当然通过调用Log方法用来记录测试的信息。 eg:

代码语言:javascript
复制
import "testing"

func TestFoo(t *testing.T) {
    t.Log("test")
}

测试代码 calc.go

代码语言:javascript
复制
package calc

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

func Sub(a, b int) int {
    return a - b
}

func Mul(a, b int) int {
    return a * b
}

func Div(a, b int) int {
    return a / b
}

单元测试代码

代码语言:javascript
复制
func TestAdd(t *testing.T) {
    a := 1
    b := 2
    c := Add(a, b)
    if c != 3 {
        t.Fatalf("err:%d + %d =%d", a, b, c)
    }
    t.Logf("%d + %d =%d", a, b, c)
}

func TestSub(t *testing.T) {
    a := 10
    b := 2
    c := Sub(a, b)
    if c != 8 {
        t.Fatalf("err:%d - %d = %d", a, b, c)
    }
    t.Logf("%d - %d =%d", a, b, c)
}
压力/性能测试benchmark

对于性能测试函数来说,其名称必须以Benchmark为前缀,并且唯一参数的类型必须是*testing.B类型的。 testing.B 拥有testing.T 的全部接口,同时还可以统计内存消耗,指定并行数目和操作计时器等

代码语言:javascript
复制
import "testing"

func BenchmarkFoo(t *testing.B) {
    t.Log("Benchmark")
}

性能测试demo

代码语言:javascript
复制
package test

import (
    "bytes"
    "strings"
    "testing"
)

func BenchmarkByte(t *testing.B) {
    b := bytes.Buffer{}
    b.WriteString("foo")
    for i := 0; i < t.N; i++ {
        b.String()
    }
}

func BenchmarkStr(t *testing.B) {
    s := strings.Builder{}
    s.WriteString("test")
    for i := 0; i < t.N; i++ {
        s.String()
    }
}

go test 不会主动执行benchmark函数的,需要增建 -test_bench,所以下面的代码不会执行任何压力测试

代码语言:javascript
复制
 go test bench_test.go                  
ok      command-line-arguments  0.001s [no tests to run]

".*"表示测试全部的压力测试函数,执行当前测试文件的所有压力测试函数,第一列表示被执行的测试函数,-8代表当前的cup执行核数,第二列表示执行了总共次数,第三列表示平均执行的耗时

代码语言:javascript
复制
 go test bench_test.go -test.bench=".*"  
goos: linux
goarch: amd64
BenchmarkByte-8         200000000                6.17 ns/op
BenchmarkStr-8          2000000000               0.34 ns/op
PASS
ok      command-line-arguments  2.577s

执行单个的测试函数

代码语言:javascript
复制
 go test bench_test.go -test.bench="Str"
goos: linux
goarch: amd64
BenchmarkStr-8          2000000000               0.34 ns/op
PASS
ok      command-line-arguments  0.719s
go test

go test +包名,执行这个包下面的所有测试用例 go test +测试源文件,执行这个测试源文件里的所有测试用例 go test -run选项,执行只定的测试用例

调试

delve是golang推荐的专门go语言调试工具,用来替代gdb,因为:golang组织说delve能更好的理解go语言。

image.png

Mac OS 安装Delve 首先需要安装xcode-select --install, window和linux 执行go get 命令

代码语言:javascript
复制
go get github.com/derekparker/delve/cmd/dlv

当前调试程序如下

代码语言:javascript
复制
package main

import "net/http"

func hello(writer http.ResponseWriter, request *http.Request) {
    host := request.Host
    writer.Write([]byte(host))
}

func main() {
    http.HandleFunc("/hello",hello)
    http.ListenAndServe(":8080",nil)
}

执行 dlv debug main.go,b命令是设置断点,发送请求命令curl localhost:8080/hello

代码语言:javascript
复制
(dlv) b main.hello
Breakpoint 1 set at 0x1330e73 for main.hello() ./main.go:5
(dlv) c
> main.hello() ./main.go:5 (hits goroutine(18):1 total:1) (PC: 0x1330e73)
     1: package main
     2:
     3: import "net/http"
     4:
=>   5: func hello(writer http.ResponseWriter, request *http.Request) {
     6:     host := request.Host
     7:     writer.Write([]byte(host))
     8: }
     9:
    10: func main() {
(dlv) n
> main.hello() ./main.go:6 (PC: 0x1330e81)
     1: package main
     2:
     3: import "net/http"
     4:
     5: func hello(writer http.ResponseWriter, request *http.Request) {
=>   6:     host := request.Host
     7:     writer.Write([]byte(host))
     8: }
     9:
    10: func main() {
    11:     http.HandleFunc("/hello",hello)
(dlv) n
> main.hello() ./main.go:7 (PC: 0x1330ea3)
     2:
     3: import "net/http"
     4:
     5: func hello(writer http.ResponseWriter, request *http.Request) {
     6:     host := request.Host
=>   7:     writer.Write([]byte(host))
     8: }
     9:
    10: func main() {
    11:     http.HandleFunc("/hello",hello)
    12:     http.ListenAndServe(":8080",nil)
(dlv) args
writer = net/http.ResponseWriter(*net/http.response) 0xc000115968
request = ("*net/http.Request")(0xc000144100)
(dlv) p host
"localhost:8080"

输入 n 回车,执行到下一行 输入s 回车,单步执行 输入 print(别名p)输出变量信息   输入 args 打印出所有的方法参数信息 输入 locals 打印所有的本地变量

二进制文件调试

go build main.go,执行当前./demo 程序

代码语言:javascript
复制
 ps -ef|grep demo
  501 11215   554   0 12:11上午 ttys001    0:00.01 ./demo
  501 11280 11218   0 12:11上午 ttys002    0:00.00 grep demo

dlv attch 11215

代码语言:javascript
复制
(dlv) s
> main.hello() ./go/src/baxiang.cn/demo/main.go:7 (PC: 0x124f620)
Warning: debugging optimized function
     2:
     3: import "net/http"
     4:
     5: func hello(writer http.ResponseWriter, request *http.Request) {
     6:     host := request.Host
=>   7:     writer.Write([]byte(host))
     8: }
     9:
    10: func main() {
    11:     http.HandleFunc("/hello",hello)
    12:     http.ListenAndServe(":8080",nil)
(dlv) locals
host = "localhost:8080"
go tool
代码语言:javascript
复制
import "fmt"

func main() {
    fmt.Println("foo")
    return
    fmt.Printf("bar")
}

在golang1.12上已经换成了go vet

代码语言:javascript
复制
go tool vet main.go
vet: invoking "go tool vet" directly is unsupported; use "go vet"

下面执行结果表示当前代码行无法被执行的

代码语言:javascript
复制
go vet main.go
# command-line-arguments
./main.go:8:2: unreachable code

分析锁的问题

代码语言:javascript
复制
import (
    "sync"
)

type Foo struct {
    lock sync.Mutex
}

func (f *Foo) Lock() {
    f.lock.Lock()
}

func (f Foo) Unlock() {
    f.lock.Unlock()
}

func main() {
    f := Foo{sync.Mutex{}}
    f.Lock()
    f.Unlock()
    f.Lock()
}

t.lock.Unlock() 实际上是由 lock 的副本调用的。在锁传值使用了值传递 需要修改,否则出现死锁。

代码语言:javascript
复制
 go vet main.go
# command-line-arguments
./main.go:15:9: Unlock passes lock by value: command-line-arguments.Foo
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.04.03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • testing包
  • 功能测试test
  • 压力/性能测试benchmark
  • go test
  • 调试
    • 二进制文件调试
    • go tool
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档