`
wuhua
  • 浏览: 2110472 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

单元测试总篇与TTD实践

阅读更多
        经过前几篇的测试学习跟实践,我觉得有必要对这次学习做个总结。其实上面的话只是幌子,主要原因还是javaeye的
lighter 写道
貌似这一篇文章要放在"agile"版块更好一些吧.
btw:wuhua同学写文章有时候可以把两篇结合成一篇,可能会更好一些,不然让别人看一篇文章要看一,二,三,四才能看完.个人建议而已,别见怪.

觉得他说的很对,当时是出于篇幅过程,怕javaeye blog不支持大篇幅的文章,所以拆开。不过我觉得我这个担心是多余的。这里说句题外话,我用过很多Blog,但觉得这里是最好的。速度快,写文章贴心(主要是对源代码格式化方面做的很出色)。

好了,进入正题。
先介绍下我以前写的那些文章先,让大家对这篇文章有个初步的认识。
单元测试之测试目的,
单元测试之实践一,关于设计的常见分层
单元测试之实践二,关于DAO的测试
单元测试之实践三 Service的测试
单元测试之实践四 Action的测试

以前我正常的设计流程是Database->Model -> Dao-> Service -> Action ->View。这样的设计伴随我1年多了,这样的设计方式好吗?这样的设计高效吗? 代码质量能保证吗? 我可以很肯定的回答,不能,如果数据库一该,我要在表格里面添加一个字段,或者什么的。那么它将会牵连到很多其他,修改的动作如下:Database->Model -> Dao-> Service -> Action ->View。 噢,my got,几乎跟设计的一样多,甚至更多,因为在修改的过程中你就算有再好IDE去重构它也不能保证它的正确性。然后你就要去测试,测试它的正确性。也许测试的过程将是修改过程的几倍时间。所以我个人觉得这样的设计方式是不高效的。总而言之就是这样的设计迟早会出问题的?

为什么会这样呢?难道就没有一种解决办法吗? 经过这段日子学习我发现,以前的设计不能很好的保证质量是因为你没有足够的单元测试去支撑着它,所以你改了代码后缺乏一个很好的手段去保持这段代码的质量,换句话的意思就是,没有一个静态的人去监督你的工作(我把单元测试比喻为静态的人,它只做一件事,就是督促你的代码不出问题)。

好了。我们已经找到了适合保证我们代码质量的方法了。但是我们还得提高我们的开发效率啊。这又怎么办呢?是不是还按照以前的方式吗?我想自己浑浑噩噩的活了20多年了。我想换种活法了,想找种更刺激,更有意义的生活方式。
设计有时候更生活是一样的,应该经常探索,经常实践才能感受的更多。
那好吧我们就来个彻底的变革吧。怎么变呢? 很明显:那就是TDD。
该怎么做呢?
以前的方式:Database->Model -> Dao-> Service -> Action ->View。
TDD的方式:Test->其他。
先看看下面Dao的例子吧:以前的方式:IBaseDao ->  BaseDao -> BaseDaoTest。
TDD:BaseDaoTest->IBaseDao->BaseDao.
 
  1. public void testFindAccountByName(){  
  2.     Account a = new Account("wuhua");      
  3.     ht.find("from Account as a where a.name=?", a.getName());  
  4.     List l = new ArrayList();  
  5.     l.add(a);  
  6.     control.setReturnValue(l);  
  7.     control.replay();  
  8.     Account result =  accountDao.findAccounByName(a.getName());  
  9.     Assert.assertEquals(a.getId(),result.getId());  
  10.     Assert.assertEquals(a, result);  
  11.     control.verify();  
  12.       
  13. }  
好,非常好,怎么这段代码不能运行呢?当然不行了,因为上面的很多类都没有。那我们这段代码的用途是什么呢?
用途就是:以为上面的从上面的代码我很清楚自己以后要做什么。1,要建立一个Model,里面起码有一个name属性,然后你会发现我们要测试的功能段是accountDao.findAccounByName(a.getName()); 里面我们要求测试的SQL是from Account as a where a.name=?,意图明确吧。好,

我们写下实际代码吧。
java 代码
  1. public Account findAccounByName(String name) {  
  2.         List l = this.getHibernateTemplate().find("from Account as ", name);  
  3.         if(l != null && l.size() >=1)  
  4.             return (Account) l.get(0);  
  5.         else   
  6.             return null;  
  7.     }  
好,代码写好了。去运行我们的测试吧。结果是令人失望的。怎么会是红色的呢。肯定是逻辑代码出问题了(如果测试代码没问题的话)。经过检查发现原来
from Account as a where a.name=?跟from Account as 完全两码事。好改回去

java 代码
 
  1. public Account findAccounByName(String name) {  
  2.         List l = this.getHibernateTemplate().
  3.                              find("from Account as a where a.name=?", name);  
  4.         if(l != null && l.size() >=2)  
  5.             return (Account) l.get(0);  
  6.         else   
  7.             return null;  
  8.     } 
怎么还是红色啊。我不干了(程序员暴躁的情绪出来了,我就经常这样)主管跟我说:“再查查吧。别灰心。”
后来查了半天发现原来
java 代码
 
  1. List l = new ArrayList();    
  2.  l.add(a);   
我只renturn一个预期的对象a
java 代码
 
  1. if(l != null && l.size() >=2)  
  2.             return (Account) l.get(0);  
  3.         else   
  4.             return null;  
而代码却要求我要传入预期两个对象才给我通过,所以代码只return null。

最后改了这段代码
java 代码
 
  1. public Account findAccounByName(String name) {  
  2.         List l = this.getHibernateTemplate().find("from Account
  3.                                         as a where a.name=?", name);  
  4.         if(l != null && l.size() >=1)  
  5.             return (Account) l.get(0);  
  6.         else   
  7.             return null;  
  8.     }  

终于通过了。绿色,绿色,我看到了。我对主管说。主管笑了。我也笑了

最后我郁闷下,写这篇文章足足话了我22个小时,
第一次写好了。杀毒突然重启。所以全没了。
第二次,提交不了。然后忘记备份,又全没了
第三次成功了。过程跟TDD差不多。



分享到:
评论
17 楼 yimlin 2007-08-29  
yiding_he 写道
楼主先把标题改一下吧,写错了。

另外,“Database->Model -> Dao-> Service -> Action ->View”的方式完全是搞反了,不符依赖倒置原则。我就是从页面开始写起,然后写 Action 和业务逻辑。


这个依赖导致原则不是这么用的吧!我的经验是:先设计Model,接着Service,然后才是Web层。我接触的项目看,Web层是一个集成模块,一个页面有可能访问到多个模块组件的数据。

16 楼 hlxiong 2007-08-29  
楼上的兄弟,LZ没有搞反。
从前台开始或是从后台开始,并没有绝对的要求,换言之,实际编码时两种方式都可以的。
比如,开发时leader可能会将前后台编码分开,有人专写后台,即service等业务逻辑处理;而有人专写前台,即页面、Action等。总不能要求每个人都View--Action--Service。。。。。吧?
而且,基本的model层对象发须先存在吧?我们都是把库建好然后自动生成pojo,dao....。
15 楼 yiding_he 2007-08-29  
楼主先把标题改一下吧,写错了。

另外,“Database->Model -> Dao-> Service -> Action ->View”的方式完全是搞反了,不符依赖倒置原则。我就是从页面开始写起,然后写 Action 和业务逻辑。
14 楼 topcloud 2007-08-28  
我现在主要集中在测试Service和DAO
做法是:
1.Service或DAO的接口(确定他们的行为)。
2.编写测试类。
3.编写实现类,填写处理代码。
4.测试---修改实现---测试
5.提交完了
13 楼 wuhua 2006-12-15  
意义就是测试你代码是否正确执行。
对啊写测试的时候差不多你写完测试,就想好了代码怎么实现。
只是用测试去驱动而已
12 楼 lewisou 2006-12-14  
这有什么意义啊?您写测试的时候已经想好怎么实现拉?
11 楼 wuhua 2006-12-14  
这段代码是主要测试:
from Account as a where a.name=?语句是否正确。
10 楼 lewisou 2006-12-14  
楼主第一段代码的

引用
ht.find("from Account as a where a.name=?", a.getName()); 

是干嘛用的?
9 楼 lighter 2006-12-14  
抛出异常的爱 写道
wuhua 写道
TDD最大的好处可能就是保证代码的质量,对于提高效率,我觉得没什么。
个人觉得开发效率最高的应该是asp了,因为存在大量的项目,对于一些简单的项目而已,只需修改下就ok了。
比如客户想要个商城,开始我并不认为全部重新开发是好的。虽然全部自己开发可以更好的控制质量,但是在效率方面还是上网找下,看看有没有适合客户需要的。如果有就在原来的基础上修改就OK了。

尽情利用网上资源估计是不错的选择。

作企业应用时....提心掉胆的用开源的代码
改来改去....最后疯掉...

一般情况,都不会大去升级开源的lib包,稳定才是最重要的,除非确定升级lib和版本能带来莫大的好处和方便...
8 楼 抛出异常的爱 2006-12-14  
wuhua 写道
TDD最大的好处可能就是保证代码的质量,对于提高效率,我觉得没什么。
个人觉得开发效率最高的应该是asp了,因为存在大量的项目,对于一些简单的项目而已,只需修改下就ok了。
比如客户想要个商城,开始我并不认为全部重新开发是好的。虽然全部自己开发可以更好的控制质量,但是在效率方面还是上网找下,看看有没有适合客户需要的。如果有就在原来的基础上修改就OK了。

尽情利用网上资源估计是不错的选择。

作企业应用时....提心掉胆的用开源的代码
改来改去....最后疯掉...
7 楼 wuhua 2006-12-14  
TDD最大的好处可能就是保证代码的质量,对于提高效率,我觉得没什么。
个人觉得开发效率最高的应该是asp了,因为存在大量的项目,对于一些简单的项目而已,只需修改下就ok了。
比如客户想要个商城,开始我并不认为全部重新开发是好的。虽然全部自己开发可以更好的控制质量,但是在效率方面还是上网找下,看看有没有适合客户需要的。如果有就在原来的基础上修改就OK了。

尽情利用网上资源估计是不错的选择。
6 楼 lighter 2006-12-14  
wuhua 写道
lighter 写道
"Assert.assertEquals(a.getId(),result.getId()); 
Assert.assertEquals(a, result);"
应当力保每个测试只有一个断言;在比较理想的状况下,setUp()构建预设环境,而每个测试针对这个预设环境只发出一个断言.


建议不错。在保证每个测试只有一个断言的条件下,必然会压迫代码更简单,逻辑更单一。
但有时候这并不现实

有时候真的不太现实,在一个测试出现多个断言情况或感觉测试有一些code smells的时候,我一般就会想到了重构,重构的时候只关心要重构的东西,而不添加新功能
5 楼 wuhua 2006-12-14  
lighter 写道
"Assert.assertEquals(a.getId(),result.getId()); 
Assert.assertEquals(a, result);"
应当力保每个测试只有一个断言;在比较理想的状况下,setUp()构建预设环境,而每个测试针对这个预设环境只发出一个断言.


建议不错。在保证每个测试只有一个断言的条件下,必然会压迫代码更简单,逻辑更单一。
但有时候这并不现实
4 楼 lighter 2006-12-14  
"Assert.assertEquals(a.getId(),result.getId()); 
Assert.assertEquals(a, result);"
应当力保每个测试只有一个断言;在比较理想的状况下,setUp()构建预设环境,而每个测试针对这个预设环境只发出一个断言.
3 楼 温柔一刀 2006-12-14  
步伐的大小是随着感觉来的
感觉好就大步前进,否则小步前进
呵呵
做到收发自如就好了
2 楼 wuhua 2006-12-14  
觉得有道路,估计看的人会比较辛苦。
1 楼 抛出异常的爱 2006-12-14  
跨度太大...
要一小步一小步的走
绿的次数太少了...

相关推荐

    测试驱动开发(TTD)

    测试驱动开发(Test-Driven Development,简称TTD)是一种软件开发方法,强调在编写实际代码之前,先编写单元测试。这种做法将测试作为设计的一部分,促进了更好的代码结构和更高的代码质量。测试驱动开发的核心理念...

    测试驱动开发的宝典-TTD

    ### 测试驱动开发的宝典—TTD #### 概述 测试驱动开发(Test-Driven Development,简称TDD)是一种软件开发方法论,强调在编写功能代码之前先编写测试用例。这种方法有助于确保代码质量,提高开发效率,并增强团队...

    软件测试《测试指南》

    关于软件测试的东西 关于软件测试的东西 关于软件测试的东西 关于软件测试的东西 关于软件测试的东西 关于软件测试的东西 关于软件测试的东西 关于软件测试的东西 关于软件测试的东西 关于软件测试的东西 关于软件...

    TTD

    8. **单元测试**:为了确保TTD功能的正确性,编写单元测试至关重要,Python的`unittest`或`pytest`框架可以帮助完成这项工作。 9. **文档**:良好的项目应该有清晰的文档,解释如何使用TTD功能,以及相关的API接口...

    TTD:学习测试驱动开发

    测试驱动开发(Test-Driven Development,简称TDD)是一种软件开发方法,强调在编写实际代码之前先编写单元测试。在TDD中,开发者遵循“红-绿-重构”原则,即首先编写失败的测试(红),然后编写刚好能让测试通过的...

    硝烟中的敏捷和xp 及 驱动测试设计

    驱动测试设计(TTD)是XP的关键实践之一,它要求开发者首先编写失败的单元测试,然后编写最小量的代码使测试通过。这种方法有助于确保代码的正确性,同时也促进了更好的设计。因为测试先行,开发者必须思考如何设计...

    ttd_134033.apk

    ttd_134033.apk

    ttd.zip_codeigniter_html

    【标题】"ttd.zip_codeigniter_html" 指的是一款基于CodeIgniter框架和HTML构建的项目,其中包含了网站的基本结构和功能。CodeIgniter是一个轻量级且高效的PHP框架,它提供了丰富的工具来简化Web应用的开发,特别...

    TDD测试驱动开发PDF及源码.zip

    TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法的核心实践,但不只适用于XP(Extreme Programming),同样可以适用于其他开发方法和过程。

    matlab论文《近场波束形成的ttd配置——并行、串行或混合》的代码.zip

    在本压缩包中,我们关注的是一个与MATLAB相关的研究论文,标题为“近场波束形成的TDD配置——并行、串行或混合”。这个主题涵盖了无线通信领域中的一个重要技术,即近场波束形成,它利用时间延迟器(Time-Delay ...

    创新安全架构、实现有效安全的最佳实践.pdf

    2017主要网络安全威胁分析 企业提高安全性面临的最大障碍 在这场攻防较量中。。。 如何去更好地做出安全考虑 思科SAFE安全设计 Step1:安全能力设计 专业安全评估提炼安全需求 ...我们的目标:不断缩短 TTD

    grow object oriented software guided by tests 英文pdf和epub合集

    2. **单元测试**:阐述了编写有效单元测试的重要性,以及如何编写能够覆盖核心业务逻辑的测试用例。 3. **模拟对象(Mocks)与桩对象(Stubs)**:介绍了如何使用这些工具来隔离被测试代码,确保测试的独立性和准确...

    String-Calculator:T-303中TTD练习的存储库

    - **单元测试**:使用JUnit或其他测试框架编写测试用例,覆盖各种输入情况,包括边界条件和异常情况。 在项目中,你可能会看到以下文件: - `StringCalculator.java`:这是主要的实现类,包含`addNumbers`方法和...

    react-native-ttd-gvr:在iOS和Android上React本机360 GVR

    react-native-ttd-gvr入门$ npm install react-native-ttd-gvr --save 大多是自动安装$ react-native link react-native-ttd-gvr 手动安装的iOS 在XCode的项目导航器中,右键单击“ Libraries ➜ Add Files to [your...

    近场波束形成的TTD配置:并行、串行或混合matlab代码.zip

    1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程...

    TTD-CI

    #你好 是一个免费的Material Bootstrap Admin,其灵感来自Google的Material Design,其设计新颖新颖。 我们很高兴通过易于使用且美观的组件来介绍我们对材料概念的看法。 Material Dashboard是基于流行的Bootstrap...

    Công Cụ Đặt Hàng Của TTD Logistics-crx插件

    语言:Tiếng Việt ttd Logistics提供在1288,Tmall,Taobao等电子商务网站上在线协助您的工具。 TTD的在线订购支持工具物流Chrome浏览器&Chrome Flag +是一个支持...图4:推车以与订单工具一起用于篮子后的产品。

    test_driven_hello_word_nodejs:根据 TTD,Node.js 中的 Hello World

    在本文中,我们将深入探讨如何在Node.js环境中实践测试驱动开发(Test-Driven Development, TDD)来构建一个简单的"Hello, World"程序。TDD是一种软件开发方法论,强调编写测试先于编写实际的代码,确保代码的质量和...

    TTD --- Projeto-PI3:Um迷游戏机Genshin Impact feito pela equipe 3 do 3D na materia de PI3

    总的来说,《TTD --- Projeto-PI3》是3D课程团队对原神游戏热爱的体现,它融合了3D建模、游戏设计、编程和项目管理等多个IT领域的知识,展现了学生们在实践中的创新能力和技术实力。通过这样的项目,他们不仅锻炼了...

Global site tag (gtag.js) - Google Analytics