定制小程序开发费用Golang 编写测试用例(单元测试、压力测试等)最新教程,细到极致

   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、最后,各位小伙伴,麻烦给老哥一个点赞、关注、收藏三连好吗,你的支持是老哥更新最大的动力,谢谢!

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发