TDD测试驱动开发︱一个完整的TDD测试驱动开发演练案例
2022-11-06
来源:逸言 我是张逸
这个职责?恩,注意,这里其实包含了两项任务:记录与显示。当我们看到类似“和”、“或者”等并列连接词时,都应该思考它是否表达了多个职责?因此,对于第四个任务,我们应该稍稍拆分一下,分解成两个任务:
记录历史猜测数据;
显示历史猜测数据;
那么应该谁来“记录历史猜测数据”?我们应该寻找承担该职责的对象。
知识:寻找职责的承担者
寻找职责的承担者,其实就是寻找某个可以承担该职责的角色。角色又是什么?想象我们现实世界中的角色。看看我们身边,是否角色遍地可寻?BA角色负责分析需求,DEV角色负责实现功能,QA角色负责测试功能是否正确,PM角色负责管理整个项目的进度与项目成员。我们是依据什么来划分角色的?——能力。能力的体现是什么?除了诸多素质要求,最直接的体现就是“知识”。因此,所谓“角色”,就是拥有了相关“知识”从而具有相关“能力”的人。
什么角色应该记录历史猜测数据呢?那就是要寻找谁具有记录历史猜测数据的能力。于是推之于知识,就是谁拥有每一次猜测的数据。显然,Game拥有当前猜测的数据,因此承担责任的应该为Game。
现在,开始编写测试。既然已经辨别出Game对象,就应该针对它编写测试方法,让我们还是从测试方法的业务逻辑描述开始吧:
在这里,实际上我驱动出了Game的guessHistory()方法,同时还得到了一个封装了猜测结果的GuessResult对象。与第一个任务不同的是,我没有使用字符串来表示猜测结果,这是因为这里的历史猜测数据不仅包含了猜测结果,还包含了当前的测测数据。
现在,应该考虑“显示历史猜测记录”的任务了。这个功能就是要在猜测了数字之后,在控制台显示历史猜测记录。虽然是控制台,我们仍然认为这属于界面的工作。TDD根本就不应该用来驱动界面设计,还是将注意力放到业务逻辑上来吧。抛开界面,这里的逻辑就转换为:
当用户猜测了数字后,应该显示历史猜测记录。
将界面与业务逻辑分开体现了“关注点分离”原则,也是表现层设计的常用做法。最常见的处理界面设计的模式就是MVC模式。因此在这里可以引入GameController类,就目前而言,它可以负责Game与GameView的协作,所以相应的还可以为界面显示定义一个专属的View对象。
虽然在这里是用控制台显示历史猜测数据信息,实现非常简单,直接调用System.out.println()方法即可,然而我们却很难测试控制台是否显示了该信息。虽然有一些框架也提供了Mock控制台的功能,但就TDD而言,这样的测试并无实际意义。我们需要合理地辨别在功能实现中,哪些内容适合编写自动化测试,哪些内容适合人工测试。因此,这里可以引入Mock框架来模拟GameView,我们只需验证Controller与View之间的协作即可。这时,测试还有助于我们设计出可测试性好的类。
因为是Controller,需要接受用户输入,而非直接传入答案的字符串值。同理,我们在TDD中也不可能测试业务逻辑与控制台的交互。因此,同样需要引入InputCommand类型来封装输入逻辑,然后以Mock框架来模拟InputCommand。 故而,我们为该功能编写的测试为:
在编写该测试之前,我们实则做了一部分设计与分析工作,辨别各种职责以及承担这些职责的对象,尤其重要的是,要分辨出它们之间的协作方式。对协作的分析应以被测对象为主。一
免责声明:
1、IT项目管理界发布的所有资讯与文章是出于为业界传递更多信息之目的,并不意味着赞同其观点或证实其描述。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请浏览者仅作参考,并请自行核实相关内容。
2、本站部分内容转载于其他网站和媒体,版权归原作者或原发布媒体所有。如文章涉及版权等问题,请联系本站,我们将在两个工作日内进行删除或修改处理。敬请谅解!