【AICon】AI 基础设施、LLM运维、大模型训练与推理,一场会议,全方位涵盖! >>> 了解详情
写点什么

TDD 实践之实用主义

  • 2008-10-20
  • 本文字数:4572 字

    阅读完需:约 15 分钟

TDD 的概念和实践依然在被怀疑和争议。然而,质疑者驻足不前,实践者却不再理会争论的口水,而是脚踏实地的实践,并获取高效回报。在这个过程中,我们发现 TDD 和敏捷倡导的理念,帮助我们解决了一个又一个的工程问题。

1. 为沟通选择语言

我们在一个海员管理系统的开发中遇到了问题,这个领域的专业术语我们很难翻译。即使勉强翻译出了,也感觉辞不达意,无论是初看上去,还是过一段时间再看都一头雾水。比如,我们写出了下面的测试用例:

public void test_should_return_NOT_pass_if_duty_higher_than_second_mate_or_second_engineer_and_education_level_is_secondary_and_guraduated_after_2002_02_01() {<br></br> ……<br></br>}但其中second mate/second engineer是什么意思呢? secondary 的 education level 具体又是什么?

还有:

public void test_should_return_third_mate_course_for_jianxi_third_mate() {<br></br> ……<br></br>}``jianxi_third_mate是什么? 等等。

当然,我们可以制定一个术语表,请专业人士先帮我们翻译好,然后在代码中遵循这个术语表。然而随着需求的增加,术语层出不穷,并且有特定中国特色的名词根本就没有对应的翻译,于是这个问题就一直困扰着我们。

而直到有一天,在一次重构中我们把上面的第一个测试用例重命名了一下,一切似乎突然间开朗了:

public void test_ 应该算未通过 _if_ 职务高于二副二管轮 _ 而 _ 学历只是中专 _ 并且 _ 毕业时间晚于 2002 年 2 月 1 日 () {<br></br> ……<br></br>}Team 里的人纷纷围过来,看着这个跟需求描述里的验收条件几乎一模一样的测试用例名称,感受到一种前所未有的清澈。大家几乎在几秒钟之内就做出了选择:这种形式是可以接受的,而且表达能力更强,交流效果不错。

什么? 使用中文作为函数名? 这似乎只是那些被主流舆论鄙视的"汉语编程"研究者才搞的东西,我们一直就被教育离这些东西远点,甚至汉语拼音都不推荐使用,一个经常拿来做反面教材的例子就是数据库表的列名使用汉语拼音,这被看作不专业的表现。又或者,以后团队中加入外国开发者怎么办?

幸运的是,我们是软件工程师,不是计算机科学家。学术理论可以极端,而工程一定是某种折衷。定理由自然界精确遵守,而工程却是各种应力的人为平衡。

具体到这个案例,让我们正视现实:

  1. 团队成员并不善长本项目领域的专业英语。
  2. 任何翻译都会造成一定的信息损失,尤其在一些具有中国特色的领域,比如"中专"翻译为英语就很难像中文一样简洁直观。
  3. 在可预见的将来,不会有老外加入开发团队。

而选用中文却能够让我们更好的坚持以下原则:

  1. 代码除了完成功能, 另外一个重要的功能是交流。(我们选择了对团队来说最有效的交流方式)
  2. 用测试用例的名字来描述需求。(用中文描述更精确, 易于理解)

当然我们也会失去一些东西,比如对上面提到的"应该坚持使用英文"原则的放弃。在这里我们认为放弃这条原则的收益大于损失。一种损失就是失去了学习英文的机会,比如上面最后一个测试用例,用中文写出来就是:

public void test_ 见习三副应该参加三副的培训 () {<br></br> ……<br></br>}或者有人会说:“见习"的英语是"intern”,常用词啊。然而系统中还有另外一类角色,叫"实习三副"等,那才是"intern"。实习是实际动手,担当实际的职责;见习是只看不练,跟在后面观摩学习。见习的英文单词是"noviciate",并不为项目组所熟悉,而我们也不再关心它。

总之,在实践中应当权衡各种利弊,选择对你来说最有效的方式。

2. 用大量测试来驱动

