Golang跳过长时间测试 Short模式应用

go语言中通过testing.Short()函数识别并标记长测试,开发者在测试中判断该函数返回值,若为true则调用t.Skip()跳过耗时或依赖外部资源的测试;如TestSomethingLongRunning中使用if testing.Short() { t.Skip(“…”) }实现短模式跳过;通常执行时间超几百毫秒或涉及网络、数据库操作的测试被视为长测试,需手动标记;在CI/CD中不应完全依赖-short模式,但可分阶段使用,如在快速预检阶段运行go test -short以快速反馈,再在后续阶段执行完整测试,确保覆盖率;为避免滥用导致覆盖不足,团队需建立规范明确标记范围,确保CI流水线始终运行完整测试,并通过代码审查和定期检查覆盖率防止测试遗漏。

Golang跳过长时间测试 Short模式应用

go语言的测试体系中,

go test -short

命令提供了一种快速迭代的机制,它允许开发者在本地开发时,跳过那些耗时较长、通常涉及外部资源或大量计算的测试,从而显著加快测试反馈循环,提升开发效率。这就像是给你的测试套件装了个“快速模式”开关,让你能优先验证核心逻辑的正确性,而把全面的、耗时的验证留给持续集成(CI)环境。

解决方案

要应用

go test -short

模式,核心在于在你的测试代码中利用

testing

包提供的

testing.Short()

函数。这个函数会在你运行

go test -short

命令时返回

true

。因此,你可以在测试函数内部通过判断

testing.Short()

的返回值来决定是否跳过当前测试。

通常,我们会将那些需要访问数据库、进行网络请求、执行文件I/O操作、或者需要长时间计算的测试标记为“长测试”。一个典型的做法是:

package mypackage  import (     "testing"     "time" // 假设某个操作需要模拟耗时 )  func TestSomethingFast(t *testing.T) {     // 这是一个快速测试,无论是否是short模式都会运行     if 1+1 != 2 {         t.Errorf("Basic arithmetic failed")     } }  func TestSomethingLongRunning(t *testing.T) {     if testing.Short() {         t.Skip("Skipping long-running test in short mode") // 在short模式下跳过     }      // 模拟一个耗时操作,比如数据库查询、api调用等     time.Sleep(2 * time.Second)     t.Log("Long-running test completed successfully.") }  func TestAnotherLongRunningWithResource(t *testing.T) {     if testing.Short() {         t.Skip("Skipping resource-intensive test in short mode")     }      // 这里可以放置需要外部资源(如真实数据库连接)的测试逻辑     // 假设需要连接到外部服务     // client, err := connectToExternalService()     // if err != nil {     //     t.Fatal(err)     // }     // defer client.Close()     // ... 执行测试 ...     t.Log("Resource-intensive test completed.") }

当你执行

go test

时,所有测试都会运行。但当你执行

go test -short

时,

TestSomethingLongRunning

TestAnotherLongRunningWithResource

就会被跳过,因为它们内部检查了

testing.Short()

true

。这种机制让开发者能够灵活地控制测试的粒度和运行时间。

立即学习go语言免费学习笔记(深入)”;

Go语言中如何识别并标记长时间测试?

识别长时间测试,这事儿说起来有点主观,但又很实际。通常,一个测试如果执行时间超过几百毫秒,或者它依赖外部服务、数据库,每次跑起来都得等个几秒甚至几十秒,那它就很有可能被归类为“长测试”了。我们写代码的时候,很容易就能感觉到哪个测试跑起来“肉”,因为它会拖慢整个测试套件的执行速度。

具体到识别上,你可以用

go test -v -bench .

来看看哪些基准测试(benchmarks)耗时,虽然这主要针对性能测试,但也能侧面反映出一些代码块的执行效率。更直接的方式,是留意

go test

完整运行一次需要多久。如果你的本地开发环境,每次修改代码后跑一遍测试要等个十几秒甚至更久,那么就得考虑哪些测试可以被跳过了。

标记嘛,就像前面代码示例里那样,直接在测试函数开头加个

if testing.Short() { t.Skip(...) }

就行。这其实是一种约定,也是一种开发纪律。团队内部可以约定一个阈值,比如“凡是需要网络请求的测试,或者执行时间预计超过1秒的,都应该在

short

模式下跳过”。这样,大家在写新测试时就能有个明确的指导。这种标记不是自动的,需要我们开发者手动判断和添加,这本身也是一种深思熟虑的体现,因为你知道哪些测试是你的“核心快检”,哪些是“深度体检”。

在CI/CD流水线中如何有效利用

go test -short

go test -short

模式在CI/CD流水线中的应用,其实是个有点意思的话题,它不像本地开发那样直观。毕竟,CI/CD的目标是确保代码质量,通常我们会希望在流水线中运行所有测试,包括那些耗时的集成测试和端到端测试,以提供最全面的质量保障。所以,直接在CI/CD中全面使用

-short

模式来替代完整测试,那绝对是自欺欺人,是不可取的。

但是,这并不意味着它在CI/CD里就毫无用武之地。想象一下,如果你的CI/CD流水线有多个阶段,比如“快速构建与单元测试”和“全面集成与部署测试”。在“快速构建”阶段,你可能需要一个极其迅速的反馈,比如在开发者提交代码到版本控制系统时,立即运行一个非常快的检查,以确保基本语法无误、核心单元测试通过,这时就可以考虑在这一阶段使用

go test -short

。这可以作为一种“预检”,快速筛掉那些连基本功能都跑不通的提交,避免浪费后续耗时更长的CI资源。

举个例子,在gitHub Actions或者gitlab CI中,你可以在

push

事件触发的第一个job中运行

go test -short

。如果通过,再触发一个更全面的job,运行所有的测试。这种分阶段的策略,既能保证快速反馈,又不牺牲最终的测试覆盖率。但务必记住,最终部署到生产环境的代码,一定是要经过所有测试的洗礼的。

-short

模式在这里扮演的是一个“守门员”的角色,而不是“终审法官”。

如何避免滥用

testing.Short()

导致测试覆盖不足?

滥用

testing.Short()

是个真实存在的风险,这就像是给了你一个“跳过”按钮,用多了就容易产生依赖,甚至忘记了还有“完整测试”这回事。最直接的后果就是测试覆盖率下降,一些只在“长测试”中被验证的边缘情况或集成逻辑,可能长时间得不到充分测试,直到生产环境出现问题才暴露出来,那时候代价可就大了。

要避免这种滥用,首先,也是最关键的,就是要有一个健壮的、始终运行完整测试的CI/CD流水线。你的CI系统必须是那个“严格的老师”,每次代码合并到主分支(或者重要的发布分支)之前,都必须强制运行所有测试,不带任何

-short

参数。这是底线,也是确保代码质量的最后一道防线。

其次,团队内部需要建立清晰的规范和共识。哪些测试可以被标记为

short

为什么?这个判断标准是什么?这些都需要明确。例如,可以约定,只有那些需要真实外部服务(数据库、消息队列、第三方API)的集成测试,或者模拟非常耗时计算的性能测试,才允许使用

testing.Short()

。纯粹的单元测试,无论多慢,都不应该被

short

掉,因为它们是验证核心业务逻辑的基石。

再来,代码审查(Code Review)在这方面也扮演着重要角色。当有开发者提交包含

t.Skip

且依赖

testing.Short()

的测试时,审查者应该问一句:“这个测试为什么需要被跳过?它真的足够长吗?是不是可以优化?”有时候,一个被标记为“长”的测试,其耗时可能并不是因为逻辑复杂,而是因为测试代码本身写得不够高效,或者模拟数据的方式有问题。这时候,与其跳过,不如去优化测试本身。

最后,定期审查测试报告和覆盖率。如果发现某些关键模块的测试覆盖率在下降,或者一些集成测试长时间没有在CI中跑过,那就需要警惕了。这可能就是

testing.Short()

被过度使用的信号。记住,

testing.Short()

是为了提高开发效率,而不是降低测试质量。它是一个工具,而不是偷懒的借口。

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享