当前位置: 首页 > news >正文

15.2 测试-网格测试、基准测试与测试覆盖率

1. 网格测试

函数或方法的输出因收到的输入而异,如果为每个输入专门编写一个测试用例,将导致大量的重复代码。

不妨将输入的各种组合存放在网格之中,只编写一个测试用例即完成对所有输入的测试,比如象下面这样:

var greetingTests = []greetingTest{
        {"en-US", "George",   "Hello George!"},
        {"fr-FR", "Chloé",    "Bonjour Chloé!"},
        {"it-IT", "Giuseppe", "Ciao Giuseppe!"},
}

// 网格测试
// 源代码
// Package greeting return greeting
package greeting
func translate(locale string) string {switch locale {case "en-US":return "Hi "case "fr-FR":return "Bonjour "case "it-IT":return "Ciao "default:return "Hello "}
}
// Greeting return greeting
func Greeting(locale, name string) string {return translate(locale) + name + "!"
}
// 源代码对应的测试用例(测试输入为我们之前定义的网格)
// 函数或方法的输出因收到的输入而异,如果为每个输入专门编写一个测试用例,将导/// 致大量的重复代码。不妨将输入的各种组合存放在网格之中,只编写一个测试用例即
// 完成对所有输入的测试 
package greeting
import "testing"type greetingTest struct {locale   stringname     stringexpected string
}var greetingTests = []greetingTest{{"en-US", "George", "Hello George!"},	// 与源代码不一致,会失败{"fr-FR", "Chloé", "Bonjour Chloé!"},{"it-IT", "Giuseppe", "Ciao Giuseppe!"},
}func TestGreeting(t *testing.T) {for _, test := range greetingTests {actual := Greeting(test.locale, test.name)if actual != test.expected {t.Fatalf("Greeting(%q,%q)->%q, expected %q",test.locale, test.name, actual,test.expected)}}
}
// 打印输出:
greeting_test.go:29: Greeting("en-US","George")->"Hi George!", expected "Hello George!"

2. 基准测试

Go语言提供了功能强大的基准测试框架,利用该框架开发人员可以精确地获知,选择何种方式能使程序完成特定任务的性能最优。

基准测试函数的函数名以"Benchmark"开头,接受一个类型为B的参数。

  • func ByPlus(strs ...string) string { ... }
  • func BenchmarkByPlus(b *testing.B) { ... }

在测试函数内部,使用循环反复地调用被测试函数以建立基准。

  • for n := 0; n < b.N; n++ {
            ByPlus("Hello", " ", "World", "!")
    }
  • 循环的次数N无需指定,框架会自动设置它以获得可靠的数据集。(为了避免随机性,会执行N次求平均值来衡量性能)

基准测试结束后,会生成一个测试报告,指出每个被测函数的总调用次数(N)和单次调用的平均耗时(单位ns)。

  • BenchmarkByPlus-8        10000000        185 ns/op

在包目录下执行如下命令,启动基准测试:

  • go test -bench
// 基准测试(测试了3种字符串拼接方法的效率)
// Package joinstrs join strings
package joinstrs import ("bytes""strings"
)// ByPlus join strings by plus
func ByPlus(strs ...string) string {s := ""for _, str := range strs {s += str}return s
}// ByJoin join strings by join
func ByJoin(strs ...string) string {return strings.Join(strs, "")
}// ByBuff join strings by buffer
func ByBuff(strs ...string) string {b := bytes.Buffer{}for _, str := range strs {b.WriteString(str)}return b.String()
}

// 基准测试(测试了3种字符串拼接方法的效率)
// 基准测试关注代码的运行性能。基准测试 
// 函数的函数名必须以"Benchmark"开头
// 
// 执行如下命令,启动基准测试: 
// go test -bench .
package joinstrs
import "testing"func TestByPlus(t *testing.T) {// 使用了"testing包"小节所述的actual-expected模式actual, expected := ByPlus("Hello", " ", "World", "!"),"Hello World!"if actual != expected {t.Fatalf("Actual %q, expected %q",actual, expected)}
}
func TestByJoin(t *testing.T) {actual, expected := ByJoin("Hello", " ", "World", "!"),"Hello World!"if actual != expected {t.Fatalf("Actual %q, expected %q",actual, expected)}
}
func TestByBuff(t *testing.T) {actual, expected := ByBuff("Hello", " ", "World", "!"),"Hello World!"if actual != expected {t.Fatalf("Actual %q, expected %q",actual, expected)}
}
func BenchmarkByPlus(b *testing.B) { // 基准测试for n := 0; n < b.N; n++ {ByPlus("Hello", " ", "World", "!")}
}func BenchmarkByJoin(b *testing.B) {// 基准测试for n := 0; n < b.N; n++ {ByJoin("Hello", " ", "World", "!")}
}func BenchmarkByBuff(b *testing.B) {// 基准测试for n := 0; n < b.N; n++ {ByBuff("Hello", " ", "World", "!")}
}
// 打印输出:goos: windowsgoarch: amd64pkg: test/benchmarkBenchmarkByPlus-8 10000000 185 ns/opBenchmarkByJoin-8 20000000 103 ns/op//字符串拼接strings.Join()是最高效的BenchmarkByBuff-8 10000000 161 ns/opPASSok       test/benchmark       6.479s

