BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

文章:TDD实践之实用主义

| 作者 李光磊 关注 0 他的粉丝 发布于 2008年10月21日. 估计阅读时间: 不到一分钟 | GMTC大前端的下一站,PWA、Web框架、Node等最新最热的大前端话题邀你一起共同探讨。

在软件开发实践中,经常会遇到这样的情形:按照书上的某种理论或者原则,无法直接解决我们遇到的问题,甚至会引入新的问题。因为任何一种书本上的“实践”,都是针对某种特定的环境,不可能放之四海而皆准。

尤其是一些相对较难把握的实践,如TDD,从诞生的那一天起就争议不断。

然而,我们是应该奉这些原则和理论为圣经,不敢越雷池一步;还是基于理论背后的思想,结合自己的实际问题,以实用主义的态度继续实践?

让我们来看看在一个实际的项目中我们采取的做法。

阅读文章全文:TDD实践之实用主义

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

实践者的实用文章 by 田 乐

在测试里面保有更多的场景描述的元数据非常好,可以让测试和验收条件合二为一。中文是多字节编码的,所以实际上我们可以在支持Unicode的Java里面使用同样的方法名长度限制下写出更清楚的验收条件,就好比中文的Twitter可以比英文的Twitter在同样73个字符的限制下写更多的句子(保有更多的信息)。

很不错的总结啊 by 张 晓庆

第二个原则是一个很不错的实践,现在一直在用。
比如开发一个story,需要涉及到界面/controller/dao多个部分。首先在selenium测试中写出类似于验收条件的空测试方法,可以很大程度上避免漏掉一些验收条件。

关于使用中文 by Zoom Quiet

如果可以使用Python 的话,
有中蟒和周蟒可以选择,其中 周蟒~ zhpy
code.google.com/p/zhpy/

跟上了Python 的版本,而且不依赖其它模块,可以直接使用,,,

Bad smell: 冗长的方法名而且还是中文的 by Zhang Charlie

赞成作者的实用主义观点。但冗长的方法名,而且还是中文的,实在有点离谱。

目前的这个方案是脆弱的,难以适应变化(中文方法名称本身就是不稳定的),我觉得作者给出的理由也是不充分的。中文术语名称,也未必比英文术语更稳定、更准确吧。

这样就真的做到了“最有效的沟通”和“最有效的交流方式”?而用了这么多下划线,是自找麻烦,可读性反而下降了。

jianxi_third_mate 更像一个笑话。

test case 方法名其实可以很简单,比方用某些关键词结合 ID 来命名。说明测试的目标或内容,为什么不能采用注释、注解、映射表或其他辅助工具呢?

总之,用中文方法名,尤其还是冗长的、难以输入、维护和适应变化的方法名,是个 bad idea,我一开始就不会用(省却了重构的麻烦)。

中西合璧的敏捷 OO 教练 张恂
www.zhangxun.com

中文夹杂着英文的方法名 by zhu pan

中文夹杂着英文的方法名看着实在是比较恶心啊

重构方法名:test_见习三副应该参加三副的培训 by Zhang Charlie

“test_见习三副应该参加三副的培训”怎么看都不像一个合理的方法名,建议避免使用。


比如上面最后一个测试用例,用中文写出来就是:

public void test_见习三副应该参加三副的培训() {
……
}


太极敏捷最佳实践:

1)开发中所有人员一律采用统一的术语表和中英文译法;

2)对于常用的关键词、领域概念、专业术语,规定统一的英文简写、缩写和/或标记代码,以便在代码、文档、模型等各种工件中使用;


Solution:

1)所有的专用术语“三副”均应采用缩写,比方 3M,见习三副(3Mn),实习三副(2Mi);

2)把所有与“见习三副”有关的测试都放入一个测试类中(基于高内聚原则),这样就可以去掉所有测试方法名前、累赘的“见习三副”;

举例:

// TCNote: 见习三副应该参加三副的培训(该注释其实可省略)
public void testAttend3MTraining() {...}

是不是更加简明、方便而有效?

