dedecms 企业网站,wordpress tag页面,搜索引擎优化的五个方面,船舶cms是什么意思没有后端基础#xff0c;学起来真是费劲#xff0c;所以打算速刷一下#xff0c;代码跟着敲一遍#xff0c;有个印象#xff0c;大项目肯定也做不了了#xff0c;先把该学的学了#xff0c;有空就跟点单体项目#xff0c;还有该看的书....
目录
#x1f34c;单元测试…没有后端基础学起来真是费劲所以打算速刷一下代码跟着敲一遍有个印象大项目肯定也做不了了先把该学的学了有空就跟点单体项目还有该看的书....
目录
单元测试
assert
覆盖率
tips
依赖
文件处理
Mock测试
基准测试
项目实战
ER图
分层结构
组件工具
Repository
Service
Controller
Router
运行 单元测试
规则 1测试文件以 _test.go 结尾 源代码与测试代码 2测试函数命名规范func TestXxx(*testing.T) Test紧挨着第一个字母大写 3初始化逻辑放到TestMain()里 assert 导入开源网站的assert包来进行判等不等等测试操作 单元测试的样例 judge.go
package judgefunc JudgePassLine(score int16) bool {if score 60 {return true}return false
}judge_test.go
package judgeimport (github.com/stretchr/testify/asserttesting
)func TestJudgePassLineTrue(t *testing.T) {isPass : JudgePassLine(70)assert.Equal(t, true, isPass)
}Run一下 解释 testing.T 是 Go 语言测试框架中的一个结构体类型它提供了一组方法和属性用于管理和报告测试的结果。当你编写和运行测试函数时测试框架会自动创建一个 testing.T 类型的实例并将其传递给测试函数 覆盖率
当我们写了单元测试后 覆盖率越高代码的质量越有保证那如何查看覆盖率呢 PS发现个Goland小技巧ctrl z可以返回上一步代码误删了也不要紧 要查看覆盖率首先要切到对应目录下视频中是 但我只会先cd到对应目录结果一样 覆盖率意味着 judge.go函数中一共3行有效代码但是judge_test.go传入的70只会运行前2行所以覆盖率是 2 / 3
当我们需要100%覆盖率只需要增加一个测试分支
func TestJudgePassLineFail(t *testing.T) {isPass : JudgePassLine(50)assert.Equal(t, true, isPass)
} 通过不断地对各个分支的测试保证了测试的完备性 减少了BUG的产生
tips 依赖 DB数据库database CacheRedis类似的组件 File本地文件 三项属于项目中的强依赖 在单元测试中一般有2个目标1幂等 2稳定 1幂等多次重复一个case的测试结果一样 2稳定单元测试之间是相互隔离的即任何时间 / 函数下都能够运行 而需要保证幂等 / 稳定需要Mock机制下面先讲文件处理 文件处理
log
line11
line22
line33
line44
line55
ProcessFirstLine.go
package firstLineimport (bufioosstrings
)// ReadFirstLine 从文件中读取第一行内容
func ReadFirstLine() string {open, err : os.Open(log) // 打开名为 log 的文件defer open.Close() // 延迟关闭文件, 避免资源泄露if err ! nil {return // 发生错误时返回空字符串}scanner : bufio.NewScanner(open) // 创建一个扫描器for scanner.Scan() { // 循环遍历文件的每一行return scanner.Text() // 返回第一行内容}return // 文件为空时返回空字符串
}// ProcessFirstLine 处理第一行内容将 11 替换为 00
func ProcessFirstLine() string {line : ReadFirstLine() // 调用 ReadFirstLine 函数获取第一行内容destLine : strings.ReplaceAll(line, 11, 00) // 将 11 替换为 00return destLine // 返回替换后的结果
}ProcessFirstLine_test.go
package firstLineimport (github.com/stretchr/testify/asserttesting
)// TestProcessFirstLine 是对 ProcessFirstLine 函数的单元测试
func TestProcessFirstLine(t *testing.T) {firstLine : ProcessFirstLine() // 调用 ProcessFirstLine 函数assert.Equal(t, line00, firstLine) // 使用断言验证结果是否符合预期
}equal还是报错但是点击这里还是可以PASS 解释 1bufio高效读取数据的包 bufio.NewReader()创建一个新的Reader对象用于读取数据。它接收一个io.Reader类型的参数并使用默认大小的缓冲区bufio.NewScanner()创建一个新的Scanner对象用于对输入流进行扫描。Scanner可用于逐行读取文本等Reader类型它提供了各种方法来从输入流中读取数据如ReadString()用于读取字符串ReadBytes()用于读取字节切片等Scanner类型它提供了各种方法来解析输入流中的数据如Scan()用于逐行读取文本ScanBytes()用于逐个字节读取等Scanner.Text()返回当前扫描的文本内容Scanner.Scan()将扫描器移动到下一行并返回是否还有更多行可供扫描 2os是一个提供与操作系统相关功能的包 os.Args一个字符串切片包含命令行参数os.Exit(code int)终止当前程序的执行并返回给定的错误码os.Getwd()返回当前的工作目录的路径名os.Chdir(dir string)将当前的工作目录更改为指定的目录os.Mkdir(name string, perm FileMode) error创建一个新目录os.Open(name string) (*File, error)打开一个文件用于读取os.Create(name string) (*File, error)创建一个文件用于写入os.Remove(name string) error删除指定的文件或目录os.Rename(oldname, newname string) error重命名移动文件或目录os.Stdout、os.Stdin、os.Stderr标准输出、标准输入和标准错误输出的文件对象 但是如果源文件被人篡改那么测试文件在特定场景下也就无法运行那如何Mock呢
Mock测试 开源Mock测试包 -- bouk/monkey: Monkey patching in Go (github.com) 打桩即用函数A替换函数B 不得不吐槽一下内部课贴的代码只贴部分默认剩下部分你都会了没学过也不能无中生有吧...真的觉得每一点代码都力求自己得到对应输出有点浪费时间了先速通吧...
基准测试
看了一遍...
项目实战
描述 用例 用户浏览页面主要展示2方面内容一是Topic话题一是PostList回帖的列表 ER图 Entity Relationship Diagram ER图由以下三个主要组成部分构成实体属性关系。 分层结构 数据层数据Model外部数据的增删改查 逻辑层业务Entity 视图层视图view处理和外部的交互逻辑 组件工具 1Gin高性能 go web 框架 gin-gonic/gin: Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin. (github.com) 2Go mod go mod init go get gopkg.in/gin-gonic/gin.v1v1.3.0 -- 执行后go.mod就有gin的依赖了 Repository
index 两个索引 初始化话题数据索引 package main //入口import (bufio //缓冲读取encoding/json //处理JSON数据os //操作系统交互
)// 初始化主题索引映射
func initTopicIndexMap(filePath string) error {open, err : os.Open(filePath topic) //打开文件filePathif err ! nil { //打开错误return err}scanner : bufio.NewScanner(open) //逐行扫描的工具topicTmpMap : make(map[int64]*Topic) //值是指向Topic结构体的指针for scanner.Scan() {text : scanner.Text() //保存每行内容var topic Topicif err : json.Unmarshal([]byte(text), topic); err ! nil {return err //json.Unmarshal将text解析为Topic结构体}topicTmpMap[topic.Id] topic //保存解析的结构体保}topicIndexMap topicTmpMap //映射赋值给全局变量return nil
}查询 package mainimport (bufio //缓冲读取encoding/json //处理JSON数据os //操作系统交互sync
)// 声明一个全局变量 topicIndexMap用于存储主题索引映射
var topicIndexMap map[int64]*Topic// Topic 定义 Topic 结构体包含了主题的属性
type Topic struct {Id int64 json:idTitle string json:titleContent string json:contentCreateTime int64 json:create_time
}// TopicDao 定义 TopicDao 结构体
type TopicDao struct {
}var (topicDao *TopicDaotopicOnce sync.Once
)// NewTopicDaoInstance 函数返回一个 TopicDao 实例
func NewTopicDaoInstance() *TopicDao {topicOnce.Do(func() {topicDao TopicDao{}})return topicDao
}// QueryTopicById 方法根据 id 查询并返回对应的 Topic 实例
func (*TopicDao) QueryTopicById(id int64) *Topic {return topicIndexMap[id]
}// 初始化主题索引映射
func initTopicIndexMap(filePath string) error {open, err : os.Open(filePath topic) //打开文件filePathif err ! nil { //打开错误return err}scanner : bufio.NewScanner(open) //逐行扫描的工具topicTmpMap : make(map[int64]*Topic) //值是指向Topic结构体的指针for scanner.Scan() {text : scanner.Text() //保存每行内容var topic Topicif err : json.Unmarshal([]byte(text), topic); err ! nil {return err //json.Unmarshal将text解析为Topic结构体}topicTmpMap[topic.Id] topic //保存解析的结构体保}topicIndexMap topicTmpMap //映射赋值给全局变量return nil
}
Service 定义两个实体 流程 流程代码 //Do 方法执行查询页面信息的流程返回 PageInfo 实例和错误信息
func (f *QueryPageInfoFlow) Do() (*PageInfo, error) {if err : f.checkParam(); err ! nil { //参数校验return nil, err //校验失败}if err : f.prepareInfo(); err ! nil { //准备数据return nil, err}if err : f.packPageInfo(); err ! nil { //组装实体return nil, err}return f.pageInfo, nil //返回 PageInfo 实例和 nil操作成功
} Controller ....看了一遍.... Router 运行 end....