06|TDD中的测试(2):行为验证为什么应该尽量避免使用?
验证结果——行为验证
行为验证是指通过待测系统与依赖组件(Depended On Component)的交互,来判断待测系统是否满足需求的验证方式。其验证方式如下图所示:
[图片上传失败...(image-2ff558-1674315666464)]
行为验证背后的逻辑是,状态的改变是由交互引起的。如果所有的交互都正确,那么就可以推断最终的状态也不会错。
在 TDD 社区中,行为验证主要是为了降低测试成本。
对于类似于数据库这样的进程外组件,我们都可以通过类似的手段加以处理。也就是说,明确指明待测系统如何与进程外组件交互,并以此为基准,验证待测组件的行为是否满足需求。类似的场景还有很多,比如三方支付服务、消息队列(Message Queue)或者其他微服务等等。
除了进程外组件,还有一种情况是进程内组件的状态难以获得。最典型的例子就是具有图形界面(Graphics User Interface,GUI)的应用,比如 Android App、Eclipse RCP 等等。在有 GUI 的情况下,我们需要测试视图(View)与模型(Model)的状态一致。通常视图中的状态难以获取,或者获取成本极高(比如我就有过很多次需要从头写 GUI TestDriver 的情况)。在这种情况下,也可以使用行为验证来代替状态验证,完成测试。
对 TDD 用处不大
无可否认,行为验证是一种有用的技巧,但是对 TDD 用处不大。
状态验证是将测试上下文与待测系统当作一个整体的黑盒验证,而行为验证就是将它们看作分离组件的白盒验证。
它的逻辑是通过测试功能是如何实现的,来推断结果是否正确。换句话说,行为验证本身并不能验证功能是否正确,而只能验证功能是否按照某种方式实现。如果按照某种方式实现,那么就可以推测出功能是正确的。
这与 TDD 的核心逻辑就冲突了。在 TDD 的红 / 绿 / 重构中,重构要求在功能不变的前提下,改变实现方式。而对于行为验证而言,实现方式改变就是功能改变。因而重构就无法进行!需要重写!也就是说,行为验证会阻碍 TDD 的进行。
除去与 TDD 的逻辑冲突之外,行为验证还可能会丧失测试的有效性,特别是在依赖复杂的框架或是进程外组件的时候。
网友评论