Bad Smell: Long, complex test conditions as method name by Zhang Charlie

本文采用复杂的测试条件作为方法名,降低了测试程序的可读性、可维护性,容易产生错误。建议不要采用。


原先的代码:

@Test
public void test_should_show_step_details_info_in_todo_item_page() throws Exception {
TodoItemPage page = navigator.gotoTodoItemPage( );
should_show_step_name_as_page_title(activeStepOfNonStartedInstance, page);
should_show_start_processing_button_if_current_step_status_is_waiting(page);
should_show_transition_buttons(activeStepOfNonStartedInstance, page);
should_NOT_ask_user_to_input_his_opinion_if_current_step_status_is_NOT_processing(page);
should_show_comment_box_after_click_start_process(page);
}

private void should_show_step_name_as_page_title(FlowStep step, TodoItemPage page) {
assertEquals(step.getName(), page.title());
}

private void should_show_start_processing_button_if_current_step_status_is_waiting(TodoItemPage page) {
assertTrue(page.isStartProcessingButtonVisible());
}

private void should_show_comment_box_after_click_start_process(TodoItemPage page) {
page.clickStartProcessingButton();
assertTrue(page.isCommentBoxAppear());
}

private void should_ask_user_to_input_his_opinion_if_current_step_status_is_processing(TodoItemPage page) {
assertTrue(page.isCommentBoxVisible());
assertTrue(page.isActionButtonsVisible());
}

// ...


以上程序不但可读性差,而且好像还存在着逻辑错误。

Refactoring results:

原先代码中的几个 private 方法,完全可以采用更加简洁而有效的名称。

Class TestTodoItemPage

@Test
public void testStepDetailsInfoScenarioA() throws Exception {
TodoItemPage page = navigator.gotoTodoItemPage();

verifyPageTitle(activeStepOfNonStartedInstance, page);

verifyStartProcessingButton(page);

verifyTransitionButtons(activeStepOfNonStartedInstance, page);

verifyNotAskUsrInputOpinion(page);

page.clickStartProcessingButton();
verifyCommentBox(page);
}


// = step name
private void verifyPageTitle(FlowStep step, TodoItemPage page) {
assertEquals(step.getName(), page.title());
}

// if step status is waiting
private void verifyStartProcessingButton(TodoItemPage page) {
assertTrue(page.isStartProcessingButtonVisible());
}

// if step status is NOT processing
private void verifyNotAskUsrInputOpinion(TodoItemPage page) {
assertFalse(page.isCommentBoxVisible());
assertFalse(page.isActionButtonsVisible());
}

// after clicking start processing
private void verifyCommentBox(TodoItemPage page) {
assertTrue(page.isCommentBoxAppear()); //?? page.isCommentBoxVisible()
}

Re: 重构方法名:test_见习三副应该参加三副的培训 by yanhui li

这种做法的话,在junit的report里只能看到“testAttend3MTraining”失败了,谁懂?

就算是项目组开发人员,如果有更简单清楚的方法,谁愿意背那么多术语对应代码


举例:

// TCNote: 见习三副应该参加三副的培训(该注释其实可省略)
public void testAttend3MTraining() {...}

是不是更加简明、方便而有效?

Re: 重构方法名:test_见习三副应该参加三副的培训 by Zhang Charlie


2008年10月30日 上午12时26分 发表人 yanhui li

这种做法的话,在junit的report里只能看到“testAttend3MTraining”失败了,谁懂?

就算是项目组开发人员,如果有更简单清楚的方法,谁愿意背那么多术语对应代码


对于大副、二副、三副之类的常用词,大家约定采用缩写、助记符(比方 1MTE、2MTE、3MTE)还是有必要的,既简单、又清楚,开发人员天天用,还需要背吗?

当然,还是要控制缩写、助记符的范围和数量,如果不常用的、确实难记、易混淆的就没必要缩写了。

Re: 重构方法名:test_见习三副应该参加三副的培训 by 熊 节

对于大副、二副、三副之类的常用词,大家约定采用缩写、助记符(比方 1MTE、2MTE、3MTE)还是有必要的,既简单、又清楚,开发人员天天用,还需要背吗?

