Go-单元测试详解与代码

简介: Go-单元测试详解与代码

概述

常言道,不会测试的程序猿不是好的产品经理!!!现在越来越多测试和运维的工作也需要研发来做了,本篇文章就来讲讲Go的单元测试

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。简单说,就是将测试用例的运行结果与预期结果进行比较。

Go的单元测试

基础知识

Go有testing测试包,配合go test命令能够进行单元测试。

  1. 测试文件以_test.go结尾
  2. 在包目录内,所有以_test.go为后缀名的源代码文件都是go test测试的一部分,不会被go build编译到最终的可执行文件中。
  3. _test.go文件包含TestXxx函数
  4. 形参类型必须为*test.T
  5. PASS表示测试用例运行成功,FAIL表示失败

个人常用Fatalf,这里就来具体说一下,其他函数见参考的链接。

func (c *T) Logf(format string, args ...interface{})

Log 使用与 Printf 相同的格式化语法对它的参数进行格式化,然后将格式化后的文本记录到错误日志里面。 如果输入的格式化文本最末尾没有出现新行,那么将一个新行添加到格式化后的文本末尾。

1)对于测试来说,Logf 产生的格式化文本只会在测试失败或者设置了 -test.v 标志的情况下被打印出来;

2)对于基准测试来说,为了避免 -test.v 标志的值对测试的性能产生影响,Logf 产生的格式化文本总会被打印出来

func (c *T) FailNow()

将当前测试标识为失败并停止执行该测试,在此之后,测试过程将在下一个测试或者下一个基准测试中继续。


FailNow 必须在运行测试函数或者基准测试函数的 goroutine 中调用,而不能在测试期间创建的 goroutine 中调用。调用 FailNow 不会导致其他 goroutine 停止。

func (c *T) Fatalf(format string, args ...interface{})

调用 Fatalf 相当于在调用 Logf 之后调用 FailNow 。

快速入门

项目结构

learnGo

└── main

   ├── compute.go

   └── compute_test.go

compute.go

package main
import "errors"
func div(a,b int) (int,error) {
  if b != 0{
    return a/b,nil
  } else{
    return 0,errors.New("b is 0")
  }
}

compute_test.go

package main
import "testing"
func TestDiv(t *testing.T)  {
  res,_ := div(4,2)
  want := 2
  if res != want{
    t.Fatalf("期待:%d ,实际结果:%d",want,res)
  }
}

main目录下运行

go test -v

结果如下:

=== RUN   TestDiv
--- PASS: TestDiv (0.00s)
PASS
ok      learnGo/main    0.457s

以上我们就针对main包的compute.go文件进行了单元测试。

进阶

查看更多的选项,可使用

go help test
go help testflag

单个文件的测试

我们在main包中再添加str.go及str_test.go

str.go

package main
func getSub(str string,start,end int) string {
  // 左闭右闭
  if 0<=start&&start<end&&end<=len(str){
    return str[start:end]
  }else{
    return ""
  }
}

str_test.go

package main
import "testing"
func TestGetSub(t *testing.T)  {
  astr := "lady_killer9"
  // 包含开头
  res1 := getSub(astr,0,4)
  want1 := "lady"
  // 包含结尾
  res2 := getSub(astr,4,len(astr))
  want2 := "_killer9"
  // 范围错误
  res3 := getSub(astr,1,len(astr)+1)
  want3 := ""
  if res1 != want1{
    t.Errorf("期望:%s,实际结果:%s",want1,res1)
  }
  if res2 != want2{
    t.Errorf("期望:%s,实际结果:%s",want2,res2)
  }
  if res3 != want3{
    t.Errorf("期望:%s,实际结果:%s",want3,res3)
  }
}

运行 go test -v,得到结果如下

=== RUN   TestDiv
--- PASS: TestDiv (0.00s)
=== RUN   TestGetSub
--- PASS: TestGetSub (0.00s)
PASS
ok      learnGo/main    0.446s

go test会运行所有的单元测试,有时候我们只想测试某个文件

如果只是运行一个测试文件,可添加参数

go test -v 测试文件 源文件

运行go test -v str_test.go str.go, 结果如下:

=== RUN   TestGetSub
--- PASS: TestGetSub (0.00s)
PASS
ok      command-line-arguments  0.619s

单个函数的测试

我们在compute.go中添加

1. func add(a,b int) int {
2.  return a+b
3. }

在compute_test.go中添加

func TestAdd(t *testing.T)  {
  a,b:=3,4
  res := add(a,b)
  want := 7
  if res != want{
    t.Fatalf("期待:%d,实际结果:%d",want,res)
  }
}

