(三)工程实践|测试|青训营笔记

134 阅读1分钟

2 工程实践

3 测试

3.1 测试粒度

从上至下覆盖率逐层增大,成本降低

回归测试:QA同学通过终端回归固定场景

集成测试:对系统功能

单元测试:面对测试开发阶段,对函数模块测试

3.2 Mock

工具: monkey

可以实现用打桩函数替换原函数,不依赖本地文件进行测试

func Patch

func Unpatch(){ //卸载打桩函数
	...
}
实际使用是 defer monkey.Unpatch(functionName)

在运行时,将运行中函数的地址替换成打桩函数,并且手动设置输入和预期结果

3.3 基准测试 bench

测试程序性能和cpu的损耗

//函数传入参数是 b *testing.B
b.ResetTimer()
//串行测试就正常执行
for i := 0; i < b.N; i++ {
		Select()
}

//并行测试需使用函数 b.RunParallel()
b.RunParallel(func(pb *testing.PB){
  for pb.Next(){
    Select()
  }
})

实验表明,并行测试时性能反而更差,因为Select()中有rand函数,随机函数持有全局锁,降低了并发的性能,可通过使用fastrand()改进

4 项目开发

需求用例
type Topic struct{
  Id int64 `json:"id"`
  Title string `json:"title"`
  Content string `json:"content"`
  CreateTime int64 `json:"create_time"`
}

type Post struct{
  Id int64 `json:"id"`
  TopicId int64 `json:"topic_id"`
  Content string `json:"content"`
  CreateTime int64 `json:"create_time"`
}
分层结构

由下自上分别是以下三部分,

Repository:数据层主要面向service层,对其透明,底层实现改变对其接口Model可不改变

Service:接收Repository的数据作打包封装,形成Entity

Controller:包装上游的数据格式,形成API

具体实现

Repository:

​ read data from file or database and form aimed data structure

​ define the function DaoInstance() and corresponding method

​ Dao:

sync.Once是单例模式的运用,适用于高并发场景,减少存储的浪费

Service:

​ 实现逻辑:参数校验(合法性) -> 准备数据 -> 组装实体

​ use the funciton of repository to query data and check validity

Controller:

​ focus more on error handling

5 课后作业

几个关键点

​ 新增发布帖子功能

​ 本地Id生成需要保证唯一性

​ Append文件,更新索引,注意Map的并发安全问题

思考及实现

按分层结构增加代码

首先是repository层

- 在db_init增加rwMUTEX
- 在post文件增加InitPost(),主要逻辑是现在文件内写入,然后加锁保护,根据是否已存在主题加入到索引

其次是service层

  • 单独增加publish_post.go
  • 关键性的id问题使用了包idWorker

然后是controller层

  • 单独增加publish_post.go
  • 增加方法

最后在server.go中增加POST方法