Go测试学习

2023-06-26 20:25:57

前言: \textcolor{Green}{前言:} 前言:

💞这个专栏就专门来记录一下寒假参加的第五期字节跳动训练营
💞从这个专栏里面可以迅速获得Go的知识

今天的学习是测试:从单元测试实践出发,提升质量意识.这是对之前内容的回顾学习,通过回顾之前的内容来提升自己。

在开发过程中测试是非常重要的。先来了解一下测试的重要性:

1、通过软件测试确保软件的质量。

2、给开发人员提供信息,以方便其为风险评估做相应的准备。

3、软件测试贯穿在整个软件开发的过程中,保证整个软件开发的过程高质量。

4、通过软件测试发现软件的错误、有效定义和实现软件成分由低层到高层的组装过程。

5、通过软件测试验证软件是否满足任务书和系统定义文档所规定的技术要求。

6、软件测试为软件质量模型的建立提供依据。

通过测试的重要性今天就来学习一下测试

03 测试

这一讲主要有go 测试相关的内容,包括单元测试规范、测试 mock、基准测试。

测试关系着系统的质量,质量决定线上系统的稳定性,一旦发现 bug,就会造成事故。

事故有:

  1. 营销配置错误,导致非预期用户享受权益,资金损失10W+
  2. 用户提现,幂等失效,短时间可以多次提现,资金损失20w+(关于幂等问题可以去查一下)
  3. 代码逻辑错误,广告位被占,无法出广告,收入损失500w+
  4. 代码指针使用错误,导致APP不可用,损失上kw+

1673869929603.png

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

image.png

测试分为:回归测试是QA手动通过终端回归一些固定的主流程场景;集成测试是对系统功能维度做测试验证;单元测试是测试开发阶段,开发者对单独的函数、模块做功能验证;
层级从上到下,测试成本逐渐减低,测试覆盖率逐步上升,所以单元测试的覆盖率一定程度上决定着代码的质量。

3.1 单元测试

image.png

单元测试主要包括,输入->测试单元->输出->校对。

单元的概念比较广:包括接口、函数、模块等;用最后的校对来保证代码的功能与我们的预期相符;单侧一方面可以保证质量,在整体覆盖率足够的情况下,一定程度上既保证了新功能本身的正确性,又未破坏原有代码的正确性。其次可以提升效率,在代码有bug的情况下,通过编写单元测试,可以在一个较短周期内定位和修复问题。

3.1.1 单元测试 - 规则

image.png

这样从文件上就可以区分源码和测试代码,以 Test 开头,且连接的第一个字母大写。

3.1.2 单元测试 - 例子
func HelloTom() string {
    return "Jerry"
}
func TestHelloTom(t *testing.T) {
    output := HelloTom()
    expectOutput := "Tom"
    if output ≠ expectOutput {
        t.Errorf("Expected %s do not match actual %s", expectOutput, output)
    }
}
3.1.3 单元测试 - 运行

image.png

3.1.4 单元测试 - assert
func HelloTom() string {
    return "Tom"
}

import (
    "github.com/stretchr/testify/assert"
    "test"
)

func TestHelloTom(t *testing.T) {
    output := HelloTom()
    expectOutput := "Tom"
    assert.Equal(t, expectOutput, output)
}

使用assert 注意需要importgithub.com/stretchr/testify/assert

3.1.5 单元测试 - 覆盖率
  • 如何衡量代码是否经过了足够的测试?
  • 如何评价项目的测试水准?
  • 如何评估项目是否达到了高水准测试等级?

这就需要 代码覆盖率 来去解决上述的问题

例子

这是一个判断是否及格的函数,超过 60 分,返回 true,否则返回 false。
右边是对输入为 70 的单元测试,通过执行右边的单测,通过指定的 cover 参数,可以看到覆盖率。
image.png

因为没有经过 false 这一行,所以仅仅是 2/3。