在项目组中曾经发生过自以为完成了某个特性,后来却发现漏掉了某些验收条件,甚至是比较重要验收条件的事情。而这也是 TDD 经常被质疑的一点,就是如何保证测试的完备性。因为总是想一点写一点,不经过深入的思考,不可避免的会漏掉某些测试条件。

然而,TDD 并不妨碍你深入思考,只是劝你在实现时步子不要太大,小步前进获得对问题的进一步认识以随时调整设计和实现。不过今天不争论 TDD 的哲学问题,我们只是关注用什么样的实践来消除对于 TDD 测试完备性的疑虑。

事实上,完全可以根据需求文档,验收条件,进行"深入思考",从一开始就写下所有能想到的单元测试用例,就跟测试人员在产品出来前就对着需求准备测试用例一样。

哦,等等,这还叫 TDD 吗? TDD 所强调的小步前进,随时应变哪里去了?为全面的测试用例所花费的大量努力岂不是有浪费的风险?

嗯,不错,TDD 强调小步前进的原因就是要避免浪费。如果我们能找到一种方法,既能够提醒我们不要忘记需求,又让我们在需求变化时不致浪费太多,岂不是皆大欢喜?

想想,我们用什么来描述需求? 是测试用例名称,而不是测试用例的函数体,而名称的书写几乎是没有成本的。从需求文档中把验收条件抠出来即可。如:

