15.测试和性能

测试:软件开发最重要的方面

  • 单元测试

单元测试针对一小部分代码,并独立地对它们进行测试。通常,这一小部分代码可能是单个函数,而要测试的是其输入和输出。在确认程序最小的构建按期望的方式运行方面,这种测试很有效

  • 集成测试

如果说单元测试检查的是程序的最小组成部分,那么集成测试就是检查应用程序各个组件协同工作的情况。

  • 功能测试

很多开发人员都提倡采用测试驱动开发,这种做法从测试的角度考虑新功能,先编写测试来描述代码片段的功能,再着手编写代码。

  1. 有助于描述代码设计,因为考虑清楚代码片段的工作原理后,可改善代码设计
  2. 有助于提供有关功能工作原理的定义
  3. 未来可使用现成的测试来确定没有发生衰退
  4. 可使用现成的测试来核实正确地实现了代码

testing包

相关约定

  • Go测试与其测试的代码在一起,测试不是放在单独的测试目录中,要在测试的文件的文件名称后面加上_test
  • 测试为名称以单词Test打头的函数
package example01

import "testing"

func TestTruthy(t *testing.T){
    if true != true{
        t.Fatal("The world is crumbling")
    }
}

//PASS
//ok      _/D_/Backup/Documents/golang    0.165s
  • 在测试包中创建两个变量:got和want,它们分别表示要测试的值以及期望的值
package example02

import "testing"

func Greeting(s string) string{
    return s
}

func TestGreeting(t *testing.T){
    got := Greeting("George")
    want := "George"

    if got != want {
        t.Fatalf("falid")
    }
}

运行表格驱动测试

通常,函数和方法的相应随着收到的输入而不同,因此,我们需要测试多个输入,就可以使用Go语言提供的表格驱动测试模式,能够测试多个条件

package example4

import (
    "testing"
    "fmt"
)

type GreetingTest struct{
    locale string
    want string
}

func translate(s string) string{
    switch s {
    case "en-US":
        return "hello"
    case "fr-FR":
        return "Bonjour"
    case "it-IT":
        return "Ciao"
    default:
        return "hello"
    }
}

var greetingTests=[] GreetingTest{
    {"en-US","hello"},
    {"fr-FR","Bonjour"},
    {"it-IT","Ciao"},
}

func TestGreeting(t *testing.T){
    for _,n := range greetingTests{
        fmt.Println(n)
        if translate(n.locale) != n.want{
            t.Errorf("Greeting")
        }
    }
}

// {en-US hello}
// {fr-FR Bonjour}
// {it-IT Ciao}
// PASS
// ok      _/D_/Backup/Documents/golang    0.033s

基准测试

Go语言提供了强大的基准测试框架,能够让您使用基准测试程序来确定完成特定任务时性能最佳的方式是哪一种

  • 基准测试的函数以关键字Benchmark打头,它们接受一个类型为B的参数,并对函数进行基准测试
  • 要运行基准测试,必须在命令go test中指定标志-bench
  • 在控制台输入go test --bench=.
package example05

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

func StringAssignment(j int) string{
    var s string
    for i := 0;i<j ;i++{
        s +="a"
    }
    return s
}

func StringAppend(j int) string{
    s := []string{}

    for i:= 0 ;i<j ;i++{
        s=append(s,"a")
    }

    return strings.Join(s," ")
}

func StringBuffer(j int) string{
    var buffer bytes.Buffer
    for i:= 0;i<j ;i++{
        buffer.WriteString("a")
    }

    return buffer.String()
}

func BenchmarkStringAssignment(b *testing.B){
    StringAssignment(100000)
}

func BenchmarkStringAppend(b *testing.B){
    StringAppend(100000)
}

func BenchmarkStringBuffer(b *testing.B){
    StringBuffer(100000)
}

// goos: windows
// goarch: amd64
// BenchmarkStringAssignment-8     1000000000               0.601 ns/op
// BenchmarkStringAppend-8         1000000000               0.00600 ns/op
// BenchmarkStringBuffer-8         1000000000               0.00100 ns/op
// PASS
// ok      _/D_/Backup/Documents/golang    20.177s

提供测试覆盖率

测试覆盖率是度量代码测试详尽程度的指标,它指出了被测试代码在所有代码中的百分比

  • go test命令提供标志-cover
package test_test

import "testing"

func Greeting(s string) string{
    return s
}

func Farewell(s string) string{
    return s
}

func TestGreeting(t *testing.T){
    got := Greeting("George")
    want := "George"

    if got != want {
        t.Fatalf("falid")
    }
}
© 版权声明
THE END
喜欢就支持以下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容