Go语言工程实践之测试 | 青训营笔记

简介: Go语言工程实践之测试 | 青训营笔记

前言

记录加入青训营的每一天的日笔记

背景

测试的出现是为了避免项目中出现重大事故

测试是避免事故的最后一道屏障

测试

image.png

单元测试的覆盖率在一定程度上而言,决定了代码的质量

单元测试

image.png

通过测试单元的输出与期望值进行校对从而验证代码的正确性,从而保证新旧代码的互不影响与程序的正常运行。

进而单元测试较于编译更易于在较短的周期内发现和定位代码中的错误使损失最小化从而提升效率。所以写单元测试是很有必要的。

Golang单元测试对文件名和方法名,参数都有很严格的要求

  • 文件名必须以xx_test.go命名
  • 方法必须是Test[^a-z]开头
  • 方法参数必须t *testing.T
  • 初始化逻辑放到TestMain中
  • 使用go test执行单元测试

演示

通过第三方包assert演示单元测试

判断函数测试值与期望值是否一致


import(
    "github.com/stretchr/testify/assert"
    "testing"
)
func TestHelloTom(t *testing.T) {
    output := HelloTom()
    expectOutput := "Tom"
    assert.Equal(t, expectOutput, output)
}
func HelloTom() string {
    return "Tom"
}

覆盖率

覆盖率出现的目的:

  • 衡量代码是否经过了足够的测试
  • 评价项目的测试水准
  • 评估项目是否达到了高水准测试等级

通过go test命令测试函数的覆盖率

// judgment.go
func JudgePassLine(score int16) bool {
    if score >= 60 {
        return true
    }
    else {
        return false
    }
}
// judgment_test.go
func TestJudgePassLineTrue(t *testing.T) {
    isPass := JudgeePassLine(70)
    assert.Equal(t, true, isPass)
}
func TestJudgePassLineFalse(t *testing.T) {
    isPass := JudgeePassLine(50)
    assert.Equal(t, false, isPass)
}
/*
 通过go test 命令测试覆盖率
 go test judgment_test.go judgment.go --cover
*/
  • 一般覆盖率:50%~60%,较高覆盖率:80%+
  • 测试分支相互独立、全面覆盖

对于上述案例代码而言

应出现成绩大于等于60 和小于60的测试用力

  • 测试单元粒度足够小,函数单一职责

依赖

image.png

  • 幂等:重复运行同一个case,结果与之前一致
  • 稳定:指单元测试相互隔离,可以独立运行

文件处理

当测试文件被修改后,可能会导致测试失败或错误率增高

从而出现了Mock函数


func ReadFirstLine() string {
    open, err := os.Open("log") // 打开一个文件
    defer open.Close()
    if err != nil {
        return ""
    }
    scanner := bufio.NewScanner(open) // 对每行进行遍历
    for scanner.Scan() {
        return scanner.Text()
    }
    return ""
}
func ProcessFirstLine() string {
    line := ReadFirstLine()
    destLine := strings.ReplaceAll(line, "11", "00") // 替换11为00
    return destLine
}
func TestProcessFirstLine(t *testing.T) { // 执行单元测试
    firstLine := ProcessFirstLine()
    assert.Equal(t, "line00", firstLine)
}

Mock

monkey: github.com/bouk/monkey 这是一个开源的mock测试库,可以对method或者实例的方法进行mock

Monkey Patch的作用域在Runtime, 运行时通过Go的unsafe包能够将内存中函数的地址替换为运行时函数的地址,将待打桩函数或方法的实现跳转。

Mock函数不仅可以为一个函数打桩 也可以为一个方法打桩

// 用函数A去替换函数B,B就是原函数,A就是打桩函数
func Patch(target, replacement interface{}) *PatchGuard {
    // target就是原函数,replacement就是打桩函数
    t := reflect.ValueOf(target)
    r := reflect.ValueOf(replacement)
    patchValue(t, r)
    return &PatchGuard{t, r}
}
func Unpatch(target interface{}) bool {
    // 保证了在测试结束之后需要把这个包卸载掉
    return unpatchValue(reflect.ValueOf(target))
}
func TestProcessFirstLineWithMock(t *testing.T) {
    monkey.Patch(ReadFirstLine, func() string {
        return "line110"
    })
    defer monkey.Unpatch(ReadFirstLine)
    line := ProcessFirstLine()
    assert.Equal(t, "line000", line)
}
// 通过patch对ReadFirstLine进行打桩mock,默认返回line110,通过defer卸载mock
// 这样整个测试函数就摆脱了本地文件的束缚和依赖

