Hello,定制小程序开发费用各位小伙伴,定制小程序开发费用我们今天来学习一下go的测试,定制小程序开发费用希望给各位一点点小小的帮助
定制小程序开发费用有过编程基础的,定制小程序开发费用或者工作的了,应该知道,定制小程序开发费用一个软件的质量,定制小程序开发费用三分靠开发,七分靠测试。如果没有及时发现存在的问题,将会给这个公司带来巨大的经济损失。老哥因为转Go了,所以非常有必要学习一个Go 相关的测试。
话不多说,开始学习吧。
1、在中,一共有4种测试,参考文档,
类型 | 格式 | 作用 | 传入参数 |
---|---|---|---|
单元测试 | 函数的前缀名为Test | 一个函数正常测试功能 | t *testing.T |
基准(压力测试) | 函数的前缀名为Benchmark | 通过cpu和内存,并发测试程序的性能 | b *testing.B |
实例测试 | 函数的前缀名为Example | 给测试人员提供实例文档 | m *testing.M |
模糊(随机) 测试 | 函数的前缀名为Fuzz | 生成一个随机测试用例去覆盖可能人为测不到的地方 | f *testing.F |
2、然后我们先来讲第一种,单元测试
,然后有多种写法,还支持钩子函数(我们可以在测试开始前和测试后,增加一些业务逻辑),新建一个文件 calc.go
package mainfunc Add(a int, b int) int { return a + b}func Mul(a int, b int) int { return a * b}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
3、然后是测试文件,在go语言中,所有的文件命名用_test结尾,新建一个测试文件 calc_test.go
package mainfunc TestAdd(t *testing.T) { if value := Add(1, 2); value != 3 { t.Errorf("1+2 expected be 3, but %d got", value) } if value := Mul(1, 2); value != 2 { t.Errorf("1*2 expected be 2, but %d got", value) }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
点击这个绿色图标,就可以开始测试了
除了点击绿色图标以外,我们也可以换一种方式,到当前文件夹下,打开Goland控制终端,输入下面的命令,它会执行当前文件夹所有的测试文件,并且输出详细的信息
PS D:\Project\Go_Project\testCobraPlus> go test -v
- 1
3A、单元测试如果有多个用例的话,可以试试嵌套测试,它可以分开测试
// 嵌套测试func TestMul(t *testing.T) { t.Run("pos", func(t *testing.T) { if Mul(2, 3) != 6 { t.Fatal("expected to get 6,but fail...") } }) t.Run("neg", func(t *testing.T) { if Mul(2, -3) != -6 { t.Fatal("expected to get -6,but fail...") } })}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
点击第一个,会测试全部用例,点击第二个或者第三个,它会测试你点击的那一个
5、单元测试第三种形式,也是k8s用的测试形式,它这种用要给切片存放多条数据,可以一次性测试多个值,推荐使用
func TestMul2(t *testing.T) { cases := []struct { Name string A, B, Expected int }{ {"pos", 2, 3, 6}, {"neg", 2, -3, -6}, {"zero", 2, 0, 0}, } for _, c := range cases { t.Run(c.Name, func(t *testing.T) { if value := Mul(c.A, c.B); value != c.Expected { t.Fatalf("%d * %d expected %d,but %d got", c.A, c.B, c.Expected, value) } }) }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
6、单元测试钩子,如果我们加了以下几行代码,那么当我们点击了3、3A、5任何一个测试用例,以下代码就会执行
func before() { fmt.Println("Before all tests...")}func after() { fmt.Println("After all tests...")}func TestMain(m *testing.M) { before() code := m.Run() after() os.Exit(code)}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
7、单元测试http,如果我们需要测试发送数据或者接收数据,可以采用httptest 测试库进行测试
新建一个测试文件 network_test.go
package mainimport ( "io" "net/http" "net/http/httptest" "testing")func helloHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello baidu"))}func TestConn(t *testing.T) { req := httptest.NewRequest("GET", "https://www.baidu.com/", nil) w := httptest.NewRecorder() helloHandler(w, req) bytes, _ := io.ReadAll(w.Result().Body) if string(bytes) != "hello baidu" { t.Fatal("expected hello baidu,but got", string(bytes)) }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
8、然后是基准(压力)测试,这里需要说明一下,压力测试和单元测试最大的区别是单元测试它只执行一次,成功一次就算成功,而压力测试需要执行多次,任何一次不成功都算失败
package mainimport ( "bytes" "testing")func Benchmark_Add(b *testing.B) { var n int //b.N 是基准测试框架提供的,表示循环的次数,没有具体的限制 for i := 0; i < b.N; i++ { n++ }}func BenchmarkConcatStringByAdd(b *testing.B) { //有些测试需要一定的启动和初始化时间,如果从 Benchmark() 函数开始计时会很大程度上影响测试结果的精准性。 //testing.B 提供了一系列的方法可以方便地控制计时器,从而让计时器只在需要的区间进行测试 elem := []string{"1", "2", "3", "4", "5"} b.ResetTimer() for i := 0; i < b.N; i++ { ret := "" for _, v := range elem { ret += v } } b.StopTimer()}func BenchmarkConcatStringByByteBuffer(b *testing.B) { elems := []string{"1", "2", "3", "4", "5"} b.ResetTimer() for i := 0; i < b.N; i++ { var buf bytes.Buffer for _, elem := range elems { buf.WriteString(elem) } } b.StopTimer()}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
同样,我们也可以在goland控制终端,查看执行信息,终端操作会执行当前文件夹的所有压力测试用例
goos: windows
运行在哪个操作系统上
goarch: amd64
运行操作系统的架构
cpu: 12th Gen Intel(R) Core(TM) i7-12700KF
cpu相关信息
Benchmark_Add-20 1000000000 0.1053 ns/op
Benchmark_Add我们测试的方法 20表示20个逻辑cpu,1000000000 表示执行了1000000000 次,最后一次是每一次执行需要0.1053ns
PS D:\Project\Go_Project\testCobraPlus\benchmark> go test -v -bench="." benchmark_test.gogoos: windows goarch: amd64cpu: 12th Gen Intel(R) Core(TM) i7-12700KFBenchmark_AddBenchmark_Add-20 1000000000 0.1053 ns/opBenchmarkConcatStringByAddBenchmarkConcatStringByAdd-20 20758946 57.88 ns/opBenchmarkConcatStringByByteBufferBenchmarkConcatStringByByteBuffer-20 40134450 28.70 ns/opPASSok command-line-arguments 2.694sPS D:\Project\Go_Project\testCobraPlus\benchmark>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
9、自定义测试时间,也就是测试多少秒,默认是测试1秒的压测情况
PS D:\Project\Go_Project\testCobraPlus\benchmark> go test -v -bench="." -benchtime=5s benchmark_test.gogoos: windowsgoarch: amd64cpu: 12th Gen Intel(R) Core(TM) i7-12700KFBenchmark_AddBenchmark_Add-20 1000000000 0.1051 ns/opBenchmarkConcatStringByAddBenchmarkConcatStringByAdd-20 98688592 58.19 ns/opBenchmarkConcatStringByByteBuffer BenchmarkConcatStringByByteBuffer-20 214375582 28.14 ns/opPASS ok command-line-arguments 14.921s
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
10、压力测试查看内存分配了多少,如
-bench=Add 指定尾缀是Add方法,都会执行
-benchmem 查看内存分配多少,比如下面一个方法,16 B/op 表示一次调用需要分配16个字节, 4 allocs/op 表示每一次调用有4次分配
PS D:\Project\Go_Project\testCobraPlus\benchmark> go test -v -bench=Add -benchmem benchmark_test.gogoos: windowsgoarch: amd64cpu: 12th Gen Intel(R) Core(TM) i7-12700KFBenchmark_AddBenchmark_Add-20 1000000000 0.1060 ns/op 0 B/op 0 allocs/opBenchmarkConcatStringByAddBenchmarkConcatStringByAdd-20 19738010 57.19 ns/op 16 B/op 4 allocs/opPASSok command-line-arguments 1.439s
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
11、实例测试,这个测试有点简单,写个 //Output注释,然后后面是期望输出的结果,如果是一致的,测试通过,否则测试失败
func Hello() string { return "Hello World"}//Output 需要和上面打印的内容一致,否则测试失败func ExampleHello() { fmt.Println(Hello()) // Output: Hello World}func TestMain(m *testing.M) { fmt.Println("Before...") code := m.Run() fmt.Println("End...") os.Exit(code)}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
和上面一样,我们也可以在控制台终端,进行实例测试
PS D:\Project\Go_Project\testCobraPlus\benchmark> go test -v -run="ExampleHello" Before...=== RUN ExampleHello--- PASS: ExampleHello (0.00s)PASSEnd...ok testCobraPlus/benchmark 0.125s
- 1
- 2
- 3
- 4
- 5
- 6
- 7
12、模糊测试,这是go1.18新推出的测试用例,如果我们没有指定参数,系统会随机填入参数进行测试
func FuzzStrToNum(f *testing.F) { f.Fuzz(func(t *testing.T, a string) { b, _ := strconv.ParseInt(a, 10, 64) fmt.Printf("%d\", b) })}
- 1
- 2
- 3
- 4
- 5
- 6
func FuzzDivision(f *testing.F) { f.Fuzz(func(t *testing.T, a, b int) { fmt.Println(a / b) })}
- 1
- 2
- 3
- 4
- 5
//我们可以在模糊测试中,自己定义参数进去func FuzzHello(f *testing.F) { f.Add(1) f.Fuzz(func(t *testing.T, num int) { if num != 6 { t.Errorf("expected 6,but got %d", num) } })}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
模糊测试同样支持控制台输入,但是同一个文件只能有一个模糊函数测试
PS D:\Project\Go_Project\testCobraPlus\benchmark> go test -fuzztime 10s -fuzz .
- 1
13、最后,各位小伙伴,麻烦给老哥一个点赞、关注、收藏三连好吗,你的支持是老哥更新最大的动力,谢谢!