1 背景
采用计算机进行需求自动处理时,获得需求的精确语义是前提条件。如果需求语义分析错误,则所生成的测试用例、所进行的需求缺陷分析也很难是正确的。
本文讨论一种常见的需求类型,即条件(conditional)需求的语义模糊问题。(前文讨论了事件、状态的语义模糊问题)
条件需求是一种基础、常见的需求描述方式。例如,一条典型的条件需求如下:
REQ1:如果系统检测到错误(p),则应告警(q)。
上述条件需求所描述的前件p和后件q的关系,存在命题逻辑和时态逻辑两个角度的语义模糊问题。如果不做语义澄清,由计算机自行对需求进行语义解释,从用例生成的场景来说,会生成不恰当的测试用例集,导致缺陷的误报(false positive)、漏报(false negative)。
2 从命题逻辑角度
对“如果p,则q”、“当p,则q”这种类型的需求,从命题逻辑角度,存在两种解释:
p和q是蕴含关系,即p→ q
p和q是等价关系,即p↔q
2.1 蕴含关系
如果p和q是蕴含关系,其真值表如下:
编号 | p: 检测到错误 | q:告警 | p→ q |
1 | True | True | True |
2 | True | False | False |
3 | False | True | True |
4 | False | False | True |
如果要进行判定覆盖,则应包含如下两条用例:
用例1:令p为真(检测到错误),验证q为真(发生告警);
用例2:令p为假(没有检测到错误),验证q为假(没有发生告警)
对于蕴含关系,在生成用例时,所谓判定覆盖是不可行的。由真值表可见,p为假,q可以为真。因此用例2在逻辑上是不成立的。即“没有检测到错误,发生告警”这种情况是允许的。这往往会引起疑问。
之所以如此,是因为在的蕴含关系中,前件p是后件q的充分条件,而不是必要条件。更显著的需求实例如下:
REQ1-1:如果系统检测到错误1,则应告警。
REQ1-2:如果系统检测到错误2,则应告警。
REQ1-3:如果系统检测到错误3,则应告警。
可见,上述需求中,每一种错误都是告警的充分条件,但不是必要条件。
针对上述需求,如果进行综合,即:
REQ1’:如果系统检测到错误1 或 错误2 或 错误3 (p),则应告警(q)。
此时,如果所有的可能的错误都已经枚举出来,则上述需求的p、q成为等价关系。
2.2 等价关系
如果p和q是等价关系,则有“当且仅当p,则q”。此时,p是q的充分、必要条件。
对于等价关系,则可进行判定覆盖,即: 令p为真,则q为真;令p为假,则q为假。
2.3 对用例的影响
在实际工程中,条件需求中,蕴含语义、等价语义的情况都是存在的。
一般来讲,将条件需求解释为等价关系的场景下,往往需求经过了设计综合,单条需求表现为较复杂的逻辑;当每条需求的逻辑都较为简单时,则更可能是蕴含关系。
如果条件需求是等价关系,则可生成判定覆盖用例。
如果条件需求是蕴含关系,则生成用例时需要讨论。仍然考虑前述需求,即:
REQ1-1:如果系统检测到错误1,则应告警。
REQ1-2:如果系统检测到错误2,则应告警。
REQ1-3:如果系统检测到错误3,则应告警。
对该需求,显然每种错误都是告警的充分条件,而不是必要条件。现实中的一种争议点在于:在测试场景下,系统激励是受控的,如果能控制错误2、错误3的状态,而单单使错误1决定是否告警,那不就能够对错误1进行判定覆盖测试了?
这种说法成立的前提,本质上是对告警逻辑进行了全面综合,然后对综合后的逻辑进行MC/DC覆盖。但是,实际中,由于相关需求分布在各处,进行综合是非常困难的,这将导致无法全面控制关联条件。
如果无法控制关联条件,则在测试中就会出现测试结果的不确定性,也即一条测试用例是否通过,依赖于不受控的系统状态。在验收测试等场景下,这是不可接受的。
3 从时态逻辑角度
从时态逻辑角度,对“当p,则q”这种类型的需求,存在如下解释:
p和q同时发生,即□(p→ q);
p发生后,q立即发生,即□(p→ 〇q);
p发生后,q最终总会发生,即□(p→ ◇q);
或者更接近工程语言的描述为:当p发生,在时间区间[Tlower, Tupper]内,q发生。
在实际需求中,能够对响应时间做出约束的情况较为少见。这实际上成为一个模糊地带。在执行验证时,设置激励条件p后,什么时候应该判决q呢?这个语义模糊,很可能成为测试系统中一个隐含的经验参数,即经过反复迭代,认为某个等待时间是可以接受的。
然而,不同用例对等待时间的敏感性不同,长了不行,短了也不行,继而要求对不同用例设置不同的判决等待时间。这最终导致测试系统的反复调试,降低了自动化测试的整体效率。
4 如何澄清语义
要澄清语义,在需求定义阶段实现更精确的语义描述,当然是一种从源头解决问题的办法。就本文讨论的条件需求的模糊语义来讲,一方面可以从条件需求的语句结构上,明确指明条件类型(充分条件或充分必要条件),来消除蕴含、等价关系的模糊;另一方面,可以补充响应的时间约束关系,来消除时态意义上的模糊。
然而,在实际工程中,到了验证阶段,除非需求错误,按照上述方式更新需求基本是不可能的。对需求语义中的模糊部分,一般通过沟通、解释来澄清;无法澄清的,则靠工程经验、调试来弥合。
同时,也应考虑到,在需求、实现、验证的各个阶段及各个相关方,歧义很可能是不可避免的。哪怕在需求定义阶段按照某种规则定义了精确语义,但是在验证阶段,由于对规则的理解偏差,仍然可能解读出错误的需求语义。
这实际上体现了测试的作用。测试独立于实现,通过对需求的解读,构造测试用例,对软件或系统进行测试,某种意义上就是为了发现偏差。如果测试不通过,既可能是实现错误,也可能是测试错误。通过分析,才能获得一致理解,消除缺陷。
5 总结
本文从命题逻辑和时态逻辑两个角度,讨论了条件需求这一广泛使用的需求类型中存在的语义模糊问题。从测试用例生成的角度,对语义的错误解读,将导致生成不恰当的用例,需要消耗大量的调试时间消除缺陷,降低了自动测试系统的整体效能。
从测试验证角度,语义模糊是一种客观现实,也是验证活动本身的重要目的所在;然而,从系统角度,则应使系统开发过程的各个活动具有更精确的信息传递途径,消除传递误差,从而提升整体效率。因此,我们会说,要把测试验证做的更高效、更准确,根源在需求开发、系统设计。这是整体互动。