基准测试

基准测试是指测试一段程序的性能及耗费CPU的程度;

在实际的项目开发中,经常会遇到代码性能瓶颈,为了定位问题,经常要对代码做性能分;

这时就用到了基准测试,其使用方法与单元测试类似。

  • 优化代码,需要对当前代码分析
  • 内置的测试框架提供了基准测试的能力

小结

对于今日课程而言,我将其划分成测试的重要性与分类。 当前课程余下部分为项目实战,该部分内容选择了放置于项目笔记。 如果笔记中有错误的地方也希望掘友们可以及时的提出纠正

目录
相关文章
|
1天前
|
存储 Go 索引
go语言使用for循环遍历
go语言使用for循环遍历
15 7
|
4天前
|
存储 Go
go语言 遍历映射(map)
go语言 遍历映射(map)
18 2
|
5天前
|
Go 调度 开发者
Go语言中的并发编程:深入理解goroutines和channels####
本文旨在探讨Go语言中并发编程的核心概念——goroutines和channels。通过分析它们的工作原理、使用场景以及最佳实践,帮助开发者更好地理解和运用这两种强大的工具来构建高效、可扩展的应用程序。文章还将涵盖一些常见的陷阱和解决方案,以确保在实际应用中能够避免潜在的问题。 ####
|
5天前
|
测试技术 Go 索引
go语言使用 range 关键字遍历
go语言使用 range 关键字遍历
14 3
|
5天前
|
测试技术 Go 索引
go语言通过 for 循环遍历
go语言通过 for 循环遍历
16 3
|
7天前
|
安全 Go 数据处理
Go语言中的并发编程:掌握goroutine和channel的艺术####
本文深入探讨了Go语言在并发编程领域的核心概念——goroutine与channel。不同于传统的单线程执行模式,Go通过轻量级的goroutine实现了高效的并发处理,而channel作为goroutines之间通信的桥梁,确保了数据传递的安全性与高效性。文章首先简述了goroutine的基本特性及其创建方法,随后详细解析了channel的类型、操作以及它们如何协同工作以构建健壮的并发应用。此外,还介绍了select语句在多路复用中的应用,以及如何利用WaitGroup等待一组goroutine完成。最后,通过一个实际案例展示了如何在Go中设计并实现一个简单的并发程序,旨在帮助读者理解并掌
|
6天前
|
Go 索引
go语言按字符(Rune)遍历
go语言按字符(Rune)遍历
21 3
|
10天前
|
Go API 数据库
Go 语言中常用的 ORM 框架,如 GORM、XORM 和 BeeORM,分析了它们的特点、优势及不足,并从功能特性、性能表现、易用性和社区活跃度等方面进行了比较,旨在帮助开发者根据项目需求选择合适的 ORM 框架。
本文介绍了 Go 语言中常用的 ORM 框架,如 GORM、XORM 和 BeeORM,分析了它们的特点、优势及不足,并从功能特性、性能表现、易用性和社区活跃度等方面进行了比较,旨在帮助开发者根据项目需求选择合适的 ORM 框架。
34 4
|
10天前
|
缓存 监控 前端开发
在 Go 语言中实现 WebSocket 实时通信的应用,包括 WebSocket 的简介、Go 语言的优势、基本实现步骤、应用案例、注意事项及性能优化策略,旨在帮助开发者构建高效稳定的实时通信系统
本文深入探讨了在 Go 语言中实现 WebSocket 实时通信的应用,包括 WebSocket 的简介、Go 语言的优势、基本实现步骤、应用案例、注意事项及性能优化策略,旨在帮助开发者构建高效稳定的实时通信系统。
45 1
|
8天前
|
存储 Go PHP
Go语言中的加解密利器:go-crypto库全解析
在软件开发中,数据安全和隐私保护至关重要。`go-crypto` 是一个专为 Golang 设计的加密解密工具库,支持 AES 和 RSA 等加密算法,帮助开发者轻松实现数据的加密和解密,保障数据传输和存储的安全性。本文将详细介绍 `go-crypto` 的安装、特性及应用实例。
28 0