由于对div函数未做改动,只想测试add函数,可以使用参数-test.run指定测试函数

go test -v -test.run 测试函数

运行 go test -v -test.run TestAdd 结果如下:

=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok      learnGo/main    0.836s

单元测试覆盖率

测试应该全面,达到100%。

可以使用-cover参数

go test -cover

结果如下:

PASS
coverage: 85.7% of statements
ok      learnGo/main    0.505s

可以看到,测试的并不全面,指定测试文件来查看。

go test -cover compute_test.go compute.go

ok      command-line-arguments  0.314s  coverage: 75.0% of statements

观察发现,我们缺少了b为0的分支,修改TestDiv函数为

func TestDiv(t *testing.T)  {
  res,_ := div(4,2)
  want := 2
  if res != want{
    t.Fatalf("期待:%d,实际结果:%d",want,res)
  }
  res,_ = div(3,0)
  want = 0
  if res != want{
    t.Fatalf("期待:%d,实际结果:%d",want,res)
  }
}

测试后再看覆盖率,结果如下

PASS
coverage: 100.0% of statements
ok      learnGo/main    0.306s

作为开发,基本的单元测试就可以了,还可以去了解基准测试、性能测试、压力测试、黑盒测试等。

参考

Go标准库-testing

更多Go相关内容:Go-Golang学习总结笔记

有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。


相关文章
|
13天前
|
SQL 安全 数据库连接
《Go 简易速速上手小册》第6章:错误处理和测试(2024 最新版)(上)
《Go 简易速速上手小册》第6章:错误处理和测试(2024 最新版)
48 1
|
13天前
|
Go 索引
掌握Go语言:Go语言范围,优雅遍历数据结构,简化代码操作实战解析(24)
掌握Go语言:Go语言范围,优雅遍历数据结构,简化代码操作实战解析(24)
|
13天前
|
Java 关系型数据库 数据库连接
Mybatis+MySQL动态分页查询数据经典案例(含代码以及测试)
Mybatis+MySQL动态分页查询数据经典案例(含代码以及测试)
49 1
|
13天前
|
JSON 测试技术 Go
《Go 简易速速上手小册》第6章:错误处理和测试(2024 最新版)(下)
《Go 简易速速上手小册》第6章:错误处理和测试(2024 最新版)
45 0
|
11天前
|
SQL 关系型数据库 MySQL
实时计算 Flink版产品使用合集之idea本地测试代码,要增大 Flink CDC 在本地 IDEA 测试环境中的内存大小如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
13天前
|
jenkins Devops 测试技术
单元测试与质量保证:确保Visual Basic代码的健壮性
【4月更文挑战第27天】在VB开发中,单元测试是保证代码质量和软件健壮性的关键。本文介绍了单元测试的基础,包括其定义和好处,如提高代码质量、促进重构。接着,讨论了MSTest、NUnit和xUnit等VB单元测试工具。遵循TDD原则和最佳实践,编写独立、有针对性的测试,并注重测试速度和覆盖率。通过示例展示了如何在Visual Studio中设置和运行测试。最后,提到了持续集成和自动化测试工具,如Jenkins和静态代码分析工具,以提升软件开发效率和质量。单元测试不仅是技术手段,更是提升团队协作和软件工程水平的文化体现。
|
5天前
|
消息中间件 Oracle 关系型数据库
实时计算 Flink版操作报错之连接外部kafka本地执行测试代码报错如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
13天前
|
程序员 测试技术
程序员难以一次性写好代码并持续修复Bug,主要源于软件的高复杂性、需求不确定性、测试局限性和技术能力限制。
【5月更文挑战第11天】程序员难以一次性写好代码并持续修复Bug,主要源于软件的高复杂性、需求不确定性、测试局限性和技术能力限制。复杂的系统易产生意外问题,需求变化导致初始设计难完备,测试无法覆盖所有情况,而技术更新和个体能力差异也会引入错误。因此,持续调试和优化是保证软件质量的关键步骤。
22 0
|
13天前
|
算法 数据可视化 API
LabVIEWCompactRIO 开发指南33 测试和调试LabVIEW FPGA代码
LabVIEWCompactRIO 开发指南33 测试和调试LabVIEW FPGA代码
16 0
|
13天前
|
测试技术
使用CLion创建Cmake项目,使用GoogleTest和GoogleMock对代码进行测试
使用CLion创建Cmake项目,使用GoogleTest和GoogleMock对代码进行测试
26 3

热门文章

最新文章