go语言中的测试

简介: go语言中的测试

@[toc]

go语言中的测试

测试文件的命名是有一套规则的,通常是某个文件相对应的测试文件,比如app.go的测试文件就是app_test.go

错误测试

错误测试,也是测试中最基础的一种,test首字母要大写,后面的函数(测试谁写谁)首字母也要大写。使用go test命令进行启动。

func TestXxx(t *testing.T){
   
    if xxx {
   
        t.Errorf("xxx")
    }
}

基准测试

所谓基准测试,指的是go语言提供的某个算法或者程序执行一定的次数,然后输出平均的执行时间这个就叫做基准测试

跟test一样B大写,Benchmark 后面的函数首字母也要大写。

func BenchmarkXxx(*testing.B){
   
    // 这里的b.N go会自动提供,次数不一定。
     for i := 0; i < b.N; i++ {
   
        // 这里就是要测试的内容
        rand.Int()
    }
}

如果想在多线程的环境中测试,go给出了一个例子:

func BenchmarkTemplateParallel(b *testing.B) {
   
    templ := template.Must(template.New("test").Parse("Hello, {
   {.}}!"))
    // 这里的 RunParallel函数是关键。
    b.RunParallel(func(pb *testing.PB) {
   
        var buf bytes.Buffer
        for pb.Next() {
   
            buf.Reset()
            templ.Execute(&buf, "World")
        }
    })
}

范例测试

范例测试的意思就是说,运行的结果要跟你提供的例子保持一致

func ExampleHello() {
   
    fmt.Println("hello")
    // Output: hello
}

func ExampleSalutations() {
   
    fmt.Println("hello, and")
    fmt.Println("goodbye")
    // Output:
    // hello, and
    // goodbye
}

这里是有固定形态的,//Output:是固定的用法,后面跟例子输出的结果。

main测试

测试来控制哪些代码在主线程上运行。

func TestMain(m *testing.M){
   
os.Exit(m.Run())
}

子测试

使用`t.Run()`可以进行子测试。
func TestTeardownParallel(t *testing.T) {
   
    // This Run will not return until the parallel tests finish.
    t.Run("group", func(t *testing.T) {
   
        t.Run("Test1", parallelTest1)
        t.Run("Test2", parallelTest2)
        t.Run("Test3", parallelTest3)
    })
    // <tear-down code>
}

关于子测试,命令行里的命令是不一样的:

go test -run ''      # Run all tests.

go test -run Foo     # Run top-level tests matching "Foo", such as "TestFooBar".

go test -run Foo/A=  # For top-level tests matching "Foo", run subtests matching "A=".

go test -run /A=1    # For all top-level tests, run subtests matching "A=1".

跳过测试

如果想跳过某些条件,可以使用t或者b.Skip()方法。

func TestTimeConsuming(t *testing.T) {
   
    if testing.Short() {
   
        t.Skip("skipping test in short mode.")
    }
    ...
}

文件系统测试

这个包是啥意思呢?其实就是帮你模拟了一个文件系统,因为你比如要打开xx文件吧,你不需要单独真的去新建一个,使用这个文件系统的测试,就可以达到这个目的,这个包是testing/fstest

    // 声明一个fstest.MapFs 对象,因为这个对象实现了fs.Fs接口
    //【func (fsys MapFS) Open(name string) (fs.File, error)】
    var ms fstest.MapFS
    // 如果这里不声明ms是这个对象,而是直接就初始化底层类型给ms,
    //下面函数要使用的ms就不是fstest.Mapfs对象,而是map[string]*fstest.MapFile对象
    // 当然你也可以直接不初始化,下面使用的时候显示转化一下即可
    // fstest.MapFs(ms) 即可。


    ms = make(map[string]*fstest.MapFile)
    mf1 := &fstest.MapFile{
   
        Data: []byte("test"),
        Mode: 30,
        ModTime: time.Now(),
        Sys: "12",
    }
    mf2 := &fstest.MapFile{
   
        Data: []byte("test1"),
    }
    // 前面是路径,后面是文件。这是一个模拟。
    ms["a/1"] = mf1
    ms["a/2"] = mf2
    fmt.Println(fstest.TestFS(ms,"a/1","a/2","a/3"))

这里多说一点,go里面的显示类型转化,刚才讲的一般使用的时候,type A int,A类型并不是int,只是它的底层是int,虽然它的一切操作都可以按照int来做,比如

    type A int

     var a A
    //a+1 就等于1,

    // 但是它仍然是A类型不是int,要注意类型转化,只有一个地方go会自动的语法糖,就是return的时候
    func fast()A{
   
            return 1
    }
    // 这里 return的时候进行自动类型判断了,没有把1判断为int,而是判断为A类型了。这属于语法糖。

io测试

io测试包testing/iotest主要是实现了readers和writers,具体我们可以理解为,它实现了很多读取和写入。

黑盒测试

黑盒测试,使用的包是testing/quick

比如一个可以快速得到是否正确的函数

func main(){
   
    f := func() bool{
   
        return 1 == 2
    }
    quick.Check(f,nil)
}

首先,对于我们来说,qucik.Check()是这个盒子的外壳,我们只能看到它,f我们是看不到的,所以我们可以通过check得到f的返回bool结果。

下面这个函数就是可以黑盒看f f1 是否是一致的。

func main(){
   
    f := func() bool{
   
        return true
    }

    f1 := func()bool {
   
        return false
    }

    quick.CheckEqual(f,f1,nil)
}

http测试

http测试,意思就是当你需要一个服务的时候,不需要自己再写一个http服务,你只需要net/http/httptest包即可。

这个包大致可以分为三个内容

  1. request,请求
    注意此包并不是客户端的请求,这是服务端的请求。【客户端用postman】
    func NewRequest(method, target string, body io.Reader) *http.Request
    

目标是RFC 7230“请求目标”:它可以是路径或绝对URL。如果目标是绝对URL,则使用URL中的主机名。否则,将使用“ example.com”。

method 空是get

  1. response,响应
    这个包就是生成一个响应。
    func NewRecorder() *ResponseRecorder
    
  2. server,服务
    服务器是侦听本地接口上系统选择的端口的HTTP服务器,用于端到端HTTP测试。
// 在这段代码中,第一段是一个server,下面是一个客户端get请求。所以上面哪个server监听了本地的请求。
func main() {
   
    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 := io.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
   
        log.Fatal(err)
    }

    fmt.Printf("%s", greeting)
}

