买东西的网站都有哪些,聊城哪里可以学网站建设呢,网站备案审批号,app搭建开发Golang中的单元测试需求传统方法基本介绍单元测试快速入门总结综合案例需求
在工作中#xff0c;我们会遇到这样的情况#xff0c;就是去确认一个函数#xff0c;或者一个模块的结果是否正确
传统方法
在main函数中#xff0c;调用addUpper函数#xff0c;看看实际输出…
Golang中的单元测试需求传统方法基本介绍单元测试快速入门总结综合案例需求
在工作中我们会遇到这样的情况就是去确认一个函数或者一个模块的结果是否正确
传统方法
在main函数中调用addUpper函数看看实际输出的记过是否和预期的结果一直如果一直则说明函数正确否则函数有错误然后修改错误
缺点
1.不方便我们需要在main函数中区调用这样就需要去修改main函数如果现在项目在运行就可能去停止项目2.不利于管理因为我们测试多个函数或者多个模块时都需要写在main函数不利于我们管理和清晰思路3.引出单元测试----testing测试框架可以很好解决问题
基本介绍
Go语言中自带有一个轻量级的测试框架testing和自带的 go test命令来实现单元测试和性能测试testing框架和其他语言中的测试框架类似可以基于这个框架写针对相应函数的测试用例(test case也可以基于该框架写相应的压力测试用例。通过单元测试可以解决如下问题
1.确保每个函数是可运行并且运行结果是正确的2.确保写出来的代码性能是好的3.当官测试能及时的发现程序设计或实现的逻辑错误是问题及早暴露便于问题的定位解决而性能测试的重点在于发现程序设计色很的一些问题让程序能够在高并发的情况下还能保持稳定
cla.go包
package main//一个测试函数
func addUpper(n int) int {res : 0for i : 0; i n; i {res i}return res}
cal_test.go包
package mainimport testing //引入go的testing框架包//编写一个测试用例去测试addUpper是否正确
func TestAddUpper(t *testing.T) {//调用res : addUpper(10)if res ! 55 {t.Fatalf(AddUpper(10)执行错误期望值%v 实际值%v, 55, res)}//如果正确输出日志t.Logf(AddUpper(10)执行正确)
}
/*RUN TestAddUppercal_test.go:13: AddUpper(10)执行正确
--- PASS: TestAddUpper (0.00s)
PASS
*/单元测试快速入门总结
1.测试用例文件名必须以_test.go结尾。比如cal_test.gocal不是固定的2.测试用例函数必须以Test开头一般来说就是Test被测试的函数名比如TestAddUpper3.TestAddUpper(t *testing.T)的形参类型必须是 *testing.T4.一个测试用例文件中可以有多个测试用例函数比如TestAddUpper, TestSub5.运行测试用例指令 cmdgo test[如果运行正确无日志错误时会输出日志]cmdgo test -v [运行正确或者是错误都输出日志] 6.当出现错误时候可以使用t.Fatalf来格式化输出错误信息并退出程序7.t.Logf方法可以输出相应的日志8.测试用例函数并没有放在main函数中也执行了这就是测试用例的方便之处9.PASS表示测试用例运行成功FALL表示测试用例运行失败10.测试单个文件一定要带上被测试的原文件 go test -v cal_test.go cal.go11.测试单个方法 go test -v -test.run TestAddUpper
综合案例
1.编写一个Monster结构体字段NameAgeSkill2.给MOnster绑定方法Store可以将一个Monster变量(对象)序列化后保存到文件中3.给Monster绑定方法ReStore,可以将一个序列化的Monster从文件中读取并反序列化为Monster对象检测反序列化名字是否正确4.编程测试用例文件store_test.go编写测试用例函数TestStore和TestRestore进行测试
//monster.go
package monsterimport (encoding/jsonfmtio/ioutil
)type Monster struct {Name stringAge intSkill string
}//给monster绑定方法store可以将一个monster变量(对象),序列化后保存到文件中
func (this *Monster) Store() bool {//先序列化data, err : json.Marshal(this)if err ! nil {fmt.Println(marshal err, err)return false}//保存到文件filePath : d:/monster.sererr ioutil.WriteFile(filePath, data, 0666)if err ! nil {fmt.Println(write file err, err)return false}return true
}//给Monster绑定方法ReStore,可以将一个序列化的Monster
//从文件中读取并反序列化为Monster对象检测反序列化名字是否正确
func (this *Monster) ReStore() bool {//先从文件中读取序列化的字符串filePath : d:/monster.serdata, err : ioutil.ReadFile(filePath)if err ! nil {fmt.Println(ReadFile err , err)return false}//使用读取到data []byte,对反序列化err json.Unmarshal(data, this)if err ! nil {fmt.Println(unmarshal err, err)return false}return true
}//monster_test.go
package monsterimport testing//测试用例测试store方法
func TestStore(t *testing.T) {monster : Monster{Name: kunkun,Age: 25,Skill: rap,}res : monster.Store()if !res {t.Fatalf(monster.store() 错误希望为%v 实际为%v, true, res)}t.Logf(monster.store()测试成功)}func TestMonster(t *testing.T) {//先创建一个monster实例不需要指定字段的值var monster Monster{}res : monster.ReStore()if !res {t.Fatalf(monster.restore() 错误希望为%v 实际为%v, true, res)}//进一步判断if monster.Name ! kunkun {t.Fatalf(monster.restore() 错误希望为%v 实际为%v, kunkun, monster.Name)}t.Logf(monster.restore()测试成功)
}
/*RUN TestStoremonster_test.go:16: monster.store()测试成功
--- PASS: TestStore (0.00s)RUN TestMonstermonster_test.go:31: monster.restore()测试成功
--- PASS: TestMonster (0.00s)
PASS
*/