• Go的单元测试


    单元测试的作用

    单元测试一般用来测试自己写的代码逻辑是否有问题,能不能按照自己的预期执行,便于自己在上线之前检验代码质量。

    在我自己使用单元测试的过程中,我自己一般都是针对某个函数进行测试,判断这个函数是否能够达到预期效果。为了在Go中使用单元测试,我们需要在xxx_test.go文件中导入testing包,通过go test命令实现自动执行如下形式的函数:

    func TestFuncName(*testing.T)
    

    需要注意的是:FuncName的函数名第一个字母不能小写

    在上面的测试函数中,如果需要发送失败消息我们可以使用Error或者FailFatal这些方法,执行成功的话我们也可以使用Log函数输出一些信息。

    在编写单元测试的时候,我们需要创建一个以_test.go结尾的文件,文件中包含了Test_FuncName函数。并且这两个文件放在同一个package下。通过执行go test xxx.go来进行单元测试。

    单元测试示例

    在这我将会在strings.go中写个方法Contains,然后在strings_test.go文件中写一个测试函数TestContains,并且我将这两个文件放在同一个package下,具体如下所示:

    strings.go

    func Contains(s, substr string) bool {
        return strings.Contains(s, substr)
    }
    

    strings_test.go

    func TestContains(t *testing.T) {
    	res := basic.Contains("res", "e")
    
    	if res == true {
    		t.Log("the result is OK")
    	} else {
    		t.Fatal("the result is wrong")
    	}
    }
    

    然后打开cmd窗口,输入命令go test -v .strings_test.go,可以看到输出结果如下:

    === RUN   TestContains
        TestContains: strings_test.go:12: the result is OK
    --- PASS: TestContains (0.00s)
    PASS
    ok      command-line-arguments  (cached)
    

    Table-Driven Test(TDT)

    上面的测试中只输入了一个case,并没有实现case覆盖,测试结果可能会不全。所以如果在一个测试中需要测试多个case,如果我们直接在代码中输入多个case,这将会很费时费力。但是不需要担心,我们可以使用table-driven的方式来实现测试函数。为了实现多个case测试的示例,我在原来的文件中分别实现一个AddTest_Add函数,示例如下:

    strings.go

    func Add(a, b int) int {
    	return a + b
    }
    

    strings_test.go

    func TestAdd(t *testing.T) {
    	// define table
    	var addtests = []struct {
    		a int
    		b int
    		res int    // expected result
    	}{
    		{1,1,2},
    		{2,3,5},
    		{3,4,7},
    		{5,6,11},
    		{6,5,11},
    		{1,22,23},
    	}
    
    	for _, sum := range addtests {
    		actual := basic.Add(sum.a, sum.b)
    
    		if actual != sum.res {
    			t.Errorf("Add(%d + %d ) = %d, expected result is %d", sum.a, sum.b, actual ,sum.res)
    		}
    	}
    }
    

    输入命令go test -v .strings_test.go得到如下结果

    === RUN   TestAdd
    --- PASS: TestAdd (0.00s)
    PASS
    ok      command-line-arguments  0.222s
    

    testing的结构体

    • B : 压力测试
    • BenchmarkResult : 压力测试结果
    • Cover : 代码覆盖率相关结构体
    • CoverBlock : 代码覆盖率相关结构体
    • InternalBenchmark : 内部使用的结构体
    • InternalExample : 内部使用的结构体
    • InternalTest : 内部使用的结构体
    • M : main 测试使用的结构体
    • PB : Parallel benchmarks 并行测试使用的结构体
    • T : 普通测试用例
    • TB : 测试用例的接口

    testing的通用方法

    1. 碰到断言错误,会判断这个测试用例失败,可能会使用到

    Fail : case失败,继续后面的测试用例 FaileNow: case失败,终止测试

    1. 碰到断言错误时希望跳过这个错误,但是不希望标识case失败,使用

    SkipNow : case跳过,终止测试

    1. 只希望在一个地方打印信息,使用

    Log: 输出信息 Logf: 输出格式化的信息

    1. 希望跳过这个case并且打印信息

    Skip: = Log + SkipNow Skipf: = Logf + SkipNow

    1. case失败的时候打印出信息,并且中断测试用例

    Fatal: = Log + FailNow Fatalf: = Logf + FailNow

    1. case失败的时候打印出信息,并且希望测试继续

    Error: = Log + Fail Errorf: = Logf + Fail

    参考文档

  • 相关阅读:
    Java学习086Springboot 自定义启动 banner 信息
    Java学习085Springboot 解决 InetAddress.getLocalHost().getHostName() took 13387 milliseconds to respond. Please verify your network configuration
    PySe023pandas.read_csv 读取 csv 文件,指定列数据类型 解决字符串数据列变为数字的问题
    Linux027Centos JDK 环境离线安装配置
    Java学习087自定义MANIFEST.MF 文件并打包生效
    如何在跨平台的环境中创建可以跨平台的后台服务,它就是 Worker Service。
    如何为Windows服务增加Log4net和EventLog的日志功能。
    微服务与SOA的区别
    java:对象的内存解析
    快速学习一个新技术的方法
  • 原文地址:https://www.cnblogs.com/zuixime0515/p/13372248.html
Copyright © 2020-2023  润新知