工欲善其事 必先利其器

发布新日志

  • 测试方法

    2016-05-18 17:29:45


    --------------------------------

    验收测试
    --------------------------------
    也称为交付测试
    ISTQB定义:  
    针对用户需求、业务流程的正式的测试,确定系统是否满足验收标准,由用户、客户或其他授权机构决定是否接受系统。
    formal testing with respect to user needs, requirements, and business processes conducted to determine whether a system satisfies the acceptance criteria and to enable the user, customers or other authorized entity to determine whether or not to accept the system

    用户验收测试,这个一般是由开发方在移交产品前
    运行验收测试,这个更多是运维层面,保证系统是可以被正常运行和维护的。比如备份、灾难恢复等等
    合同和规范验收测试,这个主要就是参照约定的规范进行验证。,以及针对政府、法律等的合规验证
    alpha测试 一般在开发者所提供的场地或环境中进行
    beta测试 则是脱离开发者环境,在用户的场所或环境中进行

    alpha版本,beta版本,release版本

    ATDD也是敏捷研发,特别是极限编程所推崇的一种开发模式。也有说BDD 就是针对用户故事user story,首先确定好针对这个用户故事的用户级的验收条件,确保Userstory的功能满足验收条件时,才可以关闭这个用户故事。





    下面我们再看一下按测试手段的不同进行分类,有哪些测试概念

    1. 黑盒、白盒、灰盒
    在测试中,把程序看作一个不能打开的黑盒子,在完全不考虑程序内部结构和内部特性的情况下,在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数据而产生正确的输出信息。黑盒测试着眼于程序外部结构,不考虑内部逻辑结构,主要针对软件界面和软件功能进行测试。
    具体的黑盒测试用例设计方法包括等价类划分法、边界值分析法、错误推测法、因果图法、判定表驱动法、正交试验设计法、功能图法、场景法等。



    白盒测试针对程序的逻辑结构设计测试用例,用逻辑复盖率来衡量测试的完整性。逻辑单位主要有:语句、分支、条件、条件值、条件值组合,路径。语句复盖就是复盖所有的语句,其他类推。另外还有一种判定条件复盖,其实是分支复盖与条件复盖的组合,在此不作讨论。跟条件有关的复盖就有三种,解释一下:条件复盖是指复盖所有的条件表达式,即所有的条件表达式都至少计算一次,不考虑计算结果;条件值复盖是指复盖条件的所有可能取值,即每个条件的取真值和取假值都要至少计算一次;条件值组合复盖是指复盖所有条件取值的所有可能组合。老纳做过一些粗浅的研究,发现与条件直接有关的错误主要是逻辑操作符错误,例如:||写成&&,漏了写!什么的,采用分支复盖与条件复盖的组合,基本上可以发现这些错误,另一方面,条件值复盖与条件值组合复盖往往需要大量的测试用例,因此,在老纳看来,条件值复盖和条件值组合复盖的效费比偏低。效费比较高且完整性也足够的测试要求是这样的:完成功能测试,完成语句复盖、条件复盖、分支复盖、路径复盖。做过单元测试的朋友恐怕会对老纳提出的测试要求给予一个字的评价:晕!或者两个字的评价:狂晕!因为这似乎是不可能的要求,要达到这种测试完整性,其测试成本是不可想象的,不过,出家人不打逛语,老纳之所以提出这种测试要求,是因为利用一些工具,可以在较低的成本下达到这种测试要求,后面将会作进一步介绍。
    关于白盒测试用例的设计,程序测试领域的书籍一般都有讲述,普通方法是画出程序的逻辑结构图如程序流程图或控制流图,根据逻辑结构图设计测试用例,这些是纯粹的白盒测试,不是老纳想推荐的方式。老纳所推荐的方法是:先完成黑盒测试,然后统计白盒复盖率,针对未复盖的逻辑单位设计测试用例复盖它,例如,先检查是否有语句未复盖,有的话设计测试用例复盖它,然后用同样方法完成条件复盖、分支复盖和路径复盖,这样的话,既检验了黑盒测试的完整性,又避免了重复的工作,用较少的时间成本达到非常高的测试完整性。不过,这些工作可不是手工能完成的,必须借助于工具,后面会介绍可以完成这些工作的测试工具。

    白盒测试的测试方法有代码检查法、静态结构分析法、静态质量度量法、逻辑覆盖法、基本路径测试法、域测试、符号测试、路径覆盖和程序变异。


    1.语句覆盖每条语句至少执行一次。
    2.判定覆盖每个判定的每个分支至少执行一次。
    3.条件覆盖每个判定的每个条件应取到各种可能的值。
    4.判定/条件覆盖同时满足判定覆盖条件覆盖。
    5.条件组合覆盖每个判定中各条件的每一种组合至少出现一次。
    6.路径覆盖使程序中每一条可能的路径至少执行一次。



    2. 静态、动态
    静态测试是指无须执行被测代码,而是借助专用的软件测试工具评审软件文档或程序,度量程序静态复杂度,检查软件是否符合编程标准,借以发现编写的程序的不足之处,减少错误出现的概率;

    (互查、走查、会议审查)

    动态测试方法是指通过运行被测程序,检查运行结果与预期结果的差异,并分析运行效率、正确性和健壮性等性能。这种方法由三部分组成:构造测试用例、执行程序、分析程序的输出结果。


    最好的一个类比是检查二手汽车的过程。踢一下轮胎、看看车漆、打开引擎盖检查都属于静态测试技术。发动汽车、听听发动机声音、上路行驶都属于动态测试技术。


    3. 手工、自动化
    手工测试 ,由专门的测试人员从用户视角来验证软件是否满足设计要求的行为。
    (众包测试、探索式测试)


    在考虑自动化测试的时候,我们必须满足人们的要求:
    平台和操作系统的独立性
    数据驱动能力(输入数据,输出数据,元数据)
    可自定义报表(数据库访问、水晶报表)
    易于调试和日志记录
    版本控制友好型的二进制文件
    可扩展性和可定制性(开放的原料药能够与其他工具相结合)
    常见的驱动程序(例如,在java开发的生态系统,这意味着Ant或Maven和流行的IDE)。这使得测试与开发人员的工作流程相结合。
    支持无人参与的测试运行的集成与构建过程和批处理运行。连续集成服务器需要这个。
    电子邮件通知,如反弹消息
    支持分布式执行环境(分布式测试床)
    支持分布式应用(分布式系统)



    自动化测试框架的要求:
    1. 定义如何来表达预期结果
    2. 连接并驱动目标软件运行
    3. 执行测试
    4. 输出结果报告



  • MonkeyTalk的使用(二)

    2013-01-24 21:22:39

    这两天没什么时间看这个东西,但还是大概了解了它的参数化和校验。

    1. MonkeyTalk自己的脚本格式类似如下
    # simple script. to login as joe
    Input username EnterText danmy
    Input password EnterText “i like cheese”
    Button LOGIN Tap

    也支持转成js脚本执行 如
    load("libs/testapidemo.js");


    testapidemo.test1.prototype.run = function() {

    this.app.device().menu();
    this.app.menu().select("Add note");
    this.app.textArea("note").enterText("My test");
    this.app.device().back();
    this.app.table().selectIndex("1");
    this.app.menu().select("Delete");
    };

    2. 设置变量
    以${var} 表示变量如
    Vars * Define usr="default-at-example.com" pwd
    Input username EnterText ${usr}
    Input password EnterText ${pwd}
    Button LOGIN Tap

    3. 可以在mt脚本中引用其他脚本
    Script. login.mt Run

    4. 支持csv格式的数据文件作数据驱动
    usr, pwd
    joe-at-doe.com, "i like cheese"
    alpha-at-beta.net, password1
    charlie-at-dog.org, abc123

    脚本格式 Script. login.mt RunWith credentials.csv

    5. 校验点
    脚本中使用verify命令支持校验

    Vars * Define usr="default-at-example.com" pwd=name

    Input username EnterText ${usr}
    Input password EnterText ${pwd}
    Button LOGIN Tap
    Label welcome Verify "Welcome, ${name}!"
    Button LOGOUT Verify


    使用Test命令执行该脚本进行校验

    Test login.mt Run joe-at-doe.com "i like cheese" "Joe Doe"


    6. 测试集的组织,定义为mts,包括多个mt脚本的执行语句,包含setup、teardown等部分

    # setup runs before every test
    Setup login.mt Run joe@doe.com “i like cheese”

    # teardown runs after every test
    TearDown logout.mt Run

    # the tests...
    Test add_contact.mt RunWith contacts.csv
    Test remove_contact.mt RunWith contacts.csv

    7. 此外还支持命令行执行、支持转换为js执行。 因为是通过http消息通信,也支持Json接口

    接口包括PING、PLAY、RECORD三类指令消息

  • 试试Word的离线发博功能

    2013-01-23 22:31:52

    Yeah~~~ Can you see me?


    重新发布不好使


    另外本地图片还是没办法直接传上来,大打折扣啊,看来只能写写纯文字的东西

  • 用MonkeyTalk测试Android应用(一)

    2013-01-22 22:03:27

    MonkeyTalk是Gorilla Logic的一款开源的支持录制回放并跨平台的自动化工具。IOS下没试,Android应用测试缺点是需要应用源码,但是操作还比较方便,在此记录下使用过程 

    1. 到http://www.gorillalogic.com/developer-resources/downloads下载对应版本的MonkeyTalk,目前最新版本是V1.0.30。 下载下来解压即可
    其中主要Agent和IDE,agent是一个jar包,需要编译到应用工程中。通过该Agent和IDE进行通信,实现PC上测试模拟器或手机上的应用

    2. 下载Eclipse的AJDT插件,用于转换应用工程
    http://www.eclipse.org/ajdt/downloads/

    3. 打开应用,如AndroidSDK下自带的Notepad应用工程。将应用转换为AspectJ工程
    Right-click project, Configure, Convert to AspectJ

    3. 在工程下创建libs目录,并将MonkeyTalk\agent\android\目录下的agentXXX.jar拷贝到libs下

    4. 将agentXXX.jar加入AspectJ路径
    Add to AspectPath

    5. 修改应用的AndroidManifest.xml文件,增加权限
    • android.permission.INTERNET
    • android.permission.GET_TASKSUpdate Android Manifest
    6.在应用的build path中order and export tab下选中AspectJ运行库 
    Export AspectJ Runtime

    7. eclipse里执行该应用或编译好应用并部署到模拟器或设备上,打开应用
    此时LogCat中会打印MonkeyTalk相关的初始化信息
    如:
    MonkeyTalk(336): starting PlaybackServer on port 16862
    。。。
    MonkeyTalk(336): Initializing Device automator
    MonkeyTalk(336): Initializing MenuAutomator
    MonkeyTalk(336): Initializing DialogAutomator
    MonkeyTalk(336): Initializing TabAutomator
    MonkeyTalk(336): Initializing Input automator

    应用的Monkeytalk agent已正常启动

    8 打开MonekeyTalk IDE,通过new菜单建立一个新的MT工程

    9. 在刚才的MT工程下新建一个测试脚本如test1.mt,此时可以看到录制工具栏
    10.选择android小绿人,连接模拟器或设备,日志栏打印如下信息
    22:44:28.000: Connection set to Android Emulator or Tethered Device

    表示IDE和Agent建立了连接

    11. 此时在模拟器上界面上操作,即会自动生成MT的关键字视图下的脚本
    下面是notepad示例应用的简单录制脚本
    Device * menu
    Menu * select "Add note"
    TextArea note enterText "My test"
    Device * back
    Table * selectIndex 1
    Menu * select Delete

    12 停止录制后,保存脚本,可以回放操作

    明天再试试校验、参数化等功能
  • 自动化测试平台建设目标之“多、快、好、省”

    2013-01-19 21:28:52

    最近一直在思考建设自动化平台的目标是什么? 

    以下总结下个人的思考以及对自动化测试平台建设目标的认识: 其实无外乎 “多、快、好、省”四字。并且这四字目标的优先级也是递减的。

    一、自动化测试的“多”
    建设自动化测试平台,首要目标是“多”。可以做尽可能多的自动化测试。
    自动化发展到现阶段,大部分的测试任务都有相对应的测试技术可以去实施、完成。从功能测试到性能测试、到覆盖安全测试、兼容性测试、用户体验测试等等,自动化的用武之地越来越多,所以应该使自动化尽可能发挥更大的作用。 在最基本的功能测试内尽可能多地覆盖更多的分支、业务逻辑、用户使用场景等。通过自动化测试完成人工测试很难完成的性能测试、兼容性测试, 通过自动化、以及工具手段优化我们的安全测试、用户体验测试,等等。 通过平台建设完成更多的测试任务,得到更高的测试覆盖率,才能从量变达到质变,让自动化测试更有效地发挥应用的效力。
    对实施自动化来说,很少的用例覆盖率是无效的,反而投入产出比过高,只有当自动化的投入转换为更多的用例覆盖才能更加突出自动化建设的意义。

    二、自动化测试的“快”
    自动化测试的应用,另一重要目标是“快”。敏捷思想、持续集成、每日构建等等,都要求自动化测试能够快速完成回归测试。所以自动化测试平台的重要目标是快速完成测试,在短时间内能够完成预期的测试目标。相应的,平台框架也需要配合RBT(基于风险测试)相关的方法论来识别风险,定义测试优先级;测试环境的快速部署技术、分布式的测试执行技术等等来达到这一目标。
    当自动化测试能做到“快”的目标时,快速发布、版本小步迭代才有基本的质量保证。


    三、自动化测试的“好”
    建设自动化测试平台,另一目标是“好”。通过自动化做更好的测试。
    借助平台自动化的技术手段,让测试做得更好,更加智能。大批量测试数据的处理,自动化的结果校验、关键异常的自动捕捉等等。通过“好”的自动化测试,进一步提升测试的价值。

    四、自动化测试“省”
    自动化测试平台建设还含有一个目标是“省”。让测试人员可以更省力、更简单的完成测试,同时让自动化测试占用更少的资源。测试人员在进行自动化测试的脚本编写、测试执行中,借助自动化测试平台,可以更加简单、快速的完成自动化的构建和实施。普通的测试人员借助良好的平台能很好地通过自动化完成测试任务。这就要求平台本身的可用性、和测试人员的交互友好度,是平台建设需要考虑的一大重要目标。
    另外从实施成本上,自动化测试平台需要占用尽可能少的资源,包括设备资源、人力投入的资源等等

    如果自动化平台的建设,能使自动化测试达到以上四点目标,则毫无疑问是一个优秀的自动化测试平台。而在建设平台的过程中,以上四点目标可以按顺序作为平台建设的分阶段目标来达成。


  • 从食堂就餐看性能测试分析

    2013-01-14 21:38:20


    中午在单位食堂吃饭排了个长队,等了好半天。然后就想这不就是在跑性能吗??

    如果把食堂看作一个在线系统,员工吃饭看作是一次业务处理。回过头来看系统性能测试分析中需要关注的点,其实颇有意思

    首先最直观的性能表现就是打饭窗口的长队,可以说这是系统性能处理能力最直观的表现了。指标对应Response Time
    队伍前进的快慢,对应每秒处理事务数TPS
    同时进餐人数,对应并发请求数  

    我们再看看影响性能指标的相关因素
    1) 打饭窗口数 -- 对应业务处理进程数,有时某个窗口存在多个打饭师傅,这时可以看作是多线程。 处理进程(线程)的多少,是决定业务处理性能的最主要因素。
    2) 师傅的业务熟练程度 -- 处理器的性能,计算能力
    3) 所点餐品多少和分布情况  -- 对应数据的处理能力。  所点餐品离窗口近,分布集中,自然处理起来快些,好比数据存储在内存库,不进行跨表、跨库的关联处理之类,性能自然较好。
    4) 刷卡付账环节  -- 一般组合的餐品价格师傅都能快速算出来,但是比较多的菜品,计算起来要多花点时间。 好比对于一些常见的请求,从缓存里读取自然会快些。
                        异常情况1: 卡内金额不够、点菜结束又再点了一份。 对应到这些异常处理或是重试会也影响处理性能。
                        异常情况2: 看菜单上有的菜,点菜时却发现没有,需要重新确认。 这个相当于业务请求先查询出携带的参数,响应却判参数不存在了。 数据实时关联没做好,属于系统Bug(此Bug还存在啊)
    5) 选择的餐品类型 --- 打饭的队伍比等面条、馄饨的队伍处理起来一般相对快些。不同业务,处理的方式不同,性能表现也不同。

    另外,餐厅的面积是有限的,窗口数也是有限的,打饭师傅的数量也是有限的。 所以系统处理能力或曰系统容量是有限的。貌似目前食堂还没达到处理极限(虽然用户满意度不高),暂时还不用扩容,呵呵
    其实我们注意到,针对处理能力的问题,有两个现象:
    1) 二楼食堂人满为患,一楼食堂比较宽松。 这个给我们的启示就是,在系统还具备处理能力的前提下,性能并不是影响用户选择的最主要参考(关键需求即业务本身的吸引力更重要)。但系统超过处理能力或者系统异常,无法提供服务后果还是很严重的。 饿肚子咋干活。。
    2) 业务上存在分时处理,所有的业务请求被强制分时间段访问。这个是根据业务特点决定的,业务具有明显的峰谷特点,在系统容量无法处理大量并发时,对请求通过业务逻辑实现错峰分流,是解决性能问题一种常规手段。

    上文也提到,餐品窗口有不同类型,面条、盖浇饭等。这个其实是根据业务特点实现的定向分流,提高资源处理效率。如果都混在一起,性能应该不好。
    再一个,我们打饭其实包含了多个操作步骤:排队、取餐具、点餐、盛饭盛汤、落座、进食、返还餐具。 对应到性能测试分析,可以借鉴的就是,业务处理要进行细分,系统重点处理关键节点,业务请求本身能完成的事务由客户端完成,在请求时携带结果参数(餐具)。 业务处理完成后,要及时完成垃圾回收释放资源。

    另外一个比较重要的地方就是应急处理,系统发生异常时要能保证提供最基本的服务。饭点时员工吃不上饭应该是这个系统不能接受的问题。其实可以考虑开个零售点备些面包、方便面啥的,这样至少停电、停气时还能满足最基本的充饥需求。

    基本就这么多,其实还有很多后台的工作我们看不到,其实应该对性能影响也是很大的,比如食材的准备、烹饪过程、配套设施的保障等,这边就不发散了。

    总结一下,从食堂系统来看,我们做性能分析其实大致要关注以下几点:
    1) 业务请求的数量、并发请求数
    2) 业务处理效率
    3) 系统资源情况,处理能力
    4) 业务处理的关键节点
    5) 分流策略
    6) 异常处理和应急机制

  • Android SDK和ADT更新失败的解决办法

    2013-01-02 10:32:01

    这几天Google的下载站点总是无法连接,Android SDK自动更新时总是提示下面的错误
    Failed to fetch URL https://dl-ssl.google.com/android/repository/repository-2.xml, reason: Connection to https://dl-ssl.google.com refused
    Failed to fetch URL http://dl-ssl.google.com/android/repository/addons_list-7.xml, reason: Connection to http://dl-ssl.google.com refused

    更新ADT时无法解析https://dl-ssl.google.com/android/eclipse

    原因大家都知道,这里记录下解决办法
    首先,SDK manager里tool->options 里选中强制使用http

    然后修改Hosts文件, 把Google相关站点加入,包括dl-ssl.google.com

    #Google Service
    #Chrome 网上应用
    203.208.46.146 chrome.google.com
    203.208.46.146 clients0.google.com
    203.208.46.146 clients1.google.com
    203.208.46.146 clients2.google.com
    203.208.46.146 clients3.google.com
    203.208.46.146 clients4.google.com
    203.208.46.146 www.googleusercontent.com
    203.208.46.146 lh0.googleusercontent.com
    203.208.46.146 lh1.googleusercontent.com
    203.208.46.146 lh2.googleusercontent.com
    203.208.46.146 lh3.googleusercontent.com
    203.208.46.146 lh4.googleusercontent.com
    203.208.46.146 lh5.googleusercontent.com
    203.208.46.146 lh6.googleusercontent.com
    203.208.46.146 clients1.googleusercontent.com
    203.208.46.146 clients2.googleusercontent.com

    #网页快照
    203.208.46.146 webcache.googleusercontent.com

    #Google SSL
    203.208.46.146 encrypted.google.com
    203.208.46.146 encrypted.google.com.hk

    #Google Docs
    203.208.46.146 docs.google.com
    203.208.46.146 docs0.google.com
    203.208.46.146 docs1.google.com
    203.208.46.146 docs2.google.com
    203.208.46.146 docs3.google.com
    203.208.46.146 spreadsheets.google.com
    203.208.46.146 spreadsheets0.google.com
    203.208.46.146 spreadsheets1.google.com
    203.208.46.146 spreadsheets2.google.com
    203.208.46.146 spreadsheets3.google.com

    #Gmail
    203.208.46.146 mail.google.com
    203.208.46.146 chatenabled.mail.google.com #Gmail中Gtalk聊天服务

    #Google 搜索
    203.208.46.146 www.google.com

    #Google preview
    203.208.46.146 www.googlepreview.com

    #Google 翻译
    203.208.46.146 translate.google.com
    203.208.46.146 translate.googleapis.com

    #Google 搜索建议(IE9)
    203.208.46.146 clients5.google.com

    #Google Code
    203.208.46.146 code.google.com

    #Picasa 网络相册
    203.208.46.146 picasaweb.google.com
    203.208.46.146 lh0.ggpht.com
    203.208.46.146 lh1.ggpht.com
    203.208.46.146 lh2.ggpht.com
    203.208.46.146 lh3.ggpht.com
    203.208.46.146 lh4.ggpht.com
    203.208.46.146 lh5.ggpht.com
    203.208.46.146 lh6.ggpht.com
    203.208.46.146 lh7.ggpht.com
    203.208.46.146 lh8.ggpht.com
    203.208.46.146 lh8.ggpht.com
    203.208.46.146 lh9.ggpht.com
    203.208.46.146 lh6.google.com

    #Google 个人资料
    203.208.46.146 profiles.google.com
    203.208.46.146 browsersync.google.com

    #Google+
    203.208.46.146 talkgadget.google.com #Google+中的聊天服务
    203.208.46.146 ssl.gstatic.com
    203.208.46.146 images-pos-opensocial.googleusercontent.com
    203.208.46.146 images1-focus-opensocial.googleusercontent.com
    203.208.46.146 images2-focus-opensocial.googleusercontent.com
    203.208.46.146 images3-focus-opensocial.googleusercontent.com
    203.208.46.146 images4-focus-opensocial.googleusercontent.com
    203.208.46.146 images5-focus-opensocial.googleusercontent.com
    203.208.46.146 images6-focus-opensocial.googleusercontent.com
    203.208.46.146 plus.google.com

    #Download 下载
    203.208.46.146 dl.google.com
    203.208.46.146 dl-ssl.google.com

    #Groups
    203.208.46.146 groups.google.com

    #Google URL Shortener
    203.208.46.146 goo.gl

    #Google App Engine
    203.208.46.146 appengine.google.com

    #Android Developer
    74.125.113.121 developer.android.com



  • 性能评估工具PageSpeed及Yslow

    2012-02-09 21:17:35

    题外话: 很久没有更新这边的blog了,想来1年多也有不少收获,还是总结总结罢。想哪是哪,先从具体的工具说起吧

    页面性能评估工具Yslow和PageSpeed

    PageSpeed及Yslow是目前比较常用的Web页面性能评级工具

    先说Yslow

    Yslow是Yahoo发布的一款免费性能评估工具,提供包括Firefox,Chrome,opera,safari浏览器上的插件。
    基于Yahoo定义的提高webSite性能的规则集对访问的页面进行评估,给出评估结论。(http://developer.yahoo.com/performance/rules.html)
    详细的使用方法此处不再介绍,也比较简单,随便搜索一下也能找到。
    本文重点说明下命令行调用Yslow进行测试的方法,这样就可以比较顺利的实现自动化测试并加入敏捷的持续集成流程中了
    1. 首先Yslow是基于Node.js的(Node.js此处不多作介绍,以后再另文详述。)首先需要安装node.js,目前最新版本是0.6.10,已集成npm(node pakage manager)

    以笔者的windows环境为例,执行
    C:\Program Files\nodejs>npm install yslow -g
    可以发现安装不成功,原因是Yslow的一个依赖包contextify在windows环境下编译不通过,需要找替代版本。
    如果是公司内网环境,有代理屏蔽之类的问题,也可直接下载好各依赖包手动安装
    http://search.npmjs.org/ 查询Yslow各依赖包并下载tgz文件
    通过执行 npm install ***.tgz 安装

    安装完成后,在windows环境上可以在node中执行相关模块代码执行Yslow测试
    $ node > require('fs').readFile('example.com.har', function (err, data) { var har = JSON.parse(data), YSLOW = require('yslow').YSLOW, doc = require('jsdom').jsdom(), res = YSLOW.harImporter.run(doc, har, 'ydefault'), content = YSLOW.util.getResults(res.context, 'basic'); console.log(content); }); { w: 98725, o: 89, u: 'http%3A%2F%2Fexample.com%2F', r: 9, i: 'ydefault', lt: 981 }

    对了,需要将待测的web页面先导出为har格式的文件(Http archive),可以通过firebox的netexport插件或者HttpWatch导出
    替换掉示例脚本中的har文件即可执行basic评估测试了
    测试类型可以是basicgradestat scompsall
    规则集一般用ydefault
    其他定义如下:
    ynumreqscore for Make fewer HTTP Requests
    ycdnscore for Use a Content Delivery Network(CDN)
    yemptysrcscore for Avoid empty src or href
    yexpiresscore for Add Expires headers
    ycompressscore for Compress components with gzip
    ycsstopscore for Put CSS at top
    yjsbottomscore for Put JavaScript. at bottom
    yexpressionsscore for Avoid CSS expressions
    yexternalscore for Make JavaScript. and CSS external
    ydnsscore for Reduce DNS lookups
    yminifyscore for Minify JavaScript. and CSS
    yredirectsscore for Avoid URL redirects
    ydupesscore for Remove duplicate JavasScript. and CSS
    yetagsscore for Configure entity tags (ETags)
    yxhrscore for Make AJAX cacheable
    yxhrmethodscore for Use GET for AJAX requests
    ymindomscore for Reduce the number of DOM elements
    yno404score for Avoid HTTP 404 (Not Found) error
    ymincookiescore for Reduce cookie size
    ycookiefreescore for Use cookie-free domains
    ynofilterscore for Avoid AlphaImageLoader filter
    yimgnoscalescore for Do not scale images in HTML
    yfaviconscore for Make favicon small and cacheable

    另一个工具PageSpeed

    PageSpeed和Yslow类似,但基于不同的规则集,包括移动网络的规则。同样也是打分机制
    PageSpeed的命令行比较简单,下载har_to_PageSpeed 工具,命令行执行即可输出结果 http://page-speed.googlecode.com/files/har_to_pagespeed.exe

    pagespeed还提供在线检测功能,对你提供的URL地址进行评估并给出得分

  • [论坛] UI界面规范,可作界面测试的参考

    2010-01-22 22:33:01

    UI色彩与字体

    1UI字体、色彩要一致

    2)整体色彩搭配要融为一体,起提示作用的部分要清楚醒目

    3)不可修改的字段,统一使用灰色文字显示

     

    窗口风格

    1)所有窗口最大化、最小化风格要一致

    2)报错页面的风格一致,最好有统一的报错页面

    3)类似功能的窗口打开的风格要一致

    4)相同功能在不同模块的名称要一致

    5)子窗体应尽量在显示在主窗体的左上或居中放置

    6)弹出式窗口尽量在不借助滚动条的情况下显示所有内容

    7)窗体最小化/最大化时,控件也要随着窗体而缩放

     

    布局

    1)窗体控件布局和间距尽量与Windows标准保持一致

    2)尽量采用Dock和锚点来让布局合理

    3)尽量让窗体中显示大部分常用功能

     

    菜单深度

    1)菜单深度一般不要超过三层

    2)菜单层次太多时应给出返回主窗口、主分支的快捷链接。

     

    按钮

    1)按钮风格相同,大小相似,字体一致

    2)无效按钮要屏蔽

     

    控件

    1)各复选框和选项框按选择几率的高低而先后排列

    2)复选框和选项框要有默认选项,并支持Tab选择

    3)界面空间较小时使用下拉框而不用选择框

    4)选项数较少时使用选项框,相反使用下拉列表框

     

     

    文本框输入

     

    必输项

    1)必输项中不可为空,不可输入空格

    2)必输项给出必输项标识(*

     

    字段长度

    超过数据库规定长度时不允许输入

     

    格式校验

    1)身份证号、E-MAIL等特定字段的格式要符合需求的规定

     

    日期格式

    1)日期显示格式一致,如 yyyy-mm-dd

    2)使用日期控件,尽量不是手工录入

     

    特殊字符

    1)输入区域输入特殊字符,插入数据库时不出错或提示不允许输入特殊字符。特殊字符包括:'"=~$%^%&#@

     

    英文输入

    英文输入不区分大小写,不可输入汉字、数字及特殊字符

     

    数值字段

    只能输入+ - 0~9及功能键(BackSpace 光标)

     

    字符字段

    1)如果支持日韩文字,则要判断全角假名/半角假名

     

    单行文本框/多行文本框

    1) 长度合适,可以容纳相应文字,但不能超过数据库该字段长度,最好将可以输入的最大字符数标在旁边。建议单行文本框中当输入的字符超过一定长度时再输入无效;对于多行文本框给出最大字符数标识

     

    附件

    1)可正常添加符合格式的附件

    2)附件可正常打开和保存,附件名较长时可正常操作

    3)直接输入错误的附件地址,保存时应给出提示信息

    4)附件打开/保存到本地时,文件名要显示原文件文件名

    5) 附件上传时应作格式和大小的检查,如果格式不对或者附件大小超过最大值,页面应有提示。页面上要有支持上传附件格式和大小的标识。

     

    密码输入

    1)需在需求中定义密码是否允许为空或空格;密码是否允许特殊字符;是否区分大小写,密码的可输入长度

    2)程序中应给出文字说明密码的可输入长度

     

    鼠标

    1)鼠标为不可点击状态时显示箭头,可点击状态显示手型;系统忙时显示沙漏形状

     

    光标定位

    1)打开新增(修改)页面时,光标初始定位在第一个待输入的文本区

    2)因输入不正确提示用户重新输入时,光标默认focus在出错的输入区,并高亮全选该错误输入

    3)若必输项未填写完毕就提交,应给出说明信息并能自动获得焦点

    4)可写控件检测到非法输入后应给出说明并能自动获得焦点

     

    TAB

    1)界面支持键盘自动浏览按钮功能。即TAB自动切换功能

    2Tab键的顺序与控件排列顺序要一致,一般情况下总体从上到下,同时行间从左到右的方式
  • 论坛上的话题PK:测试技术重要还是行业知识重要?

    2010-01-21 20:15:25

    就把测试工作做好本身而言,行业知识更重要
    测试是质量保证的手段,而测试本身是不能产生效益的。了解行业知识,才能把握好需求,才能更好地站在客户的角度看待问题,而建立在这个前提下,才有可能通过测试,最大程度地保证产品质量。仅仅通过对一些测试原理、基础的测试技术的掌握是不可能覆盖业务逻辑的

    引申个题外话,大家现在讨论何种自动化测试工具更好、要如何学习工具,其实也大可不必。是一样的道理,自动化测试本身也是手段,是一种工具,如何把测试思想、测试逻辑通过工具体现出来才是最重要的,掌握工具只是自己测试方式的延伸,是标而不是本。

  • 寻找合适的测试管理平台

    2010-01-20 17:32:18

    目前比较流行的商用测试管理平台有HP QC、Borland SilkCentral、rational RQM等,功能都比较全面,但具体到实际应用却不一定是最适合的。

    一个完善测试管理平台应该包含以下功能:

    1. 明确的权限管理,针对不同角色设定系统的不同操作权限

    2. 针对需求的管理、跟踪,并和后期的测试设计、Bug建立关联

    3. 针对测试对象的版本迭代管理

    4. 测试用例库管理

    5. 测试执行过程管理

    6. bug管理

    7. 统计分析报表

    8. 测试环境、资源管理

    9. 系统的维护(导入、导出、备份等)

    10. 工作日志平台

    11. 技巧、知识库

     

  • [论坛] 对测试工作进行度量

    2010-01-18 22:46:48

    测试工作的度量一直是测试管理的一个难点,我们如何衡量测试工作的质量呢?

    一般来说,衡量测试工作成效的KPI参数有如下几个:

    1.  工作时长

    2.  测试设计,测试用例数(自动化脚本代码行数)

    3.  发现故障数

    4.  输出的测试文档数(典型故障分析、测试报告、发布说明、系统使用说明等)

    5.  泄漏故障数

    6.  产品版本测试收敛度

    各部分的KPI比重如何分配?

    从测试工作的目的来看,首先必须要对测试通过的产品质量进行保证,而下游客户是产品质量的最终检验方,所以测试泄漏故障数和故障严重程度应该作为测试工作成效的首要度量KPI。

    其次,测试工作的主要目的是发现产品的故障,所以发现故障数应该作为第二KPI进行度量

    但是不同测试人员承担的测试任务不同,不同模块的故障分布也会不同,所以该KPI还应该和故障严重程度、所属模块的故障出现频度等进行综合考量

    第三主要的KPI应该测试收敛程度。

    任何版本的产品周期都是有限制的,留给系统测试的时间有限,故障如果不能尽快收敛,对产品的正常发布就会造成严重影响,所以必须要求重点功能优先测试,故障及早收敛。

    第四,测试设计

    测试用例是否充分决定产品测试过程中是否能够覆盖完全。所以测试用例数也是一个重要的KPI

    不过,完全通过数目衡量也不合理,测试用例的质量、用例细致程度等也需要有在度量时有一定的体现方式

    工作时长和总结、输出等工作量上的指标可作为辅助参考KPI指标。

  • QTP中页面的基本异常检查

    2010-01-18 22:44:56

    页面异常输入测试是系统测试的一个重要方面,但是因为比较繁杂,人工测试时往往难以完全覆盖,此时采用自动化测试,就有相当的优势了。

    如下图就是一个典型的信息录入页面

    其中就包括很多异常输入测试点:

    名称不能包含特殊字符,固定的电话格式,固定的手机格式,银行账号(必须全为数字),付费号码长度限制,手机号码格式、长度限制,Email格式限制等

     

    其实异常策略是有通用性的,现总结如下:

    1. exp@@SpecialChar(e_chr)     包含特殊字符,e_chr为指定的特殊字符

    2. exp@@StringLenMax(e_len)   字符串超过最大长度,e_len为最大长度值

    3. exp@@ StringLenMin(e_len)   字符串不足最小长度,e_len为最小长度值

    4. exp@@String                字符串包含数字(要求全字符)

    5. exp@@Num                 字符串包含字符(要求全数字)

    6. exp@@NumMax(e_max)    输入超过指定最大值,e_max,最大值

    6. exp@@NumMin(e_min)    输入不足指定最大值,e_mmin,最小值

    7. exp@@NumLenMax(e_len)    数值长度超限,e_len,长度最大值

    8. exp@@NumLenMin(e_len)    数值长度不足,e_len,长度最小值

    9. exp@@StringPre(e_pre)       字符串不为指定前缀,e_pre,前缀值

    10. exp@@NumPre(e_pre)       数值不使用指定前缀,e_pre,前缀值

    11. exp@@Email               数值不为标准Email格式

    12. exp@@Need               必输入项,提供空字符串

     

     

    具体实现上,在准备数据文件时,提供两种数据:

    1.      每个字段的默认输入值,即正确值。也是自动化程序执行时默认输入的数据

    2.      异常值,针对每个字段,提供该字段可能需要的异常策略,对所有异常进行遍历。

    第一行为默认值,第二行为字段对应的异常策略

     

    分三个函数来处理

    1.      执行函数

     

    Public Sub excep_OpUser()

                  routingname = "企业用户输入-异常测试"

                  载入数据表数据的第2

    GE_SetCurRow OppDataFile,"企业用户",2

                  Dim objStr,oScript,i

                  set bjStr = CreateObject("Scripting.Dictionary")

                  set Script. = CreateObject("Scripting.Dictionary")

                 

                  根据数据表字段设置每个字段的QTP执行语句

                  for i = 1 to DataTable.GetSheet("UserData").GetParameterCount

                         if DataTable.GetSheet("UserData").GetParameter(i)="企业名称" Then _

                                 objStr.add DataTable.value(i,"UserData"),".WebEdit("opername").set "

                         。。。。

                  Next

                 

                  调用异常数据生成函数,返回值保存在dictionary对象oScript

                  Gen_excepData(objStr,oScript)

                 

    依次对含异常策略的字段进行异常测试

                  For i = 0 to oScript.Count-1

                         Call OpUserSet(1,oScript(i))

                  Next

                 

                  set bjStr = Nothing

                  set Script. = Nothing

           End Sub

     

    2.      异常数据生成函数

     

    Public Function Gen_excepData(byval dObj,byRef oScript)

           异常值,正确值,异常类型,异常参数

    Dim errorValue,CorrectValue,expType,expPara

           Dim objName,scriptstr

           Dim i,j,expItem

           expItem = 0    记录异常数

           Randomize

          

           for i = 1 to DataTable.GetSheet("UserData").GetParameterCount

                  第一行数据为默认正确数值

                  CorrectValue = DataTable.GetSheet("UserData").GetParameter(i).ValueByRow(1)

                  datatable.SetCurrentRow 2

                 

                  if Instr(Datatable.value(i,"UserData"),"exp@@")>0 Then

                         objName = dObj.Item(Datatable.value(i,"UserData"))

                         同一字段多种异常策略的处理

                         arr1 = split (Datatable.value(i,"UserData"),"|",-1,1)

                         For j = 0 to Ubound(arr1)

                                获取异常类型和异常参数

    If RegExpTest("exp@@.{1,}\(.{1,}\)",arr1(j)) Then

                                       exptype = Mid(arr1(j),6,InStr(arr1(j),"(")-6)

                                       expPara = Mid(arr1(j),InStr(arr1(j),"(")+1,InStr(arr1(j),")")-InStr(arr1(j),"(")-1)

                                Else

                                       expType = replace(arr1(j),"exp@@","")

                                End If                  

                                不同策略对应的数据生成

                                select Case expType

                                Case "SpecialChar"

                                       errorValue = Replace(CorrectValue,Right(CorrectValue,1),"%")

                                       scriptstr = objName + chr (34) + errorValue + chr(34)

                                       expItem = expItem + 1

                                       oScript.add "excepData" & expItem,scriptstr

                                       errorValue = Replace(CorrectValue,Right(CorrectValue,1),"'")

                                       scriptstr = objName + chr (34) + errorValue + chr(34)

                                       expItem = expItem + 1

                                       oScript.add "excepData" & expItem,scriptstr

                                       errorValue = Replace(CorrectValue,Right(CorrectValue,1),"/")

                                       scriptstr = objName + chr (34) + errorValue + chr(34)

                                       expItem = expItem + 1

                                       oScript.add "excepData" & expItem,scriptstr

                                       errorValue = Replace(CorrectValue,Right(CorrectValue,1),":")

                                       scriptstr = objName + chr (34) + errorValue + chr(34)

                                       expItem = expItem + 1

                                       oScript.add "excepData" & expItem,scriptstr

                                       errorValue = Replace(CorrectValue,Right(CorrectValue,1),"*")

                                       scriptstr = objName + chr (34) + errorValue + chr(34)

                                       expItem = expItem + 1

                                       oScript.add "excepData" & expItem,scriptstr

                                       errorValue = Replace(CorrectValue,Right(CorrectValue,1),"&")

                                       scriptstr = objName + chr (34) + errorValue + chr(34)

                                       expItem = expItem + 1

                                       oScript.add "excepData" & expItem,scriptstr

                                       errorValue = Replace(CorrectValue,Right(CorrectValue,1),"?")

                                       scriptstr = objName + chr (34) + errorValue + chr(34)

                                       expItem = expItem + 1

                                       oScript.add "excepData" & expItem,scriptstr

                                       errorValue = Replace(CorrectValue,Right(CorrectValue,1),"""")

                                       scriptstr = objName + chr (34) + errorValue + chr(34)

                                       expItem = expItem + 1

                                       oScript.add "excepData" & expItem,scriptstr

                                       errorValue = Replace(CorrectValue,Right(CorrectValue,1),"<")

                                       scriptstr = objName + chr (34) + errorValue + chr(34)

                                       expItem = expItem + 1

                                       oScript.add "excepData" & expItem,scriptstr

                                       errorValue = Replace(CorrectValue,Right(CorrectValue,1),">")

                                       scriptstr = objName + chr (34) + errorValue + chr(34)

                                       expItem = expItem + 1

                                       oScript.add "excepData" & expItem,scriptstr

                                       errorValue = Replace(CorrectValue,Right(CorrectValue,1),"|")

                                       scriptstr = objName + chr (34) + errorValue + chr(34)

                                       expItem = expItem + 1

  • QTP中时间的处理

    2010-01-18 22:43:34

    自动化测试中,经常遇到页面需要输入时间,而这个时间很多时候是当前时间之后某个范围之类才有效。我们采用数据驱动时如果采用绝对时间,则数据复用性就很差了,数据需要经常修改。所以采用相对时间

     

    下面的函数用于获取相对时间

    '------------------------------------------------------------------------

    '获取以当前时间为参照的偏移时间

    'increTime: 偏移时间量,可使用负数 格式:day:hour:min:sec  如 1:3:8:23

    '------------------------------------------------------------------------

    Public Function GetTime(byval increTime)

           Dim y,m,d,h,n,s,timeArray

          

           timeArray = split(increTime,":",-1,1)

           d= timeArray(0)

           h= timeArray(1)

           n= timeArray(2)

           s= timeArray(3)

          

           GetTime = dateadd("d",d,now)

           GetTime = dateadd("h",h,GetTime)

           GetTime = dateadd("n",n,GetTime)

           GetTime = dateadd("s",s,GetTime)

          

           ' change to GE Time type

           Dim dateArr,timeArr

           timeArray = split(GetTime," ",-1,1)

           dateArr = split(timeArray(0),"-",-1,1)

           y = dateArr(0)

           m = ExpandByZero("L", dateArr(1),2)

           d = ExpandByZero("L", dateArr(2),2)

          

           timeArr = split(timeArray(1),":",-1,1)

           h = ExpandByZero("L", timeArr(0),2)

           n = ExpandByZero("L", timeArr(1),2)

           s = ExpandByZero("L", timeArr(2),2)

          

           GetTime = y  & "-" & m & "-" & d & " " & h & ":" & n & ":" & s

     

    End Function

    '------------------------------------------------------------------------

    '以0扩展当前字符串

    'way: 扩展方式 L-左扩,R-右扩

    'OrigStr: 原字符串

    'HopeLen: 扩展后字符长度

    '------------------------------------------------------------------------

    Public Function ExpandByZero(byval way,byval OrigStr,byval HopeLen)

       Dim i,ZeroStr

       ZeroStr = ""

       For i =1 to HopeLen - len(OrigStr)

                  ZeroStr = ZeroStr & "0"

       Next

       If way = "L" Then

                  ExpandByZero = ZeroStr & OrigStr

           elseif way = "R" Then

                  ExpandByZero = OrigStr & ZeroStr

           else

                  Exit Function

       End If

    End Function

  • QTP中类的基本使用方法

    2010-01-18 22:39:32

    对于共同开发的自动化测试项目,实例方便的调用是很重要的。QTP采用的是vbscript脚本,所以也支持类,但是应为vbs并不支持类的继承,所以只能算作一种“拟类”。采用类对脚本进行封装,有很多好处,对于测试执行人员,可以通过项目情况对封装的类进行调用,而并不必关心类实现的细节。

    此处对QTP类的使用进行一些总结。

    '类名称

    Class TestCase

           Private DataFile

          

           ' ----用例预置条件

           Private Function CasePrepare()

                 

           End Function

          

           ' ----测试数据输入

           Public Function CaseData(byval RowNum)

                 

           End Function

          

           ' ----测试执行

           Public Function CaseRun()

                 

           End Function

          

           ' ----测试结果检查

           Public Function CaseCheck()

                 

           End Function

          

           '获取测试用例号

           Public Property Get CaseID()

                  CaseID = "TestCase_0001"

           End Property

          

           '获取测试用例名称

           Public Property Get CaseName()

                  CaseName = "用户登录"

           End Property

          

           '----构造函数----

           Private Sub Class_Initialize() 

                  DataFile = "C:\autotest\data.xls"

                 

                  Call CasePrepare()

        End Sub

          

           '----解构函数----

           Private Sub Class_Terminate()

                 

           End Sub

     

    End Class

     

    其中Class_initialize为构造函数,类初始化时调用,此处预设了数据文件,并在此处调用了用例预置函数。

    Class_Terminate为解构函数,一般用于释放类执行过程种占用的内存等

    Property Get用于获取类的属性,此处获取该测试用例类的ID,和名称属性

     

    模拟测试用例,类中包含了测试用例的几个部分:

    CasePrepare 测试预置条件,如测试用户登录,此处可以判断登录界面是否已经显示

    Casedata: 测试数据准备,如测试用户登录,此处可以载入登录用户、登录密码等数据

    CaseRun:测试执行,如测试用户登录,此处可以执行输入验证码,点击登录按钮等操作

    CaseCheck:执行结果检查,如测试用户登录,此处可以对登录结果进行检查,如页面是否正确跳转,如用户、密码不对,是否正确显示提示信息等。

     

    具体在QTP中的使用如下:

    Dim CaseLogin

    Set CaseLogin = New TestCase

    CaseLogin.CaseData 2 载入数据文件中的第2行数据作为测试输入

    CaseLogin.CaseRun

    If CaseLogin.CaseCheck Then

      Case_LogInfo “测试用例 ”CaseLogin. CaseID & “测试通过!”,MicPass

    Else

    Case_LogError “测试用例 ”CaseLogin. CaseID & “测试失败!”,MicFail

    End If

  • <原创>一个批处理执行Test的VBS脚本

    2007-08-03 10:35:04

    BatchRun.vbs(转载请注明出处)

    同目录下需存在runlist.txt文件,保存需要批量运行的test路径,形如:

    c:\autotest\test1
    c:\autotest\test2

    ------------------

    On Error Resume Next
    error.clear
    Dim qtApp
    Dim qtTest
    Dim qtResultsOpt
    Dim fso, MyFile,TestName
    Const ForReading = 1, ForWriting = 2

    Set WshShell = CreateObject("Wscrīpt.Shell")
    WshShell.Popup "开始批量执行自动化测试脚本!", 3, "my AutoTest", 0 + 64

    Set qtApp = CreateObject("QuickTest.Application")
    qtApp.Launch

    qtApp.Visible = True
    qtApp.Options.Run.RunMode = "Fast"
    qtApp.Options.Run.ViewResults = False

    Set fso = CreateObject("scrīpting.FileSystemObject")
    Set MyFile = fso.OpenTextFile(".\RunList.txt", ForReading, True)
    Do While MyFile.AtEndOfStream <> True
     TestName = MyFile.ReadLine

     qtApp.Open TestName, True
     Set qtTest = qtApp.Test
     qtTest.Settings.Run.OnError = "Dialog"
     
     Set qtResultsOpt = CreateObject("QuickTest.RunResultsOptions")
     qtResultsOpt.ResultsLocation = TestName &"\AutoRes"
     
     qtTest.Run qtResultsOpt, True
     qtTest.close
     wait 1
    Loop

    MyFile.Close
    qtApp.Quit

    MsgBox "自动化测试脚本执行完毕!脚本测试结果存放在各自的AutoRes目录下,请用QTP result工具查看"

    Set fso = Nothing
    Set qtResultsOpt = Nothing  
    Set qtTest = Nothing 
    Set qtApp = Nothing
    Set WshShell = Nothing

Open Toolbar