模糊测试入门 (Fuzzing)

大家好,我是极客老墨。 单元测试只能测试你想到的情况。空字符串、负数、超长输入,这些边界情况很容易遗漏。模糊测试能自动生成大量随机输入,帮你发现那些没想到的 Bug。 这篇就聊聊 Go 的模糊测试,看看它是怎么帮我们提升代码质量的。 什么是模糊测试 模糊测试(Fuzzing)是一种自动化测试技术,通过生成随机输入来发现程序的异常。 核心思想 1// 传统单元测试:测试已知输入 2func TestAdd(t *testing.T) { 3 if Add(2, 3) != 5 { 4 t.Error("2 + 3 should be 5") 5 } 6 if Add(0, 0) != 0 { 7 t.Error("0 + 0 should be 0") 8 } 9} 10 11// 模糊测试:测试大量随机输入 12func FuzzAdd(f *testing.F) { 13 f.Fuzz(func(t *testing.T, a, b int) { 14 result := Add(a, b) 15 // 检查属性而不是具体值 16 if a > 0 && b > 0 && result <= 0 { 17 t.Errorf("Add(%d, %d) = %d, overflow?", a, b, result) 18 } 19 }) 20} 区别: 单元测试:测试已知的输入和输出 模糊测试:测试未知的输入,检查程序属性 能发现什么问题 崩溃和 panic:空指针、数组越界 整数溢出:加法、乘法溢出 无限循环:特定输入导致死循环 内存泄漏:特定输入导致内存不释放 逻辑错误:边界条件处理不当 编写第一个 Fuzz 测试 从一个简单的例子开始。 被测函数 1// reverse.go 2package stringutil 3 4// Reverse 反转字符串 5func Reverse(s string) string { 6 b := []byte(s) 7 for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 { 8 b[i], b[j] = b[j], b[i] 9 } 10 return string(b) 11} Fuzz 测试 1// reverse_test.go 2package stringutil 3 4import "testing" 5 6func FuzzReverse(f *testing.F) { 7 // 添加种子输入(可选) 8 f.Add("hello") 9 f.Add("世界") 10 f.Add("") 11 12 // Fuzz 函数 13 f.Fuzz(func(t *testing.T, s string) { 14 // 属性:反转两次应该等于原字符串 15 reversed := Reverse(s) 16 doubleReversed := Reverse(reversed) 17 18 if s != doubleReversed { 19 t.Errorf("Reverse(Reverse(%q)) = %q, want %q", 20 s, doubleReversed, s) 21 } 22 }) 23} 要点: ...

2025-08-20 · 8 min · 1540 words · 老墨