接下来提升覆盖率,增加一个不及格的测试 case。重新执行所有的单测,最终得到覆盖率为 100%。

image.png

3.1.5 单元测试 - Tips

在实际项目中:

  • 一般覆盖率:50%~60%,较高覆盖率 80%+
  • 测试分支相互独立、全面覆盖。
  • 测试单元粒度足够小,函数单一职责。

3.2 单元测试 - 依赖

image.png

工程中复杂的项目,一般会依赖数据库、本地文件等强依赖,而我们的单测需要保证稳定性和幂等性,稳定是指相互隔离,能在任何时间,任何环境,运行测试。幂等是指每一次测试运行都应该产生与之前一样的结果,而要实现这一目的就要用用到 mock 机制。

3.3 单元测试 - 文件处理

替换文件中第一行字符串中的 11,将其换为 00。测试通过,会发现 单测需要依赖本地的文件,如果文件被修改或者删除就会 fail。为了保证测试 case的稳定性,需要对读取文件函数进行 mock,从而屏蔽对文件的依赖。

image.png

3.4 单元测试 - Mock

monkey

image.png

monkey 是一个开源的 mock 测试库,可以对 method 或者实例的方法进行 mock。
反射指的是指针赋值。
Mockey Patch 的作用域在 Runtime,在运行时通过 Go 的 unsafe 包,能够将内存中函数的地址替换为运行时函数的地址。

下面是一个 mock 的使用样例, 通过 patch 对 Readfineline 进行打桩 mock,默认返回 line110,通过 defer 卸载 mock,这样整个测试函数就需要本地文件的束缚和依赖。

image.png

对 ReadFirstLine 打桩测试,不再依赖本地文件

3.5 基准测试

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

go 语言提供了基准测试框架,基准测试是指测试一段程序的运行性能以及耗费CPU 的程度,而我们在实际项目开发中,经常会遇到代码性能瓶颈,为了定位问题经常要对代码进行性能分析,这就用到了基准测试。使用方法类似于单元测试。

3.5.1 基准测试 - 例子

下面是 服务器负载均衡的例子,首先有10个服务器列表,每次随机执行 select 函数随机选择一个执行。

import (
    "math/rand"
)

var ServerIndex [10]int

func InitServerIndex() {
    for i := 0; i < 10; i++ {
        ServerIndex[i] = i + 100
    }
}

func Select() int {
    return ServerIndex[rand.Intn(10)]
}

10个服务器随机选择一个服务器执行。对其进行一个基准测试

3.5.2 基准测试 - 运行

基准测试 以 Benchmark 开头,入参 试 testing.B,用 b 中的 N 值反复递增循环测试。
(对于一个测试用例的默认测试时间为1s,当测试用例函数返回时还不到1s,那么testing.B中的N值将按1、2、5、10、20、50…递增,并以递增后的值重新进行用例函数测试)

image.png

Resetimer重置计时器,再 reset之前做了int或其他的准备工作,这些不作为基准测试的范围;RunParallel 是多协程并发测试;执行两个基准测试,发现代码在并发情况下存在劣化,主要原因是 rand 为了保证全局随机性和并发安全,持有了一把全局锁

3.5.3 基准测试 - 优化

为了解决随机性能问题,开源一个高性能随机数方法 fastrand。开源地址 再次进行基准测试,发现性能会提升百倍为什么?这是因为牺牲了一定的数列一致性。

image.png

更多推荐

【错误记录】exe4j 打包程序无法设置 jar 包依赖的问题 ( 将源码 和 依赖库打包到同一个 jar 包中 )

文章目录一、问题描述二、解决方案一、问题描述在【错误记录】IntelliJIDEA导出可执行jar包执行报错(java.lang.ClassNotFoundException|打包时没有选择依赖库)博客中遇到java.lang.ClassNotFoundException:com.microsoft.sqlserver

【错误记录】Android Studio 中 Kotlin 版本报错 ( Module was compiled with an incompatible version of Kotlin. T )

