测试插入与断言覆盖收敛实战 - 第2节
语句覆盖:定义与原理
语句覆盖,说白了就是测试用例执行了多少行代码。我刚开始做测试时,总觉得这玩意儿太基础了,不就是看代码跑没跑过嘛。但后来踩过坑才明白——它是最底线的质量门禁。
它的核心定义很简单:每个可执行语句至少被执行一次。注意我说的是"可执行语句",像变量声明、空行、注释这些都不算。你想想看,如果一段代码里有一行从来没被执行过,那这行代码写出来干嘛?
语句覆盖的数学定义
语句覆盖率 = (被执行的语句数 / 总可执行语句数) × 100%
嗯,这里要注意:语句覆盖只关心"有没有执行",不关心"执行结果对不对"。它是最弱的覆盖标准,但也是必须跨过的第一道坎。
如何计算语句覆盖率
计算过程其实就三步,我习惯这么教新人:
- 数总数——先找出代码里所有可执行语句的数量
- 看执行——跑测试用例时,记录哪些语句被触发了
- 算比例——用执行数除以总数,得到覆盖率
举个例子,假设有这段代码:
def check_score(score):
if score >= 90: # 语句1
print("优秀") # 语句2
elif score >= 60: # 语句3
print("及格") # 语句4
else: # 语句5
print("不及格") # 语句6
print("结束") # 语句7
总共有7条可执行语句。如果我只写一个测试用例 check_score(95),那么执行的是语句1、2、7。覆盖率就是 3/7 ≈ 42.8%。
我的小技巧:在代码里临时加个计数器,或者用IDE的调试模式单步走一遍,就能清楚看到哪些语句被覆盖了。我在项目中经常用这个笨办法来快速验证覆盖率数据是否准确。
实战案例:计算一个简单函数的语句覆盖率
咱们来点真实的。这是我之前在一个支付系统里遇到过的场景——判断订单是否满足退款条件:
def can_refund(order):
if order.status == "已支付": # 语句1
if order.days_since_pay <= 7: # 语句2
return True # 语句3
else:
return False # 语句4
elif order.status == "已发货": # 语句5
return False # 语句6
else:
return False # 语句7
总共有7条可执行语句。现在我们来设计测试用例:
| 测试用例 | 输入 | 覆盖的语句 | 覆盖率 |
|---|---|---|---|
| 用例1 | 已支付,3天前 | 1, 2, 3 | 3/7 = 42.8% |
| 用例2 | 已支付,10天前 | 1, 2, 4 | 4/7 = 57.1% |
| 用例3 | 已发货 | 1, 5, 6 | 6/7 = 85.7% |
| 用例4 | 已取消 | 1, 5, 7 | 7/7 = 100% |
你看,只用4个用例就能达到100%语句覆盖。但这里有个坑——我曾经遇到过一个项目,语句覆盖做到100%了,结果线上还是出了bug。为什么?因为语句覆盖只保证代码被执行了,但不保证每个分支条件都测全了。
避坑指南:我曾经在测试一个登录模块时,语句覆盖做到了100%,但漏掉了"用户名正确但密码错误"这个分支。结果上线后用户反馈说密码输错了也不报错。后来我才意识到——语句覆盖根本不管条件判断的真假,它只关心"有没有走到这行代码"。
所以我的建议是:语句覆盖作为最低标准,必须达到100%。但别停在这里,后面还有分支覆盖、条件覆盖等着你。说白了,语句覆盖就是测试的"及格线",过了这道线,你才有资格谈更深入的覆盖策略。
核心要点总结
- 语句覆盖是最基础的覆盖标准,关注"代码是否被执行"
- 计算方式:执行语句数 / 总可执行语句数
- 100%语句覆盖 ≠ 无bug,它只是最低门槛
- 实际项目中,建议先跑语句覆盖,再逐步提升覆盖标准
可可精品资料库