性能分析

net/http/pprof 包提供了例如gc,内存,cpu等数据的性能分析包。

如果要使用这个功能,需要写入这个import _ "net/http/pprof"

以及将下面代码加入

go func() {
   
    log.Println(http.ListenAndServe("localhost:6060", nil))
}()

新开一个go的groutine,然后来进行性能分析。

https://golang.org/pkg/net/http/pprof/

go tool pprof -http=:6062 http://localhost:6060/debug/pprof/block

go tool pprof -http=:6062 http://localhost:6060/debug/pprof/goroutine

go tool pprof -http=:6062 http://localhost:6060/debug/pprof/cpus

使用这个命令,可以把数据的分析,使用浏览器打开,http跟的端口,是自己设定的,后面的是分析的具体参数,比如/block /heap等。下面有个列表,最前面就是这些命令。

runtime/pprof
pprof的具体实现,所有类型的代码都可以使用。如果不是Web应用程序,建议使用该包。

类型 描述 备注
allocs 内存分配情况的采样信息 可以用浏览器打开,但可读性不高
blocks 阻塞操作情况的采样信息 可以用浏览器打开,但可读性不高
cmdline 显示程序启动命令及参数 可以用浏览器打开,但可读性不高
goroutine 当前所有协程的堆栈信息 可以用浏览器打开,但可读性不高
heap 堆上内存使用情况的采样信息 可以用浏览器打开,但可读性不高
mutex 锁争用情况的采样信息 可以用浏览器打开,但可读性不高
profile CPU 占用情况的采样信息 浏览器打开会下载文件
threadcreate 系统线程创建情况的采样信息 可以用浏览器打开,但可读性不高
trace 程序运行跟踪信息 浏览器打开会下载文件

http请求跟踪测试

net/http/trace包提供了监听http请求的各个过程的功能,我们来看一个例子