文章目录一、报错信息二、问题分析三、解决方案1、低版本Gradle配置2、高版本Gradle配置一、报错信息在AndroidStudio中,编译应用,报如下错误:C:/Users/octop/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-s

设计模式Java实战

文章目录一、前置1.1目的1.2面向对象1.3接口和抽象类二、七大设计原则2.1单一职责2.2接口隔离原则2.3依赖倒转原则2.4里氏替换原则2.5开闭原则2.6不要重复原则2.7迪米特最少知道法则三、23种设计模式3.1创建型:创建对象3.1.1单例模式定义最佳实践场景线程级别的单例缺点3.1.2工厂模式(简单工厂)

DolphinDB x 龙蜥社区,打造多样化的数据底座

近日,浙江智臾科技有限公司(以下简称“DolphinDB”)正式签署CLA贡献者许可协议,加入龙蜥社区(OpenAnolis)。DolphinDB主创团队从2012年开始投入研发产品。作为一款基于高性能时序数据库,DolphinDB支持复杂分析与流处理的实时计算平台,集成了功能强大的编程语言和高吞吐率的流数据分析系统,

Appium 全新 2.0 全新跨平台生态,版本特性抢鲜体验!

关于AppiumV2AppiumV2beta版本在2021年发布,从2022年1月1号开始,Appium核心团队不会再维护Appium1.x版本了,所有近期官方发布的平台驱动(如Android平台的UIAutomator,IOS平台的XCUITest)不再兼容Appium1.x,需要基于AppiumV2版本。让我们一起

6.2 构建并评价聚类模型

6.2构建并评价聚类模型6.2.1使用sklearn估计器构建聚类模型1、聚类的概念2、常见聚类方法3、使用sklearn估计器构建聚类模型4、sklearn估计器代码:构建K-Means聚类模型6.2.2评价聚类模型1、FMI评价法2、轮廓系数评价法3、Calinski-Harabasz指数评价法6.2.1使用skl

Spring Security 源码详解

SpringSecurity源码详解这里主要介绍SpringSecurity的整体流程,方便以后查阅!!!一、SpringSecurity过滤器链加载1、注册springSecurityFilterChain过滤器当SpringBoot项目启动后,SecurityFilterAutoConfiguration类会加载D

[交互]AJAX

[交互]AJAX创建XMLHttpRequest发送请求服务器响应XMLHttpRequestreadyState状态值响应数据请求状态变更回调函数XMLHttpRequeststatus的值常用状态码设置AJAX是技术,不是工具,区别于axios、fetch、$.ajax等(封装工具)现有交互工具,是用于改变部分网页

最佳优先搜索简介

概念:最佳优先搜索算法(Best-FirstSearch)是一种启发式搜索算法,用于在图中找到从起点到目标节点的最佳路径。使用一个优先队列来存储待扩展的节点,优先队列根据节点的启发式评估函数值进行排序。在每次迭代中,算法选择队列中启发式评估函数值最小的节点进行扩展,直到找到目标节点或遍历完所有节点。最佳优先搜索算法用于

什么是智能推荐?智能推荐的原理是什么?

一、智能推荐的魔力2020年的愚人节晚间,罗永浩在抖音带货,相信你也被刷屏了吧。3小时的直播过程中,22款产品轮番出场,最终首播支付交易总额突破1.1亿、整场直播观看总人数超过4800万、总销售件数逾91万,粉丝打赏音浪收入3600万,由此看来,罗老师看起来离“带货一哥”的目标又进了一步。不得不说,这场魔幻版的流量狂潮

如何学习java

带着问题去学?为什么我们debug的时候代码会停在哪一个位置什么是多态?(这个在类的生命周期里面寻找答案)我们学习java就是从代码到成为程序的过程所以这很明显就是我们的编译原理和os打交道这很明白就是操作系统和另一台机器打交道,那么就是计算机网络java指令8个从代码到程序就是从代码到字节码(javap命令可以看到)

热文推荐