船上的职位总共有71个,人家信息中心干这个系统干多少年了都得现用现查,你牛逼,你都能背下来。
还扯什么“把所有与“见习三副”有关的测试都放入一个测试类中”。几十个功能,每个功能都涉及到每个职位。我这个人有点笨,我不知道一个功能的测试散在71个测试里它怎么就符合“高内聚原则”了。
有些话我都说烂了。没有实践经验就少扯些看起来很美其实狗屁不通的蛋。哦对了,听说你最近又去了某CMM 5级企业做咨询,看见他们的配置管理问题了吗?怎么还没见你摘他们牌呢?

霍编辑,这回又是 Jeff Xiong 先挑起的(请勿删贴) by Zhang Charlie

看清楚了吧,希望你们不要再包庇,混淆是非。


2008年11月2日 上午3时32分 发表人 Jeff Xiong

船上的职位总共有71个,人家信息中心干这个系统干多少年了都得现用现查,你牛逼,你都能背下来。

还扯什么“把所有与“见习三副”有关的测试都放入一个测试类中”。几十个功能,每个功能都涉及到每个职位。我这个人有点笨,我不知道一个功能的测试散在71个测试里它怎么就符合“高内聚原则”了。

有些话我都说烂了。没有实践经验就少扯些看起来很美其实狗屁不通的蛋。哦对了,听说你最近又去了某CMM 5级企业做咨询,看见他们的配置管理问题了吗?怎么还没见你摘他们牌呢?


我们本来在认真地探讨技术问题,没想到这个“大嘴”惹事佬又跳将出来。其实 Jeff Xiong 自 2005 年放弃著名媒体人的身段以来,连 5 年的正式开发经验都没有,有什么资格跟别人理论“实践经验”呢?秉性使然。

霍编辑,按照你们 InfoQ China 的标准,这算不算恶意的谩骂和人身攻击呢?

怒放几个“牛逼”、“扯淡”、“狗屁不通”,并不能代表你熊节的牛逼吧。这些词汇,既然你们 InfoQ 中国的编辑可以用,我们读者当然也可以用了。

我看 Jeff Xiong 这种“裤腿撕咬者”、“狂躁症患者”的著名缔造者,素质低、品质差的混混(已经被其这些年来的言行所实证),显然不配继续留在 InfoQ 中国的编辑队伍里,建议你们早点清理门户,免得大家难堪,避而不及。

It's really a SHAME for an InfoQ editor to behave like this.

Jeff Xiong 再现狗屁不通的逻辑 by Zhang Charlie

2008年11月2日 上午3时32分 发表人 Jeff Xiong

船上的职位总共有71个,人家信息中心干这个系统干多少年了都得现用现查,你牛逼,你都能背下来。


71 个职位,当然没必要全背。但其中可能有十几个、几十个是常用的,而像大副、二副、三副之类的日常词汇,还需要背吗?

我的建议是,对于常用业务词汇在程序中可以采用缩写/助记符代替,比方 1MTE、2MTE、3MTE 等等,以简化程序的编写(这本来是废话,稍有点实践经验的程序员都明白,可有些人就是连废话也不懂)。

我可没建议大家把这 71 个职位都背下来。对于生僻、难记的完全可以现用现查。

熊节却扯出了“你牛逼,你都能背下来”。什么阅读、理解力?这叫无理取闹。

2008年11月2日 上午3时32分 发表人 Jeff Xiong

还扯什么“把所有与“见习三副”有关的测试都放入一个测试类中”。几十个功能,每个功能都涉及到每个职位。我这个人有点笨,我不知道一个功能的测试散在71个测试里它怎么就符合“高内聚原则”了。


我们这里讨论的是如何简化 test_见习三副应该参加三副的培训()。

把与见习三副相关的、见习三副作主语的、见习三副发起的 ... 测试都归并到一起,可以简化测试方法名称的书写,没必要写 n 个“见习三副应该 ...”,这是显而易见的方法。而把见习三副的测试与其他无关的测试混在一起,很可能违反了高内聚原则。

