详解Go Testing

TL; DR 本文介绍了Go原生支持的testing的两种测试方法(包内测试和包外测试)和Go支持的四种测试类型(TestXxxx、FuzzXxxx、BenchmarkXxxx和ExampleXxxx)以及使用IDE提示的run test/debug test和手动执行go test命令的区别。和实际项目开发中的被测对象相比,本文的示例比较简单,只是用于说明如何编写四种Go原生支持的测试函数。 Testing 测试的意义 测试是软件生命周期中一个重要部分,测试能带来很多好处: 减少代码缺陷,提升软件质量; 起到文档说明的作用,降低使用门槛; 加深开发人员对代码的理解,提高开发人员的自信; 提高软件开发效率; …… Go Testing Go对test有很好的支持,go专门提供了用于测试的test子命令,测试代码需要写在以go项目中以_test.go结尾的文件中。Go提供了包内测试和包外测试,测试类型又可分为四种:TestXxxx、BenchmarkXxxx、FuzzXxx、ExampleXxx。 包内测试 vs 包外测试 包内测试 包内测试面向实现。包内测试可以访问包内的所有符号(包括未导出的符号);测试代码的测试数据构造和测试逻辑通常与被测包的数据结构以及具体实现逻辑紧密结合。因此,如果修改了被测包的数据结构/实现逻辑,一般需要同步调整包内测试代码。 包外测试 包外测试面向接口。包外测试只能访问被测包导出的API;被测包的API是与外部交互的契约,契约一旦确定就应该长期保持稳定和向前兼容。因此一般修改被测包内部的数据结构和具体实现逻辑不影响包外测试代码。 四种测试类型 目前Go支持4种测试类型:四种测试方法的命名分别为:TestXxxx、BenchmarkXxxx、FuzzXxx和ExampleXxx。 TestXxxx **用途:**用来检查被测代码的输出是否符合预期,最常用的一种测试类型。 **示例:**实现一个查找最长无重复子串的函数;(直接运行) // mytest/mytest.go // leetcode problem_3: https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/ func LengthOfLongestSubstring(s string) int { if len(s) == 0 { return 0 } // 哈希集合,记录每个字符是否出现过 m := map[byte]int{} n := len(s) // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动 rk, ans := -1, 0 for i := 0; i < n; i++ { if i != 0 { // 左指针向右移动一格,移除一个字符 delete(m, s[i-1]) } for rk+1 < n && m[s[rk+1]] == 0 { // 不断地移动右指针 m[s[rk+1]]++ rk++ } // 第 i 到 rk 个字符是一个极长的无重复字符子串 ans = max(ans, rk-i+1) } return ans } func max(x, y int) int { if x < y { return y } return x } 如何验证这个函数是否符合预期?可以写一个简单的main函数,构造一些测试用例,然后调用这个函数。但是Go有自己的测试方法,只需要在被测代码的目录下创建一个以_test.go结尾的文件,并编写一个测试函数即可: ...

十月 14, 2025 · 9 分钟 · rand0m