测试左移的思想,讲究尽早测试,测试是一系列的行为,并不一定要等代码运行起来才能测,下面会分享一些经验,提供大家参考。
一、静态分析
1.1 分析方法调用链
目标:梳理结构,化繁为简
原理:相同数据源,相同方法(逻辑),无需进行重复测试
举例:通用榜单项目,多个不同入口,榜单前置预检逻辑:
1.2 代码阅读
目标:补充技术文档中未涉及部分&确认代码和文档的匹配一致性;
原理:不能自洽的部分,读着读着就发现问题了(可以自己读,也可以和开发一起读)
举例:涉及代码段,不太方便举例子
1.3 可以直接被review出来的常见错误
- 容易遗漏的一般是:系统行为、异常处理、排序逻辑;
- 容易出错的一般是:硬编码、方法的调用方和方法定义不一致(方法名和执行命令名不一致、方法名和kv设计不一致)、逻辑错误(缺少结束返回值、变量赋值错误)、接口文档和实际接口结构体,字段定义不一致、边界值处理;
- 条件逻辑错误:比如go语言的“&&”乱用;
- msg_id和redis幂等键书写取值错误:redis锁使用了秒级时间戳(秒级锁相当于一个失败的锁);
//总的来说,多关注下内部数据流转链路、并发的设计。//
二、代码“异味”
有的问题,属于能用但是很烂,我们可以借助一些工具来辅助。
不同语言,适用的检测工具是不同的,因为本司接触go比较多一些,故而以下可以适用于go。
2.1 GolangCi-lint
1、谷歌、脸书、IBM、雅虎等公司均采用
2、下载方便,速度快,可与sublime,vscode等编辑器整合
3、聚合48种linters,扫描规则丰富
2.2 SonarQube集成GolangCi-lint
2.2.1 docker 安装SonarQube
- 拉取postgre镜像:
docker pull postgres
- 拉取sonarqube镜像:
docker pull sonarqube
- 启动postgre容器:
docker run --name db
-e POSTGRES_USER=sonar -e POSTGRES_PASSWORD=sonar
-d postgres
- 挂载目录赋权:
chown -R 999:999 sonarqube_data sonarqube_extensions sonarqube_logs sonarqube_conf
//注:docker内部使用sonarqube用户,如果不改权限,挂载本地目录会报错,sonarqube内部使用的默认用户名分组为999
- 启动sonar容器:
docker run --name sonarqube \
--link db \
-e SONARQUBE_JDBC_USERNAME=sonar -e SONARQUBE_JDBC_PASSWORD=sonar \
-e SONARQUBE_JDBC_URL=jdbc:postgresql://db:5432/sonar \
-v $PWD/sonarqube_data:/opt/sonarqube/data \
-v $PWD/sonarqube_extensions:/opt/sonarqube/extensions \
-v $PWD/sonarqube_logs:/opt/sonarqube/logs \
-v $PWD/sonarqube_conf:/opt/sonarqube/conf \
-p 9000:9000 \
-d --privileged=true sonarqube
2.2.2 安装静态代码扫描工具golangci-lint
通过github获取指定版本:https://github.com/golangci/golangci-lint/releases
本地安装:
- mac brew 安装:
brew install golangci-lint
or
brew install golangci/tap/golangci-lint
- Linux和Windows:
# binary will be $(go env GOPATH)/bin/golangci-lint
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.39.0golangci-lint --version
- 使用golangci-lint开始执行扫描:
$ cd go-live/app/service/live-reward/internal/service
$ golangci-lint run -v --out-format checkstyle > golangcilint.xml
- 控制台信息如下:
$ mauer@MabledeMacBook-Pro service % golangci-lint run -v --out-format checkstyle > golangcilint.xml
INFO [config_reader] Config search paths: [./ /Users/mauer/go/src/bilibili/go-live/app/service/live-reward/internal/service]
INFO [lintersdb] Active 10 linters: [deadcode errcheck gosimple govet ineffassign staticcheck structcheck typecheck unused varcheck]
INFO [loader] Go packages loading at mode 575 (types_sizes|deps|imports|name|compiled_files|exports_file|files) took 585.760604ms
INFO [runner/filename_unadjuster] Pre-built 0 adjustments in 3.390498ms
INFO [linters context/goanalysis] analyzers took 0s with no stages
INFO [runner/max_same_issues] 17/20 issues with text "unusedresult: result of fmt.Sprintf call not used" were hidden, use --max-same-issues
INFO [runner] Issues before processing: 44, after processing: 6
INFO [runner] Processors filtering stat (out/in): diff: 23/23, max_per_file_from_linter: 23/23, max_from_linter: 6/6, sort_results: 6/6, cgo: 44/44, skip_files: 44/44, autogenerated_exclude: 44/44, nolint: 43/43, uniq_by_line: 23/43, severity-rules: 6/6, path_prefixer: 6/6, filename_unadjuster: 44/44, path_prettifier: 44/44, skip_dirs: 44/44, exclude: 44/44, source_code: 6/6, path_shortener: 6/6, identifier_marker: 44/44, exclude-rules: 43/44, max_same_issues: 6/23
INFO [runner] processing took 4.739912ms with stages: nolint: 2.471254ms, exclude-rules: 874.552µs, identifier_marker: 520.534µs, path_prettifier: 425.545µs, skip_dirs: 149.956µs, source_code: 128.702µs, autogenerated_exclude: 121.867µs, max_same_issues: 23.073µs, uniq_by_line: 10.309µs, cgo: 4.657µs, max_from_linter: 2.591µs, filename_unadjuster: 2.188µs, max_per_file_from_linter: 1.967µs, path_shortener: 1.246µs, diff: 317ns, skip_files: 269ns, severity-rules: 264ns, sort_results: 257ns, exclude: 232ns, path_prefixer: 132ns
INFO [runner] linters took 206.589753ms with stages: goanalysis_metalinter: 201.585771ms
INFO File cache stats: 4 entries of total size 62.1KiB
INFO Memory: 10 samples, avg is 72.1MB, max is 72.6MB
INFO Execution took 809.232544ms
2.2.3 使用sonar-scanner集成golangci-lint报告
$ cd go-live/app/service/live-reward/internal/service
$ sonar-scanner-Dsonar.projectKey = live-reward \-Dsonar.sources .\-Dsonar.host.url = http://192.168.0.20:9000 \-Dsonar.login = 8113d659484bea6a600cc2d080e546f7df8a7b60
如果使用sonar-project.properties则无需指定配置参数:
$ cd go-live/app/service/live-reward/internal/service
$ sonar-scanner
控制台信息如下:
$ mauer@MabledeMacBook-Pro service % sonar-scanner
WARN: * golangcilint.xml
INFO: Analysis report generated in 61ms, dir size=326 KB
INFO: Analysis report compressed in 61ms, zip size=94 KB
INFO: Analysis report uploaded in 274ms
INFO: ANALYSIS SUCCESSFUL, you can browse http://192.168.0.20:9000/dashboard?id=live-reward
INFO: Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
INFO: More about the report processing at http://192.168.0.20:9000/api/ce/task?id=AXWJy_nPVL3yjLKDbznj
INFO: Analysis total time: 6.570 s
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 7.569s
INFO: Final Memory: 13M/50M
INFO: ------------------------------------------------------------------------
2.2.4 sonar配置文件
#----- Default SonarQube server
sonar.host.url=http://192.168.0.20:9000
#----- 需要扫描的服务名称(相同key不会创建新项目)
sonar.projectKey=live-reward
sonar.projectName=live-reward#----- sonar服务安全令牌口令
sonar.login=8113d659484bea6a600cc2d080e546f7df8a7b60#----- GolangCI-Lint报告文件路径
sonar.go.golangci-lint.reportPaths=golangcilint.xml#----- Default source code encoding
sonar.sourceEncoding=UTF-8sonar.sources=.
2.2.5 SonarQube查看扫描报告
报告总览:
报告详情: