您的位置:控制工程论坛网论坛 » 嵌入式系统 » 我对单元测试的实践与理解[1]

zlj

zlj   |   当前状态:离线

总积分:312  2024年可用积分:0

注册时间: 2007-04-02

最后登录时间: 2007-04-12

空间 发短消息加为好友

我对单元测试的实践与理解[1]

zlj  发表于 2007/4/15 22:45:35      1198 查看 6 回复  [上一主题]  [下一主题]

手机阅读

谈起单元测试的好处,每个人都能说得头头是道,但真正能将单元测试成功地应用于产品开发的过程中,却难之又难。我所呆的几个公司,以及我从朋友了解到的其它公司,都曾经尝试过采用单元测试来控制软件质量,但到目前为止,我还没有看到一个真正成功的样榜。

我自己在单元测试方面做过三次尝试,一次失败,一次半成功,一次比较成功。试着分析这几次尝试的成败得失的原因,也许能得出普遍而通用的结论。

案例一:

项目名称:

《某水电厂智能短信平台》

项目目标:

从电厂MIS系统的关系数据库中取得实时数据,加工后按照一定规则,通过手机向电厂相关人员发布与生产安全相关的短信。该项目是我到湖南某公司后,接手的一个半拉子项目。该项目已开发了半年多,到了初验收阶段,但用户在使用过程中发现短信系统很不稳定,并提出了许多功能改进意见。我的工作目标是:完善该系统,使之通过用户的验收。

工作过程:

我阅读了该系统的源码后,认为该系统的编码极不严谨,只考虑了常规用例路径,没有各种防误措施。选用的工业MODEM不稳定,经常出现处理异常、假死机、真死机等现象。

我工作的第一步,就更换了底层串口通讯构件,重构了MODEN收发软件模块,在此过程中引入了单元测试,对每一函数都进行了严格的单元测试。

这次引入单元测试是成功的,中途更换工业MODEM的厂家,需要重构短信解析层,因为有单元测试,很快便完成了收敛。该模块的质量也非常高,系统运行至今,底层通讯、短信处理等模块一直非常稳定。

但是,在远程管理平台这一层,我的尝试没有成功,主要原因是因为我对ASP.NET编程极不熟悉,对它的理解、改动非常吃力,更不用说为之增加单元测试模块了。

好在只有系统管理员关心远程管理平台,一般用户不关心这个功能。该项目最后验收通过了。验收之后,该系统也曾出现几次问题,但都是与上层模块有关。

经验:

1. C#开发平台上有一个很好的单元测试工具NUNIT,Visual studio 2003也很好地支持该工具,因此,引入单元测试在技术上没有困难;

2. 我对串口编程比较熟悉,对串口通讯中异常处理的重要性认识得比较深刻,因此,对引入方法以保证系统稳定性的迫切性比较高;

3. 我加入单元测试的几个模块都是底层的模块,这些模块与其它模块的交互性比较小,容易实现单元测试;

4. 单元测试的关键问题是如何将需测试的模块与其它模块隔离,这个系统中需要隔离的是重点是:将实际的串口通讯隔离,我采用了宏替代,并辅以一些模拟函数来模拟串口通讯过程,这个思路很好,实际上就是桩函数的思想;

5. 我对程序防误有一定的经验,因此在设计单元测试用例时比较有针对性;

6. 我在接手该系统前,正在看《单元测试之道 C#篇》,这本书从理论方面给了我很多帮助;

教训:

1. 我对ASP.NET编程极不熟悉,在自己不熟悉的领域也强行推动单元测试,最后的结果非常不理想;

2. 上层模块更需要处理好桩函数和隔离,这一点我经验不足;

3. 单元测试的工作量非常大,我最后放弃在上层模块推行单元测试,便是在项目交付与开发工作量之间权衡后取消的。

待续...

1楼 0 0 回复
  • zlj

    zlj   |   当前状态:离线

    总积分:312  2024年可用积分:0

    注册时间: 2007-04-02

    最后登录时间: 2007-04-12

    空间 发短消息加为好友

    zlj   发表于 2007/4/15 11:26:43

    案例二:


    项目名称:


    某公司《IMS开发平台》


    项目目标:


    IMS的全称为发电厂信息管理系统,IMS开发平台的目标是为信息管理系统提供一个基于.NET环境的二次开发工具,由它可以开发出管理系统的各个功能模块


    工作过程:


    该项目是我在湖南某公司的核心产品,我并未参与该产品的任何开发。只是在平台开发的后期,很多开发人员和使用者发现该平台不太稳定,同时由于项目周期延期等别的原因,惊动了公司高导,那时公司老总希望我能抓一下该产品的测试。


    因为有前一次单元测试的经验,我便想在该项目的测试中引入单元测试和自动化黑盒测试。当时我的思路时:先在一些主要模块上做一些单元测试的样版,在取得成效后再对开发人员内部推广测试方法。


    对该平台的单元测试工作陆续地做了一个月多,我完成了其中五个模块(文件)进行单元测试,但是,在做该工作的过程中,发现工作量实在太大,开发人员不可能接受这种代码质量控制方式。


    刚好,那时手上接了一个新的项目(即我下面要讲的案例三),该工作便不了了之。


    经验:



    教训:


    1. 在项目后期再投入单元测试,几乎是不可能的;


    待续...

    2楼 回复本楼

    引用 zlj 2007/4/15 11:26:43 发表于2楼的内容

  • zlj

    zlj   |   当前状态:离线

    总积分:312  2024年可用积分:0

    注册时间: 2007-04-02

    最后登录时间: 2007-04-12

    空间 发短消息加为好友

    zlj   发表于 2007/4/15 11:27:31

    案例三:


    项目名称:


    《某水电厂AGC/AVC改造项目》


    项目目标:


    AGC为“自动发电控制”的英文简称,AVC为“自动电压控制”的英文简称。


    某水电厂为6台灯泡贯流式机组,单机容量45MW,总装机容量为270MW,机组监控系统选用某国外知名厂家的产品,由某国内知名厂家实施。


    该监控系统未提供AGC/AVC模块,而实施厂家提供的AGC/AVC模块在稳定性、速度等方面不能满足用户的要求。于是用户重新招标,改造AGC/AVC。


    工作过程:


    作为已发电电站,电厂不允许对电组进行各种工况的的实际试验,比如水位为下限值、机组故障时AGC的动作情况等,即便可以进行某些试验,也不可能长时间进行。


    该项目在UNIX下使用C语言开发,在开发过程中引入了单元测试,系统级模拟测试平台、系统运行日志记录。单元测试完全自动化进行,系统级模拟测试平台则由测试人员手工进行。最后的结果是:编码量2万行。单元测试代码量3万多行,系统模拟测试平台代码量1万行。其中单元测试没有采用专用的工具,直接用C语言写框架和测试用例,单元测试用例超过1200个。


    应该说,单元测试对该项目稳定运行起了非常大的作用,系统投运后,只发现一个程序BUG(通过系统运行日志记录很快就找到原因了)。



    经验:


    1. 该项目是我引入单元测试最成功的项目;


    2. 特殊的安全及应用要求,逼迫我们寻找良好的软件质量控制办法,在单元测试的过程中,曾多次犹豫,但考虑安全性问题,最后终于坚持下来了。机组因为AGC/AVC而出事故,我是吃不了兜着走;


    3. 没有界面功能(界面由监控系统的组态系统完成),系统规模不大,2万行的系统应该说只是一个中小型的系统,这为单元测试提供了实现基础;


    4. 良好的模块设计,使得程序的可测性非常高;


    5. 整个项目只由我一人开发,只配了两个测试人员(一个是公司的,一个是电厂的),这两个人员非常敬业,沟通成本很低;


    教训:


    1. 没有使用测试工具和框架,项目后期发现,维护测试工程比维护工程本身的难度还要大;


    2. 因为设计调整的原因,至少有1/3的用例是白做了。


    待续...

    3楼 回复本楼

    引用 zlj 2007/4/15 11:27:31 发表于3楼的内容

  • zlj

    zlj   |   当前状态:离线

    总积分:312  2024年可用积分:0

    注册时间: 2007-04-02

    最后登录时间: 2007-04-12

    空间 发短消息加为好友

    zlj   发表于 2007/4/15 11:28:15

    1、单元测试是谁的职责?
     单元测试可以由开发人员来做,也可以由测试人员来做,两者各有利弊,就本人观点,单元测试是开发人员的职责,原因如下:
     A、国内大部分软件企业,都没有比较规范的项目管理和开发流程;
     B、公司由于各种压力,不能配置足够多的具备开发能力的测试人员,不会为测试投入足够多的资源;
     C、公司不会为测试人员开出与开发人员相同的工资,即便有,也不会招来同样数量同样层次的测试人员;
     D、具有较强编码能力又愿意专职从事测试的人员少之又少,非常难招;
     E、开发人员在将代码或模块移交给测试人员之前,已经或多或少地通过各种方法对代码进行了测试,这些工作其实就是单元测试,如果将该工作变成可提交的成果,工作量并不会增加非常多;

    2、单元测试在何时进行?
     按照极限编程的思想,单元测试应在编码之前进行,即以测试驱动开发。还有一种思路,即在每个模块完成后进入单元测试。本人观点,单元测试应该在每个模块完成后进行,原因如下:
     A、极限编程在中小型项目中,或者在需求非常明确的项目中,可以发挥很大的作用。但是,在大型项目开发中,或者在项目需求很模糊的情况下,极限编程很可能导致开发工作量大,需求不能收敛,项目发散和失败的危险;
     B、极限编程强调项目管理经验,对于未有极限编程的实践经验,贸然引入极限编程,很可能控制不了开发进度;
     C、对单元测试工程的管理难度与项目工程的管理难度相比,在大型项目中应该差不多,在项目后期,对单元测试的工程管理会非常麻烦,如果以单元测试工程为主线进行项目管理,难度太大;
     D、程序员编完代码后进行测试是一件很自然的事情,管理起来相对容易;


    3、单元测试应该选用何种工具?
     现在单元测试工作非常多,对C/C++语言而言,可选的不下十多种,国内几个厂家的广告打得尤其响,但比较这些测试工具后,我还是推荐CPPUNIT,原因在本章不展开描述。


    4、关于单元测试的一些注意事项
     A、单元测试不只是工具的使用,是一种编程思路的转变,在项目管理、开发流程方面,都要同时考虑;
     B、单元测试能很好开展的前提是,在设计过程中,尽量将模块设计得藕合性松,即强调编写可测的代码。关于编写可测的代码,有很多思路、理论;
     C、单元测试考验项目主管的决心,在刚开始时,单元测试的工作量比较具大,很多项目在尝试一段时间后,由于项目主管的决心不够,对单元测试的工作不再放在主要位置上,项目成员便会不自觉地放弃该工作;
     D、对单元测试的工作量要有比较清醒地认识,要为单元测试留出足够多的时间;
     E、对单元测试的工程管理要放在一个非常重要的位置,项目开始时,如果不对单元测试的工程进行管理,后期的维护很可能失控,导致单元测试半途而废;


    (待续...)

    4楼 回复本楼

    引用 zlj 2007/4/15 11:28:15 发表于4楼的内容

  • zlj

    zlj   |   当前状态:离线

    总积分:312  2024年可用积分:0

    注册时间: 2007-04-02

    最后登录时间: 2007-04-12

    空间 发短消息加为好友

    zlj   发表于 2007/4/15 11:29:10

    先说一些题外话。


    记得当初在湖南某公司工作时,经常由于用户提出新的要求,而对程序进行改动,而每次改动后,程序的稳定性都要经过相当常一段时间,才能稳定下来。于是有一位湖南大学的教授就评说了:问题的关键是在程序设计前,没有进行充分的需求调研,开发过程不符合软件工程思想。


    公司老总在旁边连连点头。


    事实上,那位教授是自动化专业的教授,年纪也比较大,并没有软件开发的经验。


    在软件行业,有这样一个特点,那些并没有经验的人,也可以就软件开发的过程进行的许多问题进行点评,点评的内容也象模象样。


    典型的点评是这样的:


    开发周期没控制住,是因为需求工作未做好,需求经常变动,导致开发时间经常延期。


    软件的质量不高,程序在现场经常出现BUG,是因为测试未做好。


    程序员之间的沟通不畅,是因为大家没有统一使用UML和VSS。


    测试工作的工作量过大,每次都需要重复进行,是因为没有引入单元测试和自动化测试。


    等等,不一而足。


    问题是:既然非专业人士都能说得头头是道,难道程序的设计人员和开发人员不懂这些道理?


    对单元测试的点评也是这样,在项目质量经常出问题的情况下,公司老总第一反应是:测试没做好,应该在源码级就进行单元测试,一块一块地控制程序质量。但真正在执行的过程中,又发现这样那样的问题。


    那么,出现这些问题真正原因,到底是什么呢?


    归纳一下,有如下几点:


    1、软件开发是一项系统工程,一项比刚开始想象更复杂的工程,需要系统工程的理论支持和工具支持,而计算机技术发展时间较短,并没有建立一套行之有效的理论和有用的工具(现在这方面的东西多起来了)。


    2、国内的计算机教学体系,教出了一大堆只将计算机软件开发看作是技术应用的学生。没有教会学生如何系统思考问题的能力。培养出一大堆将偏执当个性、思维简单的计算机开发人员。


    3、舆论将裘、简、鲍、盖等人的早期行为作为津津乐道的榜样和典型来宣传,并在潜移默化中鼓励程序员将挑灯夜战、独行单为、内向专执等作为计算机开发人员的品德标牌,造成了一代有缺陷的程序员。


    4、公司的决策者在公司启动时,或项目的前期,尝到了单个程序员带来的甜头,便认为程序开发应该就应该是这样,出问题只是个别的,很快就能找到办法。


    扯远了,再回到单元测试。


    在与朋友交流中,发现对单元测试的理解,有以下几方面的误解:


    1、在项目开发中,只要引进了单元测试,项目的成功便有了保证。


    2、单元测试太简单,工具太弱智,单元测试工作非常容易,不应该由开发人员来做。


    3、只有复杂逻辑的程序模块才需要单元测试,分支少的程序模块不需要单元测试。


    4、单元测试太费时,在项目工期紧时,就不应该进行单元测试。


    5、对所有程序的测试,都需要进行单元测试。


    6、单元测试只应该对那些基本底层模块进行测试,对上层应用模块的测试,不需要进行单元测试。


    还要工作,先将问题列在这儿,有时间继续......

    5楼 回复本楼

    引用 zlj 2007/4/15 11:29:10 发表于5楼的内容

  • zlj

    zlj   |   当前状态:离线

    总积分:312  2024年可用积分:0

    注册时间: 2007-04-02

    最后登录时间: 2007-04-12

    空间 发短消息加为好友

    zlj   发表于 2007/4/15 11:29:56

    单 元 测 试 之 感 想
                           ———XX
    上周完成了XXXX系统MODEM与串口通信部分几个接口的测试,现结合该平台中的发送短消息模块,谈谈我在第一次编写测试程序的过程中对以下两个方面的总结——测试的目的、测试的技巧及方法,希望能对初学者有所帮助。
    那么,首先简要的介绍一下发送短消息模块的处理流程:通过计算机,把发送短消息命令(包括接受方手机号码,短消息内容)发送到与串口相连的MODEM,MODEM接受到该命令后,自动完成对短消息的发送。
    “软件测试”的目的简要的说就是发现错误、纠正错误,即保证在任何条件下,我们的被验证代码都能达到预期设计的目标。不能否认,采用新的语言、先进的开发方式、完善的开发过程都可以减少错误的发生,但是,要真正实现软件的零BUG,我们只能借助于软件测试,找出存在的每一个BUG然后对其进行处理,测试是软件质量的保证,所以我们要认真的对待,切不可马虎行事。
    进行测试时,第一,要了解被测试函数的功能以及其处理流程,否则测试将会是无稽之谈,即使编写了测试程序,对于代码是否按照预期的方式运行也会全然不知。第二,程序员在编写程序时,是由外到内,或是由内到外一层套一层来实现其功能的,所以测试时,只需对外部提供的接口进行测试。
    测试的技巧与方法有很多,在MODEM与串口通信部分几个接口测试中,用到的几种测试如下所示,我想这几种方式在整个软件测试中都比较常用:
     边界测试。如发送短消息时,有以下几种边界形式,用户可能发空字符;可能发的字符数很多,也可能很少;那么遇到此种情况时我们就可以采用此法测试。
     非法测试。如发送短消息时,用户有发全英文,全中文,中英文,特殊字符等情况;遇到这种情形时我们又可采用这种测试法。
     使用替换。如在发送短消息时,基于效率与资源因素下,我们不可能将每条命令都写入MODEM,所以我们就模拟MODEM发送短消息,以此来方便完成整个测试;
     当增加某一个功能模块时,需保证以前的测试都能通过;
     当重用测试时,可能忘记在原有代码上修改或修改不全面,而造成的错误;
     进行测试时,测试员不要带有任何的感情色彩,不要怀疑或是找借口否认只出现过一次的BUG;
    总之,世上无难事,只要肯登攀。作为一名软件测试员,我们只要在测试过程中,不断的探索和积累经验,找出适合自己独特的测试方式,并在熟练掌握一些测试方法和技巧的同时,多注重自身素质的培养,这样就可以使我们的测试水平不断地得以提升,成为真正意义上合格的软件测试员。

    单元测试系列的后续文章还有3篇,敬请期待

    6楼 回复本楼

    引用 zlj 2007/4/15 11:29:56 发表于6楼的内容

  • 瑞雪照丰年

    瑞雪照丰年   |   当前状态:在线

    总积分:4510  2024年可用积分:0

    注册时间: 2007-02-01

    最后登录时间: 2016-01-14

    空间 发短消息加为好友

    瑞雪照丰年   发表于 2007/4/15 22:45:35

     


    单元测试指什么部分?

    7楼 回复本楼

    引用 瑞雪照丰年 2007/4/15 22:45:35 发表于7楼的内容

总共 , 当前 /