public void test_ 会被认为不服从调配 _if_the_seaman_ 在当前职位上曾经旷工 () {<br></br> // TODO<br></br> }<p> public void test_ 会被认为不服从调配 _if_the_seaman_ 在当前职位上曾经请过病假 () {</p><br></br> // TODO<br></br> }<p> public void test_ 会被认为不服从调配 _if_the_seaman_ 在当前职位上曾经请过事假 () {</p><br></br> // TODO<br></br> }<p> public void test_ 会被认为不服从调配 _if_the_seaman_ 在当前职位上曾经被遣返 () {</p><br></br> // TODO<br></br> }<p> public void test_ 不会被认为不服从调配 _if_the_seaman_ 在当前职位上从未旷工 _ 请病假 _ 请事假 _ 和遣返 () {</p><br></br> // TODO<br></br> }两分钟,我们就把这个用户故事的测试用例按照验收条件里说的全部描述出来了。函数体全部都是空的,因此所有的测试都是通过的,不会强迫你一次性把所有的测试都实现。

每次你流览或修改这段代码,空的函数体或里面的// TODO都会提醒你还有测试没有完成。即使你不在这个特性上工作了,切换过来的 Pair 也会从你遗留的测试用例名称中迅速的了解需要做什么。

这种方法是怎么解决问题的呢?

第一,还是让我们正视现实:如果需求描述不和代码放在一起,开发人员很少会在开发过程中去翻阅需求文档,甚至是特性编码结束后。这在成熟的开发团队中会有改善,但仍然不可避免。把需求描述以测试用例名称的方式放进代码,便会无时无刻不在提醒开发者,还有这个这个这个验收条件没满足。

第二,我们依然坚持了以下原则:

  1. 用测试用例的名字来描述需求。
  2. 小步前进,编写一个测试用例,实现一段产品代码,编写下一个测试用例,实现下一段产品代码。(因为所有的未完成测试都是通过的,不妨碍你运行测试,提交代码和持续集成)
  3. 当实现过程中发现事情并不是当初想的那样时,随时更改或删除之前写的测试用例,不会造成大的浪费。(因为只是函数名加空的函数体,成本很低)

在开始写下"所有"的测试用例名称并不意味着一劳永逸。中间当需求发生变化,我们需要对应的添加或删除一部分测试用例。在实现的过程中,发现某些条件不在验收范围内,或许是之前没考虑到,那么跟 BA/QA 确认后,需要添加到用例列表中。

(细心的读者可能发现,这里面存在着重复。就是以普通文本形式存在的验收条件和以测试用例名称存在的验收条件。或许应该有类似 SVN2Wiki 的工具,来消除这类重复)

当然,完备性还有其它的含义和检测条件,不是说你提前多写几个用例就是完备了。这里只是用一种成本最低的方式来解决问题。

3. 一个环境,多个断言

随着时间的推移,项目组发现测试运行的越来越慢。当然,这是一个普遍现象,也已经有很多方法来加速测试的运行速度。但很多需要新工具的支持,而项目组暂时没时间去切换工具。有没有其它更方便的做法?

像其它性能问题一样,我们首先需要确定瓶颈在哪里。我们发现主要是每个测试用例运行前搭建测试所需的环境相对较为耗时,尤其是 Selenium 测试,它需要启动和关闭浏览器。并且,很多测试用例其实使用相同的环境设置,只是每个用例仅仅去断言其中一个需求。

我们可以修改 Runner,让一组测试使用同一个浏览器实例,每次环境的清理通过清理 Session 来完成。而我们也可以采取另外一种方法,就是合并使用相同环境设置的测试用例,把它们的断言都放进同一个用例。

哦,这又违反了 Kent Beck 为 TDD 制定的原则:每个测试用例最好只有一个断言。

好,让我们再一次分析原则背后的理念。一个用例一个断言,是为了让测试更清晰,更精确的描述需求,测试失败更容易定位。那么有没有一种方法,既能让多个断言共享相同的环境设置,又能清晰精确的描述需求呢?

想想,我们用什么来描述需求? 是测试用例的名称,确切的说,是函数的名称。只要我们把一组组相关的断言封装到一个个函数里,给它们一个能够清晰精确的描述这组断言对应的需求的名称,然后在测试用例里面调用这些函数就可以了。这样我们只需为多个断言设置一次环境,而同时又保留了清晰精确的表达需求的能力。

@Test<br></br> public void test_should_show_step_details_info_in_todo_item_page() throws Exception {<br></br> TodoItemPage page = navigator.gotoTodoItemPage( );<p> should_show_step_name_as_page_title(activeStepOfNonStartedInstance, page);</p><br></br> should_show_start_processing_button_if_current_step_status_is_waiting(page);<br></br> should_show_transition_buttons(activeStepOfNonStartedInstance, page);<br></br> should_NOT_ask_user_to_input_his_opinion_if_current_step_status_is_NOT_processing(page);<br></br> should_show_comment_box_after_click_start_process(page);<br></br> }<p> private void should_show_step_name_as_page_title(FlowStep step, TodoItemPage page) {</p><br></br> assertEquals(step.getName(), page.title());<br></br> }<p> private void should_show_start_processing_button_if_current_step_status_is_waiting(TodoItemPage page) {</p><br></br> assertTrue(page.isStartProcessingButtonVisible());<br></br> }<p> private void should_show_comment_box_after_click_start_process(TodoItemPage page) {</p><br></br> page。clickStartProcessingButton();<br></br> assertTrue(page.isCommentBoxAppear());<br></br> }<p> private void should_ask_user_to_input_his_opinion_if_current_step_status_is_processing(TodoItemPage page) {</p><br></br> assertTrue(page.isCommentBoxVisible());<br></br> assertTrue(page.isActionButtonsVisible());<br></br> }<p> private void should_ask_user_to_select_next_step_operators(FlowTransitionDefinition nextTransitonOfStep,</p><br></br> TodoItemPage page) {<br></br> assertTrue(page。isUserGroupVisible(nextTransitonOfStep.getId()));<br></br> }<br></br> ……## 小结

回过头来我们看看上面的三个实践,它们如出一辙的,一次又一次的"违反"了某种原则。它们分别是"不能用汉语",“不能一次编写多个测试用例”,和"不能在一个用例里面使用多组断言",而实际上,我们违反的只是这些原则的外在形式,但却坚持了这些原则背后的思想,如最有效的沟通,注重实效而不是形式。以此为基石,我们可以在出现新的约束的情况下,灵活运用,发明各种实践,并享受由此带来的效率提升。


作者简介:李光磊,软件工程师,同时还是一位敏捷教练,就职于 ThoughtWorks。他还是活跃的 blog 作者,了解他最新的想法,请访问 http://blog.csdn.net/chelsea

2008-10-20 01:023339

评论

发布
暂无评论
发现更多内容

金三银四 面试准备 数据结构面试题,编程与算法经典面试题

测吧(北京)科技有限公司

测试

JetBrains PhpStorm 2023 for Mac(PHP集成开发)v2023.3.2中文激活版

iMac小白

PhpStorm 2023下载 PhpStorm mac

YashanDB V23.2 LTS发版 | 共享集群首个长期支持版本

YashanDB

产品发布 yashandb 共享集群 崖山数据库

PDF Reader Pro for mac(全能pdf编辑阅读软件)v3.3.1.0直装激活版

影影绰绰一往直前

PDF Reader Pro中文 PDF Reader Pro破解 PDF Reader Pro下载

软件测试学习笔记丨Selenium自动化关键数据记录

测试人

软件测试 自动化测试 测试开发

重磅新品发布!云耀数据库HRDS,享受轻量级的极致体验

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号2024年4月PK榜

coconutBattery Plus for Mac(电池质量检测工具)3.9.15 直装版

iMac小白

coconutBattery Plus

XMind for mac (XMind思维导图)v24.01.14362中文版

iMac小白

XMind 2024思维导图 XMind 2024中文

AI将诗意装进口袋!合合信息扫描全能王“扫描书籍”功能优化上线

合合技术团队

人工智能 OCR 图片识别 扫描全能王 扫描书籍

小程序实现前端热更新的技术原理

Geek_2305a8

苹果Mac电脑窗口辅助管理工具:Magnet for Mac 支持M1

影影绰绰一往直前

Magnet for mac Magnet中文版 Magnet Mac下载

KeyShot 2024.1 for mac(3D渲染和动画制作软件)v13.0.0.92破解版

iMac小白

KeyShot 2024许可证 KeyShot2024下载 KeyShot 2024安装包

Autodesk AutoCAD 2024 Mac(cad2024激活版)v2024.3.61.182中文激活版

iMac小白

AutoCAD 2024 Mac版 AutoCAD 2024下载 AutoCAD 2024破解

NTFS Disk by Omi NTFS for mac(NTFS 磁盘管理器)v1.1.4中文版

影影绰绰一往直前

华为阅读·读书会:品读“外卖诗人”眼中的诗与画

最新动态

深化MIAOYUN定位,坚守产品初心!

MIAOYUN

容器 云原生 产品定位 智能运维 MIAOYUN

Alfred 5 for Mac(苹果应用快速启动器)v5.1.4 (2195)中/英免激活版

iMac小白

Alfred 5下载 Alfred 5 Mac Alfred 5破解版

【JAVA】助力数字化营销:基于协同过滤算法实现个性化商品推荐

智在碧得

机器学习 数据 java 编程 分布式框架 数字化营销

EMQX Platform 产品发布会回顾:全球部署与无缝数据集成,驱动汽车行业智能化转型

新消费日报

PDF Expert for Mac(PDF编辑阅读转换器)v3.10中文激活版

iMac小白

PDF Expert下载 PDF Expert for Mac PDF Expert破解版

当世界读书日遇见华为阅读:让电子书读出“画面感”

最新动态

Rust 和 Go?通过详细比较选择最佳编程语言

Liam

Go 编程 程序员 rust 编程语言

LED电子显示屏新技术

Dylan

技术 信息 数字 电子 LED显示屏

MindNode for mac(思维导图软件)v2023.3.1中文激活版

iMac小白

MindNode破解版下载 MindNode for mac

MestReNova for Mac(专业核磁数据处理软件)v14.2.3中文激活版

iMac小白

MestReNova软件 MestReNova14破解版 MestReNova下载

Maplesoft Maple 2024 for mac(专业的数学计算软件)v2024.0激活版

影影绰绰一往直前

Lightroom Classic 2023 for mac(专业数字照片处理软件)v12.5中文激活版

影影绰绰一往直前

Lightroom Classic 2023 Lightroom Classic 下载 Lightroom Classic 破解版

Tableau Desktop 2019 for Mac(最好用的数据分析工具)v2019.1.0中文激活版

iMac小白

给测试同学的成长书单

老张

书单推荐 技术书单

Cinema 4D 2024 for mac(c4d 2024)v2024.3.2中文激活版

影影绰绰一往直前

Cinema 4D 2024 Cinema 4D下载 Cinema 4D破解版

Topaz Video AI for mac(地表最强视频无损放大修复工具)v5.0.2激活版

影影绰绰一往直前

Topaz Video AI下载 Topaz Video AI破解版 Topaz Video AI中文版

TDD实践之实用主义_研发效能_李光磊_InfoQ精选文章