测试插入与断言覆盖收敛实战 - 第2节

语句覆盖:定义与原理

语句覆盖,说白了就是测试用例执行了多少行代码。我刚开始做测试时,总觉得这玩意儿太基础了,不就是看代码跑没跑过嘛。但后来踩过坑才明白——它是最底线的质量门禁。

它的核心定义很简单:每个可执行语句至少被执行一次。注意我说的是"可执行语句",像变量声明、空行、注释这些都不算。你想想看,如果一段代码里有一行从来没被执行过,那这行代码写出来干嘛?

语句覆盖的数学定义

语句覆盖率 = (被执行的语句数 / 总可执行语句数) × 100%

嗯,这里要注意:语句覆盖只关心"有没有执行",不关心"执行结果对不对"。它是最弱的覆盖标准,但也是必须跨过的第一道坎。

如何计算语句覆盖率

计算过程其实就三步,我习惯这么教新人:

  1. 数总数——先找出代码里所有可执行语句的数量
  2. 看执行——跑测试用例时,记录哪些语句被触发了
  3. 算比例——用执行数除以总数,得到覆盖率

举个例子,假设有这段代码:

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,它只是最低门槛
  • 实际项目中,建议先跑语句覆盖,再逐步提升覆盖标准
语句覆盖核心逻辑流程图 源代码 识别所有可执行语句 设计测试用例执行代码 计算语句覆盖率 关键点 • 只关心"是否执行" • 不关心执行结果 • 最弱的覆盖标准 • 必须达到100% • 但仅此不够 ⚠ 注意分支条件

可可精品资料库