“天街小雨润如酥,草色遥看近却无。最是一年春好处,绝胜烟柳满皇都。”读一首古诗,心情也随之平静下来

发布新日志

  • 软件测试的重要原则

    2007-06-20 10:51:16Top 1 Digest 1

    Glenford J. Myers编著的《软件测试的艺术》一书中提到软件测试中大多说重要的问题都是心理学问题,并且归纳出了一系列重要的测试指导原则,下面我将他抄录下来,供大家分享。

    1、 测试用例中一个必需部分是对预期输出或结果进行定义。

    2、 程序员应当避免测试自己编写的程序。

    3、 编写软件的组织不应当测试自己编写的软件。

    4、 应当彻底检查每个测试的执行结果。

    5、 测试用例的编写不仅应当根据有效的或预料到的输入情况,而且也应

        该根据无效的或未预料到的输入情况。

    6、 检查程序是否“未做起应该做的”仅是测试的一半,测试的另一半是

        检查程序是否“做了其不应该做的”。

    7、 应避免测试用例用后即弃,除非软件本身就是一个一次性的软件。

    8、 计划测试工作时不应该默许假定不会发生错误。

    9、 程序某部分存在更多错误的可能性,与该部分已发现错误的数量成正

        比。

    10、 软件测试是一项极富创造性、极具智力挑战性的工作。

     

  • Selenium的演变过程

    2013-10-14 16:56:34

    本文依据selenium 官方文档,结合自己的理解完成,可能存在不尽准确的地方,各位看官请多多指教。

    2004年,Jason Huggins 在ThoughtWorks测试一个内部应用,作为一个有头脑的人,他不能局限于将有限的生命投入到无限的手工测试中去,他必须去改变这种现状,遇上他就开发了一套Javascript. library,在多个浏览器上自动运行test cases,这个Javascript. library最终变成了 selenium score,实现了Selenium Remote Control (RC) and Selenium IDE的基础功能。

    虽然selenium是一款强大的自动化工具,但是他也是有一定缺陷的,他的javascript是基于自动引擎和具有一定安全限制的浏览器上运行。更糟糕的是,webapps变得越来越强大,并且会越来越多的使用浏览器提供的一些特有特性。selenium的局限性越来越明显。

    | |

    | |

    | |

    2006年,Google一个非常勇敢的工程师Simon Stewart开始一个被叫做WebDriver的工程。Google已经使用Selenium很长时间了,但是测试人员不得不使用有局限性的产品。Simon想到了一款测试工具能够直接使用‘本土’的方法为浏览器和操作系统,以此规避这个Javascript环境带来的沙盒限制。WebDriver工程就为了这个目标而开始。

    | |

    | |

    | |

    2008年,北京奥林匹克运动会标志着中国已经达到了一个全球化的高度。这一年最重要的事情就是Selenium and WebDriver的归并。Selenium 已经有大量用户的支持,但是WebDriver才是这个工具真正的未来,两个工具的合并给用户提供了统一的特性,并且带来更多新的亮点,成功绕开了javascript. sandbox问题。

    Selenium 2 (aka. Selenium Webdriver)

    Selenium 1 (aka. Selenium RC or Remote Control)

    http://docs.seleniumhq.org/docs/01_introducing_selenium.jsp

  • 关于测试用例的探讨(讨论稿)

    2010-06-22 14:31:10

    测试用例是测试过程中不可或缺的部分,如何形成一种合理的工作流程,设计出高效的测试用例,用例应该遵循什么样的书写规范,这是对整个项目质量提高的一种保证,也是对我们测试人员自身用例设计能力的一种提高。本文初步整理了一些测试用例的设计规范,希望能够抛砖引玉,多多收获大家的意见或建议。

    测试用例的六大特性

    1. 测试用例对需求覆盖的完整性

    测试是基于需求的,所以说测试用例应该尽可能100%的覆盖需求。100%的覆盖跟0缺陷的要求有些类似了,实现起来是非常非常困难的,但是我们应该做到尽可能的去覆盖,至少显性的需求必须保证有用例覆盖,隐性的需求可允许有一定遗漏,一旦发现遗漏后需要及时的对测试用例进行补充。

     

    2. 测试用例的有效性

    如何定义用例的有效性,什么是有效的用例,个人认为可归结为两类,一类是能发现问题,特别是严重问题,甚至是致命问题的用例,这类用例可以称之为高效用例,另一类是覆盖了需求所要求功能的用例,这类用例不一定能发现问题,但是必不可少的。

     

    3. 测试用例的易理解性

    测试用例应该是易于理解的,主要表现在语言组织方面,不使用生涩词汇,不让人产生歧义。目前我们期望的最理想的状态就是,任何一个用户,在不熟悉系统,不了解需求的情况下,拿到这个用例就可以根据步骤一步一步执行。

     

    4. 测试用例的清晰性

    测试用例的清晰性包括测试用例分类明确、设计思路清晰、操作步骤简洁明了等等。

     

    5. 测试用例的可复用性和可维护性

    之所以花很大的代价去设计测试用例就是为了能够重复使用,但是用例又不可能是一成不变的,随着产品的升级或需求的变化,用例也需要做相应的维护,如果用例设计的比较混乱,维护成本就会非常高。如何降低维护成本,提高用例的可维护性,最重要的就是需要我们设计用例时能遵循统一的规范,这样不论将来谁来维护,都可以比较容易的去进行。这一点也避免了人员流动后造成用例无法重用的尴尬局面。

     

    测试用例的生命周期

    测试用例从开始规划到设计完成直至被执行是需要一个过程的,在这里我称之为测试用例的生命周期,其实最主要的还是一个流程问题。

     

    1. 版本确定下来,需求完成并收到评审邮件时,就分配专门的测试人员熟悉需求并为用例设计做准备

     

    2. 根据产品需求或开发需求提取测试需求点,保证测试用例对需求的覆盖

    在我们开始接触需求并了解需求的时候,就可以适当的提取出测试需求点,这个需求点可以是非常详细的,也可以是比较粗略的,可以是一个测试需求对应一个测试用例,也可以是一个需求对应多个测试用例,用例设计的时候再对测试需求进行分解。

    提取测试需求的目的有二,一是帮助测试人员更快更好的理解需求,把问题发现在需求阶段,降低整个项目成本。二是对用例设计起到一定的指导作用。

    测试需求提取后记录到QC的{需求}模块中,还是记录到Excel中,这个大家可以讨论。

      

    3. 需求评审后及时对测试需求进行调整

        需求评审后,肯定会或多或少的有些变动,这个时候需要对变更后的测试需求及时做调整。此类情况是针对产品需求进行的测试需求提取,如果针对开发需求,变化的可能性会小一些。

    4. 根据测试需求设计测试用例,并且测试用例要覆盖到每个测试需求

        可直接在QC中覆盖

    5. 用例完成后提前1-2天发给相关人员阅读并发评审通知

    6. 用例评审结束后,需要对有问题的用例及时调整,调整后的用例可单独导出来,邮件给所有相关评审人员再次确认

    7. 将用例拖入执行计划,准备用例执行,执行可分两种情况,自己设计自己执行,或者交换执行,对于有条件的项目最好是交换执行。

    可直接在QC中进行

    用例执行过程中,如发现BUG,请及时将BUG ID更新到相应的用例中

    8. 执行过程中发现用例遗漏,需及时补充,如无遗漏,用例执行通过,整个生命周期结束。

     

    测试用例设计规范

    测试用例的组织结构

    测试用例首先需要清晰的表达出我们的测试思路,拿到一个需求后,应该先测什么,再测试什么,最后测试什么。

     

    如何保证测试用例的清晰性,可以先从测试用例的组织结构入手,结合之前用例设计思路,加上在网上参考的一些资料,目前测试用例可分以下几类进行设计,这几个分类在QC中表现形式为5个文件夹。

     

    功能

    该文件夹中主要包含一些的功能性的用例,可以包含正常流或异常流,以登录为列:

    正常流:用户名和密码正确,登录成功

    异常流:用户名和密码均为空,登录失败

            用户名或密码有一个为空,登录失败

                  ……

    业务逻辑与规则

        该文件夹主要包含一些业务逻辑和规则,跟具体的业务相关的用例,比如说系统允许用户名50个字符以内,采用及时校验机制。用例设计为:

       用户名正好为50个字符,离开焦点,验证通过

    用户名为中文,离开焦点,验证失败

    ……

    接口

        该文件夹主要包含一些接口相关的用例,特别是遇到系统间相互调用、模块间相互调用,与数据库的接口。比如说领动与OSS订单的接口,爱聘才与OSS编辑系统的接口,TMMIC VO的接口等等。

        以近期TM项目与MIC VO的一个举例,MIC VO中修改了用户基本信息,在TM的个人设置页面显示。

    设计该类用例时,需要有清晰的操作步骤,如果用户对系统不舒适,需要在明确说明

    操作步骤:

    (1)       TM账号登录MIC VO

    (2)       修改个人信息

    (3)       用该账号重新登录TM客户端

    (4)       点击TM头像旁边的个人设置,检查信息是否变化

    期望结果:

    TM个人设置中的信息与用户在VO中修改的个人信息一致

       

    接口用例中请注意对数据库表的检查

    页面

        该文件夹主要包含一些与页面相关的用例,如果页面元素检查、有特殊要求的页面检查

    权限

        该文件夹主要包含一些与权限有关的用例,比如说XXX网站只允许高级会员使用统计功能,用例设计为:

    用高级会员登录,有【统计】功能

    用非高级会员登录,没有【统计】功能

    控件

        该文件夹主要包含一些特殊控件的用例,比如说日历控件、分页按钮等等,因为这些控件基本上都统一调用的,我们可以作为公共用例来设计

    测试用例的设计要素

    目前测试用例的设计主要是在QC中进行,用例的要素包括:用例概述、用例优先级、前置条件、操作步骤、测试数据、预期结果、备注、对应JIRA_BUG_ID

    测试用例的书写规范

        测试用例最好能够做到尽量详细,我们的要求是尽量保证一个用例只有一个主要结果,可以包含其他辅助结果,也就是主结果完成后出现的其他现象,没有必要另建一个测试用例的,比如说xxx模块添加用户成功(主结果),系统自动跳转到用户列表页面(辅助结果)。

       

        关于用例设计要素的书写规范,我做了如下描述:

     

        用例概述(必需项):QC中表现为一个Test Case的名称,要简明扼要对该用例设计的目的进行描述。

     

        用例优先级(必需项):一些功能性的、流程性、业务规则的、接口的用例优先级最高,必须执行,一些页面的用例优先级会相对较低,可选择执行,优先级别需要视需求而定。优先级必须定义,这对建立测试执行计划有很大的帮助

     

        前置条件(可选项):对于当前的用例,必须要满足一个前提条件才能完成,这些条件如果写在操作步骤中就会很繁琐,就可以单独放置在前置条件中。前置条件可以是一个说明,一个注意事项,也可以是一个前面的case,具体视情况而定。

     

        操作步骤(必需项):尽量详细,步骤鲜明,语言简洁,为清晰的描述最终结果,操作步骤中可适当包含一些中间结果。

     

        测试数据(必需项):基本上每个测试用例都是需要有测试数据支持的,该项必不可少,有的时候可能是多种情况的测试数据对应同一个结果,这就需要每种情况准备一组数据。比如说,用户年龄范围必需为【18-25】岁之间,才可以注册XXX游戏,若满足【18-25】这个区间范围,我们可以用三个数据,18岁、20岁、25岁,这三个数据时都必须要验证的。

     

        如果不能给出明确的测试数据,可以提供测试数据准备条件,准备了几组数据,就相当于要执行这个Test case几次。

     

        预期结果(必需项):准确描述出用例的结果,结果具有唯一性。

       

        备注(可选项):一些特殊的说明地方

     

        BUG_ID(如果该用例有对应的BUG,此项必填):这个主要用于测试用例执行过程中,尽量不要怕麻烦,每发现一个BUG就要把BUG_ID记录到这个用例中,一来可以我们的BUG_ID和测试用例连接起来,二来便于对用例的有效性作统计。

     

  • lr_set_debug_message()函数的使用

    2009-02-06 16:09:58

    lr_set_debug_message()函数的使用

     

    简介:

    lr_set_debug_mssage()函数可以作为脚本中日志输出的开关,其作用如同Runtime Setting -> log中的设置一样,如果Runtime setting取消勾选Enable log,而在脚本调试的过程中需要查看日志输出就可以使用lr_set_debug_mssage()函数。

     

    该函数使用起来比Runtime Setting要灵活,他可以根据需要设置应该输出哪些代码段的日志,而不是像Runtime Setting一样,只要设置了就会输出整个脚本的日志,不管这些日志对用户来说是否有用。如果把这两种设置方式比作变量的话,Runtime Setting就是一个全局变量,在整个脚本中有效,而lr_set_debug_message()函数则属于局部变量,只在当前脚本中有效。

     

    比如说脚本中有一个登录一个退出函数,我只想在脚本调试过程中查看登录的日志,那么就可以实现这样的设置:lr_set_debug_mssage() - 登录 - lr_set_debug_mssage(),如此以来,就可以只针对性的查看“登录”的日志了。

     

    函数介绍:

    int lr_set_debug_message (unsigned int message_level, unsigned int on_off);

    message_level有如下几种形式

    1、标准日志(Brief)LR_MSG_CLASS_BRIEF_LOG

    2、扩展日志(Extended Log)LR_MSG_CLASS_EXTENDED_LOG

    扩展日志中还包括几个小项

    服务器返回值(Result Data): LR_MSG_CLASS_RESULT_DATA

    参数替换(Parameter Substitution)LR_MSG_CLASS_PARAMETERS 

    高级输出(Full Run-Time Trace) : LR_MSG_CLASS_FULL_TRACE

     

    3、另外还有一种情况就是仅当在出错的时候输出:

    LR_MSG_CLASS_JIT_LOG_ON_ERROR

     

    on_off2种形式:

    LR_SWITCH_ON LR_SWITCH_OFF

     

    由上可知lr_set_debug_message()函数使用大致如下

    lr_set_debug_message(LR_MSG_CLASS_EXTENDED_LOG| LR_MSG_CLASS_PARAMETERS, LR_SWITCH_ON);

    … …

    lr_set_debug_message(LR_MSG_CLASS_EXTENDED_LOG| LR_MSG_CLASS_PARAMETERS, LR_SWITCH_OFF);

     

    示例:

    /*********************************************************

    本示例主要是关于lr_set_debug_message()函数的使用

    如果关闭了Runtime setting中的Log输出,

    但是在脚本中设置了lr_set_debug_message()开关,

    脚本调试过程中仍然能够输出调试日志

    注:运行该脚本前请取消勾选Runtime setting->Log中的Enable Log

    *********************************************************/

    Action()

    {

        char str[10] = "tester";

     

        lr_output_message("*****开启日志保存前%s*****",str);

        //开启日志输出

        lr_set_debug_message(LR_MSG_CLASS_EXTENDED_LOG|LR_MSG_CLASS_PARAMETERS                                 |LR_MSG_CLASS_RESULT_DATA|LR_MSG_CLASS_FULL_TRACE ,LR_SWITCH_ON);

        //设置一个开始日志输出的flag

        lr_debug_message(LR_MSG_CLASS_PARAMETERS |LR_MSG_CLASS_RESULT_DATA                           |LR_MSG_CLASS_FULL_TRACE ,"*****开始标志****");

     

        lr_save_string("good",str);

        //设置一个结束日志输出的flag

        lr_debug_message(LR_MSG_CLASS_PARAMETERS |LR_MSG_CLASS_RESULT_DATA                               |LR_MSG_CLASS_FULL_TRACE ," *****结束标志****");

        //关闭日志输出

        lr_set_debug_message(LR_MSG_CLASS_EXTENDED_LOG|LR_MSG_CLASS_PARAMETERS                               |LR_MSG_CLASS_RESULT_DATA|LR_MSG_CLASS_FULL_TRACE ,LR_SWITCH_ON);

     

        lr_output_message("*****开启日志保存后%s*****",str);

     

        return 0;

    }

    该实例中还使用了一个lr_debug_message()函数,该函数的第一个参数与lr_set_debug_message()函数中的参数相同。

    运行结果:

    Action.c(12): *****开启日志保存前tester*****

    *****开始标志****

    Action.c(20): Notify: Saving Parameter "tester = good"

     *****结束标志****

    Action.c(29): *****开启日志保存后tester*****

    Ending action Action.

    Ending iteration 1.

    Ending Vuser...

    Starting action vuser_end.

    Ending action vuser_end.

    Vuser Terminated.

  • LoadRunner中参数的设置

    2008-11-10 13:37:59

    LoadRunner中参数的设置

     

    参数个数:10

    tester1tester2tester3 tester10

    迭代次数:2

     

    场景设置()Sequential+Each Iteration

    执行结果:

    VuGen中:1个用户

    第一次迭代(Iteration)取值为tester1

    第二次迭代(Iteration)取值为tester2

     

    Controller中:5个用户并发,每个用户

    第一次迭代(Iteration)取值为tester1

    第二次迭代(Iteration)取值为tester2

     

    (备注:5个用户每次迭代取值都相同,强调了用户之间的一致性)

     

    场景设置()Sequential+Each Occurrence

    执行结果:

    VuGen中:1个用户,1次迭代

    第一次出现(Occurrence)取值为tester1

    第二次出现(Occurrence)取值为tester2

     

    Controller中:5个用户,1次迭代

    第一次出现(Occurrence)取值为tester1

    第二次出现(Occurrence)取值为tester2

     

    每次迭代以此类推…

     

    (备注:5个用户每次出现取值都相同,每次迭代取值都不同)

     

    场景设置()Sequential+Once

    执行结果:

    VuGen中:1个用户

    每次都取同一个值,无论迭代多少次,都取tester1

     

    Controller中:5个用户

    每次都取同一个值,无论迭代多少次,都取tester1

     

    (备注:5个用户每次都取同一个值,无论迭代多少次)

     

    场景设置()Unique+Each Iteration+Abort Vuser

    执行结果:

    VuGen中:1个用户

    第一次迭代(Iteration)取值为tester1

    第二次迭代(Iteration)取值为tester2

     

    Controller中:5个用户

    用户1:第一次迭代(Iteration)取值为tester1

    第二次迭代(Iteration)取值为tester2

     

    用户2:第一次迭代(Iteration)取值为tester3

    第二次迭代(Iteration)取值为tester4

    .

    .

    .

    以此类推…

     

    (备注:当6个用户并发时,会出现参数不够的情况,有一个用户就会被终止)

     

    场景设置()Unique+Each Iteration+Continue in a cycle manner

    执行结果:

    VuGen中:1个用户

    第一次迭代(Iteration)取值为tester1

    第二次迭代(Iteration)取值为tester2

     

    Controller中:5个用户

    用户1:第一次迭代(Iteration)取值为tester1

    第二次迭代(Iteration)取值为tester2

     

    用户2:第一次迭代(Iteration)取值为tester3

    第二次迭代(Iteration)取值为tester4

    .

    .

    用户6:第一次迭代(Iteration)取值为tester1

    第二次迭代(Iteration)取值为tester2

     

    以此类推…

     

    (备注:当6个用户并发时,会出现参数不够的情况,会重新从参数列表第一行开始取)

     

    场景设置()Unique+Each Iteration+With Last Value

    执行结果:

    VuGen中:1个用户

    第一次迭代(Iteration)取值为tester1

    第二次迭代(Iteration)取值为tester2

     

    Controller中:5个用户

    用户1:第一次迭代(Iteration)取值为tester1

    第二次迭代(Iteration)取值为tester2

     

    用户2:第一次迭代(Iteration)取值为tester3

    第二次迭代(Iteration)取值为tester4

    .

    .

    用户6:第一次迭代(Iteration)取值为tester9

    第二次迭代(Iteration)取值为tester10

     

    以此类推…

     

    (备注:当6个用户并发时,会出现参数不够的情况,会用最后的值作为参数)

     

    场景设置()Unique+Once

    执行结果:

    VuGen中:1个用户,迭代2次,每个迭代中参数出现2

    与迭代无关,一次都取唯一一个值:tester1

     

    Controller中:5个用户

    用户1: 取值为tester1

    用户2: 取值为tester2

    用户3: 取值为tester3

    .

    .

    以此类推…

     

    (备注:与迭代无关,强调用户之间的差异性)

     

    场景四至七中,Block Size是自动分配的,如果人工分配取值会有变化,比如说2个用户,每个用户迭代2次,为每个用户分配3个参数,则:

    用户1取值tester1tester2 tester3

    用户2取值tester4tester5 tester6

     

  • [转贴] 测试人员应具备的几种思维方式,你是否也具备了?

    2007-07-09 10:59:49

    看到ffhhj的帖子,觉得写得非常好,所以转贴下来用以勉励自己,谢谢咯^_^
     
    [转贴]测试人员应具备的几种思维方式,你是否也具备了?

       1、逆向思维方式
       · 逆向思维在测试中用的很多,比如将根据结果逆推条件,从而得出输入条件的等价类划分
       · 其实逆向思维在调试当中用到的也比较多,当发现缺陷时,进一步定位问题的所在,往往就是逆流而上,进行分析
       · 逆向思维是相对的,就是按照与常规思路相反的方向进行思考,测试人员往往能够运用它发现开发人员思维的漏洞

       2、组合思维方式
       · 很多东西单一的思考都没有问题,当将相关的事物组合在一起却能发现很多问题;如多进程并发,让程序的复杂度上了一个台阶,也让程序的缺陷率随之而增长
       · 按照是否排序组合可以分为:排列(有序)和组合(无序);针对不同的应用,可以酌情考虑使用“排列”或者“组合”
       · 为了充分利用组合思维而不致于让自己的思维混乱,要注意“分维”,将相关的因素划分到不同的维度上,然后再考虑其相关性

       3、全局思维方式
       · 事物往往存在多面性,当我们掌握了越多的层面,我们对它的认识就越清楚,越有利于我们掌握其本质,全局思维方式就是让我们从多角度分析待测的系统;试着以不同角色去看系统,分析其是否能够满足需求
       · 其实平常我们在软件开发过程中,进行的各种评审,就是借助全局思维的方式,让更多的人参与思考,脑力激荡,尽可能的实现全方位审查某个解决方案的正确性以及其他特性

       4、两极思维方式
       · 边界值分析是两极思维方式的典范
       · 为了看系统的稳定性,我们采用了压力测试
       · 两极思维方式,是在极端的情况下,看是否存在缺陷?
       · 注意是两极,不是一极
       · 测试人员做久了,往往容易走极端——职业病,不利于与人沟通

       5、简单思维方式
       · 剥离一些非关键特征,追逐事物的本质,让事物简单的只剩下“根本”
       · 针对事物本质(解决问题的本质)的测试,让我们不至于偏离方向

       6、比较思维方式
       · 认识事物时,人们往往都是通过和头脑中的某些概念进行比较,找出相同、相异之处,或者归类,从而将其加入大脑中的知识体系,可能的话,再建立好的搜索方式,以便以后使用
       · 应用模式是“比较思维”很常见的例子,现在模式很火,有设计模式、体系结构模式、测试模式、等等,一些专家针对一些相关问题的共性找出来的解决方法,取完名字后,可以让大家方便的复用
       · 让经验在这里发挥作用,测试中经验很重要,比较思维是使用经验的方式

       7、动起来,更精彩
       · 关注程序的运行时状态
       · 传统的基于结构的程序可以更多的在代码中反映将来程序的运行方式;而面向对象将代码和运行时显著分离
       · 让我们在关注代码静态结构(如类结构)的同时,也要谨慎关注其动态(对象交互网)表现

       其实这些思维方式,大家都在有意识或者无意识的使用着,它们各自都有自己的妙处,将我们的思维发散,有意识的将他们用在问题的思考上,有时可以给我们一种“柳暗花明又一村”的感觉。

       最后想说,只是知道这些原则意义不是很大,如果真能让它们成为思考的血液,才能发挥它的真正价值。那真的需要很多的历练,其实

    成为一名出色的测试人员,远没有那么简单,需要简单,需要(不断的学习+不断的经历+不断的思考)。

  • 三个重要的测试原则

    2007-06-20 11:05:06

     

    三个重要的测试原则:

    1、 软件测试是为了发现错误而执行程序的过程。

    2、 一个好的测试用例具有较高的发现某个尚未发现的错误的可能性。

    3、 一个成功的测试用例能够发现某个尚未发现的错误。

Open Toolbar