func main() {
   
    // 这里有一个新的request
    req, _ := http.NewRequest("GET", "http://example.com", nil)
    // 这里,有两个参数被监听
    trace := &httptrace.ClientTrace{
   
        GotConn: func(connInfo httptrace.GotConnInfo) {
   
            fmt.Printf("Got Conn: %+v\n", connInfo)
        },
        DNSDone: func(dnsInfo httptrace.DNSDoneInfo) {
   
            fmt.Printf("DNS Info: %+v\n", dnsInfo)
        },
    }
    // 将钩子放入这个http的请求之内,实现监听的效果。
    req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
    _, err := http.DefaultTransport.RoundTrip(req)
    if err != nil {
   
        log.Fatal(err)
    }
}
目录
相关文章
|
22小时前
|
JSON 安全 Java
2024年的选择:为什么Go可能是理想的后端语言
【4月更文挑战第27天】Go语言在2024年成为后端开发的热门选择,其简洁设计、内置并发原语和强大工具链备受青睐。文章探讨了Go的设计哲学,如静态类型、垃圾回收和CSP并发模型,并介绍了使用Gin和Echo框架构建Web服务。Go的并发通过goroutines和channels实现,静态类型确保代码稳定性和安全性,快速编译速度利于迭代。Go广泛应用在云计算、微服务等领域,拥有丰富的生态系统和活跃社区,适合作为应对未来技术趋势的语言。
8 0
|
1天前
|
安全 测试技术 Go
Golang深入浅出之-Go语言单元测试与基准测试:testing包详解
【4月更文挑战第27天】Go语言的`testing`包是单元测试和基准测试的核心,简化了测试流程并鼓励编写高质量测试代码。本文介绍了测试文件命名规范、常用断言方法,以及如何进行基准测试。同时,讨论了测试中常见的问题,如状态干扰、并发同步、依赖外部服务和测试覆盖率低,并提出了相应的避免策略,包括使用`t.Cleanup`、`t.Parallel()`、模拟对象和检查覆盖率。良好的测试实践能提升代码质量和项目稳定性。
7 1
|
1天前
|
运维 监控 Go
Golang深入浅出之-Go语言中的日志记录:log与logrus库
【4月更文挑战第27天】本文比较了Go语言中标准库`log`与第三方库`logrus`的日志功能。`log`简单但不支持日志级别配置和多样化格式,而`logrus`提供更丰富的功能,如日志级别控制、自定义格式和钩子。文章指出了使用`logrus`时可能遇到的问题,如全局logger滥用、日志级别设置不当和过度依赖字段,并给出了避免错误的建议,强调理解日志级别、合理利用结构化日志、模块化日志管理和定期审查日志配置的重要性。通过这些实践,开发者能提高应用监控和故障排查能力。
8 1
|
1天前
|
安全 Go
Golang深入浅出之-Go语言标准库中的文件读写:io/ioutil包
【4月更文挑战第27天】Go语言的`io/ioutil`包提供简单文件读写,适合小文件操作。本文聚焦`ReadFile`和`WriteFile`函数,讨论错误处理、文件权限、大文件处理和编码问题。避免错误的关键在于检查错误、设置合适权限、采用流式读写及处理编码。遵循这些最佳实践能提升代码稳定性。
5 0
|
1天前
|
Go C++
go 语言回调函数和闭包
go 语言回调函数和闭包
|
1天前
|
存储 负载均衡 监控
【Go 语言专栏】构建高可靠性的 Go 语言服务架构
【4月更文挑战第30天】本文探讨了如何利用Go语言构建高可靠性的服务架构。Go语言凭借其高效、简洁和并发性能,在构建服务架构中备受青睐。关键要素包括负载均衡、容错机制、监控预警、数据存储和服务治理。文章详细阐述了实现这些要素的具体步骤,通过实际案例分析和应对挑战的策略,强调了Go语言在构建稳定服务中的作用,旨在为开发者提供指导。
|
1天前
|
测试技术 Go 开发工具
【Go语言专栏】Go语言中的代码审查与最佳实践
【4月更文挑战第30天】Go语言因其简洁、高性能及并发能力,在云计算等领域广泛应用。代码审查对提升Go代码质量、遵循规范及团队协作至关重要。审查流程包括提交、审查、反馈、修改和合并代码。工具如GoLand、Git、ReviewBoard和GitHub提供支持。最佳实践包括遵循命名规范、添加注释、保持代码结构清晰、复用代码和确保测试覆盖。积极参与代码审查是提高质量的关键。
|
1天前
|
Prometheus 监控 Cloud Native
【Go语言专栏】Go语言中的日志记录与监控
【4月更文挑战第30天】Go语言在软件开发和运维中扮演重要角色,提供灵活的日志记录机制和与多种监控工具的集成。内置`log`包支持基本日志记录,而第三方库如`zap`、`zerolog`和`logrus`则扩展了更多功能。监控方面,Go应用可与Prometheus、Grafana、Jaeger等工具配合,实现系统指标收集、可视化和分布式追踪。健康检查通过HTTP端点确保服务可用性。结合日志和监控,能有效提升Go应用的稳定性和性能。
|
1天前
|
存储 安全 中间件
【Go语言专栏】Go语言中的安全认证与授权机制
【4月更文挑战第30天】本文探讨了Go语言中实现安全认证与授权的方法。认证机制包括HTTP Basic Auth、表单认证、OAuth和JWT,可借助`net/http`及第三方库实现。授权则通过中间件或拦截器,如RBAC、ABAC和上下文相关授权,`casbin`和`go-permission`等库提供解决方案。实践中,需设计认证流程、存储用户凭证、实现逻辑、定义授权策略和编写中间件,并确保安全性。案例分析展示了认证授权在RESTful API服务中的应用。在Go开发中,不断学习和优化安全策略以应对安全挑战至关重要。
|
1天前
|
SQL 安全 Go
【Go语言专栏】Go语言中的安全审计与漏洞修复
【4月更文挑战第30天】本文介绍了Go语言中的安全审计和漏洞修复实践。安全审计包括代码审查、静态分析、运行时分析、渗透测试和专业服务,借助工具如`go vet`、`staticcheck`、`gosec`等。修复漏洞的方法涉及防止SQL注入、XSS攻击、CSRF、不安全反序列化等。遵循最小权限原则、输入验证等最佳实践,结合持续学习,可提升Go应用安全性。参考[Go安全工作组](https://github.com/golang/security)和[OWASP Top 10](https://owasp.org/www-project-top-ten/)深入学习。

热门文章

最新文章