main.go
// Go语言·单元测试
package main
// 包的本质是创建不同的文件夹
// go的每一个文件都是属于一个包的
// go以包的形式管理项目和文件目录。
// import "包的路径"
import (
model "day29/model"
)
var content string = `
————————————————Go语言·单元测试————————————————————
一、单元测试
测试用例(Test Case)
1.传统的方式进行测试:
在main函数中,调用函数,看看实际执行结果是否正确
不方便
不利于管理
2.单元测试 testing 测试框架
go test 单元测试,性能测试。
二、单元测试基本介绍
1.确保每个函数是可运行的,并且运行结果是正确的
2.确保写出来的代码性能是好的
3.单元测试能及时的发现程序设计或实现的逻辑错误,使
问题尽早暴露,便于问题的定位解决,而性能测试的重点
在于发现程序设计的一些问题,让程序能够在高并发的情
况下还能保持稳定。
三、注意事项:
1.测试用例文件名必须以_test.go结尾,
比如:Utils_test.go,Utils不是固定的
2.测试用例函数必须以Test开头,
一般来说就是Test+被测试函数名(函数名首字母大写)
3.测试用例函数的形参类型是 t *testing.T
4.一个测试用例文件中,可以有多个测试用例函数,比如:TestSum、TestHello
5.运行测试用例指令:
1)cmd>go test [如果正确运行,无日志,错误时,会输出日志]
2)cmd>go test -v [运行正确或错误,都输出日志]
6.当出现错误时,可以用t.Fatalf来格式化输出错误信息,并退出程序
7.t.Logf方法可以输出相应的日志
8.测试用例函数,并没有放在main函数中,也执行咯,原因:
运行测试用例指令
先import "所有的xxx_test.go"
会在main中调用"所有TestXxx"函数
在"TestXxx"函数运行对应的函数。
逐一完成测试,并输出结果
9.PASS表示测试用例运行成功,FAIL表示测试用例运行失败
10.测试单个文件:一定要带上被测试的原文件
go test -v Sub_test.go Utils.go
11.测试单个函数:
go test -v -test.run TestSum
`
func main() {
model.Entry()
}
Utils_test.go
package model
import (
"testing"
)
func TestSum(t *testing.T) {
res := sum(10)
if res != 55 {
t.Fatalf("sum(10) 执行错误,期望值:%v,实际值:%v \n",55,res)
}
t.Logf("sum(10) 执行正确...")
}
func TestHello(t *testing.T) {
t.Logf("TestHello running...")
}
// go test -v -test.run TestStore
func TestStore(t *testing.T) {
CreatMonster("小可爱",18,"嘤嘤拳").Store()
ok,_ := exists(filepath)
if !ok {
t.Fatalf("mon.Store() 执行错误,数据保存失败!\n")
}
t.Logf("mon.Store() 执行成功,数据已写入文件...")
}
// go test -v -test.run TestRestore
func TestRestore(t *testing.T) {
ok,err := CreatMonster("",0,"").Restore()
if !ok {
t.Fatalf("mon.Restore() 数据恢复失败:%v!\n",err)
}
t.Logf("mon.Restore() 数据恢复成功...")
}
Monster.go
package model
import (
"bufio"
"encoding/json"
"errors"
"fmt"
_ "io"
"os"
)
type Monster struct {
Name string `json:"name"`
Age int `json:"age"`
Skill string `json:"skill"`
}
var filepath = "D:/日常工作/go/src/day29/data/data.json"
func CreatMonster(name string, age int, skill string) *Monster {
return &Monster{
Name: name,
Age: age,
Skill: skill,
}
}
/**
* [Store 存储]
* @author Jhou Shuai
* @datetime 2019-06-11T12:15:56+0800
*/
func (this *Monster) Store() {
data, err := json.Marshal(this)
if err != nil {
return
}
file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
return
}
// 及时关闭句柄,否则会有内存泄漏
defer file.Close()
content := string(data)
// *writer 使用带缓存的。
writer := bufio.NewWriter(file)
writer.WriteString(content)
// 将缓存中的数据,写入的文件
writer.Flush()
}
/**
* [Restore 读取,恢复,显示]
* @author Jhou Shuai
* @datetime 2019-06-11T12:15:42+0800
*/
func (this *Monster) Restore() (bool, error) {
ok, _ := exists(filepath)
if !ok {
return false, errors.New("File not exist")
}
file, err := os.OpenFile(filepath, os.O_RDONLY, 0666)
if err != nil {
return false, err
}
// 及时关闭句柄,否则会有内存泄漏
defer file.Close()
// 显示终端
// 第一种方式: bufio.NewReader(file)
// reader :=bufio.NewReader(file)
// for {
// line, err := reader.ReadString('\n') //以'\n'为结束符读入一行
// if err != nil || io.EOF == err {
// if line == ""{
// break
// }
// }
// err = json.Unmarshal([]byte(line),this)
// if err!=nil{
// return false,err
// }
// fmt.Println(this)
// }
//
// 第二种方式: bufio.NewScanner(file)
scanner := bufio.NewScanner(file)
for scanner.Scan() && scanner.Text() != "" {
line := scanner.Text()
err = json.Unmarshal([]byte(line), this)
if err != nil {
return false, err
}
fmt.Println(this)
}
return true, nil
}