可达性(Reach):语法可达 vs 语义可达

基础概念:什么是"可达"?

在控制流图(CFG)中,可达性描述的是:从某个节点出发,能不能"走到"另一个节点。

基本定义: 如果存在一条路径从 v1v_1 开始、到 v2v_2 结束,则称 v1v_1 可以到达 v2v_2


语法可达(Syntactic Reach)

图中存在这条路径 —— 只要边连着,就算可达。

这是一个纯图结构上的概念,不管程序逻辑、不管输入数据,只看图里有没有这条路。

举例:

1 → 2 → 5

    3 → 4 → 7

        6

v2v_2 语法上可以到达 v5v_5 —— 因为图中存在 v2v5v_2 \to v_5 这条边/路径。


语义可达(Semantic Reach)

存在一个实际测试用例,能真正执行到这条路径 —— 光有边不够,得能跑起来。

这是程序执行层面的概念。有些路径在图上存在,但由于条件约束,任何输入都不可能让程序走这条路,那它就是语义不可达的。


两者的关键区别

判断依据关注点
语法可达图的结构(有没有路径)图论
语义可达实际测试用例能否执行到程序逻辑 + 数据

语义可达语法可达\text{语义可达} \subseteq \text{语法可达}

语义可达一定语法可达,但语法可达不一定语义可达。


经典例子

func foo(x int) int {
    if x > 0 {
        if x < 0 {   // 这个分支语法上存在,但永远不会执行
            return -1
        }
    }
    return 0
}

在 CFG 中,x < 0 这个 true 分支语法可达(图中有这条路),但语义不可达x > 0x < 0 同时成立是不可能的)。


白盒测试

语句覆盖:使程序中的每条可执行语句至少执行一次

分支覆盖:使程序中的每个分支至少执行一次

条件覆盖:使程序中每一个条件的所有取值至少被执行一次

  • 条件覆盖不一定是分支覆盖,分支覆盖不一定是条件覆盖

条件-分支覆盖:使程序中每个条件所有取值至少执行一次,并使每个判断本身可能判定结果也执行一次

条件组合覆盖:使程序中每个判定中条件各种组合都至少出现一次