3.测试覆盖率

测试覆盖率指被测试执行的代码总代码百分比。

  • 单元测试通过,说明功能正确
  • 基准测试效果也不错,说明性能可以接受
  • 这并不表示被测软件经受住了考验,因为有些代码可能根本就没有被执行到

在包目录下执行如下命令,计算测试覆盖率:

  • go test -cover
  • 其是针对某一包目录下的所有go源文件中的func进行计算的
// 测试覆盖率指被测试执行的代码占总代码的百分比
// 
// 执行如下命令,启动测试并输出覆盖率: 
// go test -cover
package greetingimport "testing"func TestGreeting(t *testing.T) {actual, expected := Greeting("World"),"Hello World!"if actual != expected {t.Fatalf("Actual %q, expected %q",actual, expected)}
}
// Package greeting return greeting
package greeting// Greeting return greeting
func Greeting(s string) string {return "Hello " + s + "!"
}// Farewell return farewell
func Farewell(s string) string {return "Goodbye " + s + "!"
}
// 打印输出:
PASS
coverage: 50.0% of statements
ok test/coverage 0.447s 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 基于拓扑漏洞分析的网络安全态势感知模型
  • 源码讲解kafka 如何使用零拷贝技术(zero-copy)
  • 云端之上的边缘:解读云计算与边缘计算的战略融合
  • 苹果召开WWDC:属于你的“定制”AI智能?
  • 直线度测量仪发展历程!
  • 鸿蒙原生开发——轻内核A核源码分析系列三 物理内存(2)
  • 利用 AI 深度学习,实现化合物配比最优化解决方案
  • Android:UI:Drawable:View/ImageView与Drawable
  • React实现在线预览word报告/本地选择报告预览
  • LabVIEW调用DLL时需注意的问题
  • 文件IOoooo
  • 计算机网络 —— 数据链路层(以太网)
  • adb 脚本化Android系统截图和录屏
  • Python的Pillow(图像处理库)非常详细的学习笔记
  • 【HarmonyOS】鸿蒙应用子模块module资源如何获取
  • 《剑指offer》分解让复杂问题更简单
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • 【知识碎片】第三方登录弹窗效果
  • IOS评论框不贴底(ios12新bug)
  • Java面向对象及其三大特征
  • js算法-归并排序(merge_sort)
  • php面试题 汇集2
  • Redis学习笔记 - pipline(流水线、管道)
  • Twitter赢在开放,三年创造奇迹
  • Vim Clutch | 面向脚踏板编程……
  • Vue.js-Day01
  • 百度小程序遇到的问题
  • 半理解系列--Promise的进化史
  • 程序员最讨厌的9句话,你可有补充?
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 前端_面试
  • 前端技术周刊 2019-02-11 Serverless
  • 容器服务kubernetes弹性伸缩高级用法
  • 通过几道题目学习二叉搜索树
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • 转载:[译] 内容加速黑科技趣谈
  • ​业务双活的数据切换思路设计(下)
  • #pragma once
  • #预处理和函数的对比以及条件编译
  • (C#)获取字符编码的类
  • (二)c52学习之旅-简单了解单片机
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (含笔试题)深度解析数据在内存中的存储
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (全注解开发)学习Spring-MVC的第三天
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • .“空心村”成因分析及解决对策122344
  • .locked1、locked勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .net core 连接数据库,通过数据库生成Modell
  • .net framework profiles /.net framework 配置
  • .net mvc 获取url中controller和action
  • .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
  • .NET6 命令行启动及发布单个Exe文件
  • .NET与 java通用的3DES加密解密方法