Go核心开发学习笔记(廿七) —— 单元测试

单元测试作用:确认一个函数或者一个package引入后的结果是否正确。

传统方法:测试输出的结果是否和预期结果一致,
有些东西要放在生产环境做,才能有效,测试环境下没有这种环境;
不利于管理,所以需要测试框架来解决上述问题。

Golang中带有一个轻量级的测试框架testinggo test测试命令来实现单元测试和性能测试(执行代码花费时间)。
通过单元测试解决下面问题:

  1. 确保每个函数是可运行,并且结果输出时正确的。
  2. 确保写出来的代码性能是好的
  3. 单元测试能及时发现程序设计和实现的逻辑错误,使用问题及早暴露,便于问题的定位解决。
  4. 性能测试的重点在于程序设计上的一些问题,让程序能够在高并发的情况下还能保持稳定。

单元测试的使用

  1. 测试单独建立一个文件夹,用来和main()隔离,测试文件的运行不需要main()入口。
  2. .go测试文件中的函数,提取到_test.go文件中,_test.go需要import Testing包。

示例:

	package tst
	import "testing"

	func Test<dest>(t *testing.T) {
		//引入测试函数1
		//引入测试函数2
	}

案例模拟:创建一个tst包,然后在里面写入两个文件,Accumu.go和Accumu_test.go,两个文件写法如下

Accumu.go

	//>>> Accumu.go <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	
	package tst
	
	func Accumu(n int) int {        //就是一个累加器,没啥说得,没有main()
		res := 0
		for i := 0 ; i <= n ; i++ {
			res += i
		}
		return res
	}                 

Accumu_test.go

	//>>> Accumu_test.go <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

	//测试单个文件:切换到此目录下,go test -v会默认测试所有函数,如果只想测试其中一个,需要命令 go test -v Accumu_test.go Accumu.go
	//测试单个方法:切换到此目录下,需要命令 go test -v -test.run Accumu
	
	package tst

	import (
		"testing"       //需要导入testing包
	)

	func TestAccumu(t *testing.T) {    //在Goland中,默认test文件都会直接出此类格式
		res := Accumu(10)              //测试结果与res所传函数有关,与函数名无关
		if res != 55 {
			t.Fatalf("应输入值为%v,实际输出为%v",55,res)   //遇到错误即终止,并会反馈结果为FAIL
		}
		t.Logf("程序测试正确!")    //如果测试无异常则打印PASS,后面日志为t.logf()中的字符串内容
	}                   //关于测试结果,Goland中测试文件都会有一个红色箭头,因此无需黑屏终端go test命令来使用

测试结果如下:

/*
e:\Golear\src\tst>go test -v
=== RUN   TestAccumu
--- PASS: TestAccumu (0.00s)
    cal_test.go:12: 程序测试正确!
PASS
ok      _/e_/Golear/src/tst     0.536s

e:\Golear\src\tst>go test -v -test.run Accumu
=== RUN   TestAccumu
--- PASS: TestAccumu (0.00s)
    cal_test.go:12: 程序测试正确!
PASS
ok      _/e_/Golear/src/tst     0.607s
*/

序列化和反序列化+文件使用+单元测试 结合实战应用:

需求:创建一个结构体:Heros
字段:Name string, Age int, Hobby string
方法:Store()将结构体变量序列化后保存到文件kunkun.txt中
RevStore()将结构体变量从文件kunkun.txt汇总读取并反序列化
单元测试:测试上述两个方法是否正常。

核心代码段:(假设作为生产,不可以轻易测试)

package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
)

type KunFamily struct {
	Name string `json:"name"`
	Age int `json:"age"`
	Hobby string `json:"hobby"`
}

func (k *KunFamily) Store() bool {       //为了确保测试,故返回布尔值
	slice, err := json.Marshal(k)
	if err != nil {
		fmt.Println("序列化失败,失败原因为: ",err)
		return false
	}

	file, err := os.OpenFile("D:/kunkun.txt", os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println("请检查错误为:", err)
		return false
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	_, _ = writer.WriteString(string(slice))
	_ = writer.Flush()
	return true
}

func (k *KunFamily) RevStore() bool {      //为了确保测试,故返回布尔值
	//读取文件
	file := "D:/kunkun.txt"
	content, err := ioutil.ReadFile(file)
	if err != nil {
		fmt.Println("读取错误,错误为:", err)
		return false
	}
	//反序列化
	err1 := json.Unmarshal([]byte(content), k)      //err := json.Unmarshal([]byte(string), &<struct结构体变量>)
	if err1 != nil {
		fmt.Println("反序列化出现异常,异常报错为:",err1)
		return false
	}
	return true
}

func main() {
	var caixukun1  = &KunFamily{"蔡徐坤1",20,"鸡你太美"}
	caixukun1.Store()
	caixukun1.RevStore()
}

被测试文件写法:(从生产代码段摘出,x.go)

package tst
import (
	"bufio"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
)

type KunFamily struct {
	Name string `json:"name"`
	Age int `json:"age"`
	Hobby string `json:"hobby"`
}
func (k *KunFamily) Store() bool {
	slice, err := json.Marshal(k)
	if err != nil {
		fmt.Println("序列化失败,失败原因为: ",err)
		return false
	}

	file, err := os.OpenFile("D:/kunkun.txt", os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println("请检查错误为:", err)
		return false
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	_, _ = writer.WriteString(string(slice))
	_ = writer.Flush()
	return true
}
func (k *KunFamily) RevStore() bool {
	file := "D:/kunkun.txt"
	content, err := ioutil.ReadFile(file)
	if err != nil {
		fmt.Println("读取错误,错误为:", err)
		return false
	}

	err1 := json.Unmarshal([]byte(content), k)      //err := json.Unmarshal([]byte(string), &<struct结构体变量>)
	if err1 != nil {
		fmt.Println("反序列化出现异常,异常报错为:",err1)
		return false
	}
	return true
}

测试文件写法:(x_test.go)

package tst

import (
	"testing"
	)

func TestKunFamily_Store(t *testing.T) {
	var caixukun  = &KunFamily{"蔡徐坤1",20,"鸡你太美"}
	res := caixukun.Store()
	if res != true {
		t.Fatalf("测试失败")
	}
	t.Logf("程序测试正确!")
}

func TestKunFamily_RevStore(t *testing.T) {
	var caixukun  = &KunFamily{"蔡徐坤1",20,"鸡你太美"}
	res := caixukun.RevStore()
	if res != true {
		t.Fatalf("测试失败")
	}
	t.Logf("程序测试正确!")
}
发布了49 篇原创文章 · 获赞 18 · 访问量 3998

猜你喜欢

转载自blog.csdn.net/weixin_41047549/article/details/90477305