“见习三副应该参加三副的培训”,这个功能涉及到了每个职位?扯蛋吧。

而 Jeff Xiong 所谓的“一个功能的测试散在71个测试里”,更是不知所云。

我看你这个人不能叫一点笨,是相当的笨。这就叫胡搅蛮缠,自取其辱。

Re: Jeff Xiong 再现狗屁不通的逻辑 by 熊 节


“见习三副应该参加三副的培训”,这个功能涉及到了每个职位?扯蛋吧。

而 Jeff Xiong 所谓的“一个功能的测试散在71个测试里”,更是不知所云。

说你牛逼你还真牛逼。
我要是告诉你还有个测试说“见习三管轮应该参加三管轮的培训”,不知道您老又做何感想呢?
顺便告诉你吧,这样的逻辑,它还真有好几十个。没办法,谁叫人家海员级级晋升都要培训呢?
71 个职位,当然没必要全背。但其中可能有十几个、几十个是常用的

真糟糕,这71个职位总是同时出现。没办法,谁叫人家一统计总是要所有职位都一起统计呢?其实我也觉得船长轮机长大副大管轮之类的应该比其他虾米职位更重要,可惜啊,客户他不这么想啊。

再说一遍,没有实践经验就少扯这种看起来很美其实狗屁不通的蛋。你这辈子就没干过一个跟航运有关的项目还扯什么“常用职位”,说真的,你知道啥叫职位不?

原来这种descriptive的方式也被TDD使用啊 by 徐 毅

原以为只有acceptance test里面才使用到这种命名的方式呢。

张恂对于本案的详细分析 by Zhang Charlie

全文请见:

www.zhangxun.com/?sname=InfoQTDDPractice


作者 李光磊 发布于 2008年10月20日 上午1时2分

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


总体上,我肯定作者反对教条、提倡创新和重构的思路,这种精神值得发扬。但另一方面,我认为作者的重构在技术上还没有到位,为了实现“注重实效而不是形式”的目标,我们还需要继续重构。

原文的篇幅不长。从目前作者所提供的信息来看,我认为作者的分析是比较片面的,因为过分自信而导致片面,只看到了这些“创新”做法可能带来的好处和优点,而对这些做法存在哪些缺点和不足,却分析得不够,既缺乏深入性和全面性,也缺乏前瞻性。作者及其同事们所给出的三个实践,尤其是直接把冗长的有关测试/验收条件、测试结果的说明用作(简单地拷贝为)测试用例的方法名这一做法,违反了简化、稳定、灵活和 DRY(Don't Repeat Yourself)等敏捷软件的基本设计原则和思想。我认为目前原文中给出的解决方案,只能算是一些低成本的、脆弱的、不稳定的临时措施(临时搭建的工棚?),存在明显的 bad smells,需要通过重构来进一步提高测试程序的质量。

当然,如果作者或他人能够给出支持这些做法的更充分的信息和理由,我也准备接受。


资深敏捷 OO 教练
www.zhangxun.com

无意制造新矛盾,只是想说说想法。 by Lin Qing

感觉这样,
技术讨论很不错,
有新想法也不错,
说些有点脏的话也没什么,
没必要太在意,显得小气了。

倒是为何那个教练老是给自己做广告呢?
自夸在我看来总是有些自大。
虽然,自信没问题,但是,
中国嘛,还是要收敛些的好吧。

这样复杂的测试,
用动态语言会不会更加方便呢?
这样很多重复且又有微小差别的测试可以动态创建。

Re: 无意制造新矛盾,只是想说说想法。 by X 1073

还吵呢。。。这都多久了。。。。有什么深仇大恨滴。。。。。

用注释蛮好啊,不理解为什么一定要在case的命名上斤斤计较。。。。是有工具可以支持通过名字做某些操作的功能吗?如果是那样是不是有些太依赖工具了。。。。。
第2和第3点还是蛮好滴,我也经常这样做,不过正在尝试慢慢改变,学习在这种情况下寻求平衡的方法。

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

17 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT