记录阿里巴巴QA架构组成长点滴。2008年关键词为效率,技术,影响力!QA/测试架构师定义:开发和设计测试框架测试库;纵横全局的考虑产品的功能,设计复杂的测试系统;负责研发某一项特定的测试技术;为公司考虑如何提高测试效率。领导公司测试技术的发展和测试策略上的方向,关注整个公司的测试部门的问题,前瞻性的考虑未来的版本的测试策略和技术。测试架构师计划/设计测试平台,关注着产品的测试过程,提供咨询服务,影响到公司内的测试机构测试社区,以及开发机构等,对产品各个方面施加深远而正确的影响,最终提高整体软件质量。

发布新日志

  • php 执行linux 命令

    2008-12-10 19:23:54

    by leshui

    dargoon项目,自动化跑测试用例

    ini_set("display_errors", "On");
    error_reporting(E_ALL);
    include_once("lib.test.php");
    $lib=new libtest();
    $lib->db_conn();
    //测试时间段角本;
    $array_case=file("testcase/time_case.txt");
    //$array_case[0]="'sssss'";
    $sql="select * from device_service where dev_service_id=6";
    $array_db=$lib->getall($sql);
    $sc_name=$array_db[0]["scrīpt_name"];
    echo $sc_name."------------------------------------";
    $logname="log_".time().".log";$al_lgos="";
    foreach ($array_case as $k=>$case){
     $al_lgos="";
     //修改数据库
     $upsql="update device_service set run_time_range=\"".trim($case)."\" where dev_service_id=6 limit 1";
     $lib->db_excute($upsql); 
     sleep(1);
     //执行 agent ====================================
     exec("/home/qjy/src/agent/aliprobe -d /home/qjy/src/agent/cps/ -a 0.0.0.0:7777 -m 10.2.6.21:6000 -i 1 -v3 --debug  > sagent.txt &");
     sleep(10);
     //kill agent ===================================
     exec("netstat -nlp > test.txt ");
     sleep(2);
     $array_agent=file("test.txt"); 
     //根据端口号 0.0.0.0:7777  kill 线程
     foreach ($array_agent as $k1=>$v1){
      if (ereg("0.0.0.0:7777",$v1)){
       if (ereg ("([0-9]{1,10})/python", $v1, $regs)){
        $pid=$regs[1];
        exec("kill -9 ".$pid);
        sleep(1);
       }  
      }
     }
     sleep(2);
     //分析日志 =======================================
     //是否存在 $sc_name
     $al_lgos.=$case." ==============================      \r\n";
     $array_agent_logs=file("sagent.txt");
     $err=0; $ok=0; $check=0; $error_lgos="";
     foreach ($array_agent_logs as $keys=>$agent_logs){
      if (ereg($sc_name,$agent_logs)){
       //$al_lgos.="已检测试到".$sc_name." ||||| ".$agent_logs." \r\n";
       if (eregi("Loading check: ".$sc_name,$agent_logs)){
        //存在 说明发送成功
        //eregi("(Loading check: ".$sc_name.").*?",$agent_logs,$args);   
        $al_lgos.="发送成功 "." ||||| ".$agent_logs."\r\n";
        $ok=1;   
       }
       $check=1;
      }
      
      if (eregi("ERROR",$agent_logs)){
       $error_lgos.="**********错误 **************:"." ||||| ".$agent_logs." \r\n";
      }
      
     } 
     
     if ($check==0){
      $al_lgos.="====未检测试到====".$sc_name." \r\n";
     }
     if ($ok==0){
      $al_lgos.="----------角本".$sc_name." 没有发送成功--------- \r\n";
     }
     $al_lgos.=$error_lgos;
     $al_lgos.=" end ======================================== \r\n"; 
     $al_lgos.="\r\n";
     
     //输出分析日志 =======================================  
     $handle = fopen("analysis/".$logname, 'a');
     fwrite($handle, $al_lgos);
     fclose($handle);
     //break;
    }

  • ruby正则表达式快速指南

    2008-12-09 09:28:43

    by jiale

    [abc]        A single character: a, b or c
    [^abc]      Any single character but a, b, or c
    [a-z]        Any single character in the range a-z
    [a-zA-Z]   Any single character in the range a-z or A-Z
    ^             Start of string
    $             End of string
    (...)         Capture everything enclosed

    .             Any single character
    \s           Any whitespace character
    \S           Any non-whitespace character
    \d           Any digit
    \D           Any non-digit
    \w           Any word character (letter, number, or underscore)
    \W          Any non-word character

    (a|b)       a or b
    a?           Zero or one of a
    a*           Zero or more of a
    a+           One or more of a
    a{3}       Exactly 3 of a
    a{3,}      3 or more of a
    a{3,6}    Between 3 and 6 of a

  • 阿里巴巴集团部分技术BLOG

    2008-12-07 17:31:05

      阿里人才济济,越来越多的技术专家在infoq上露面,也有很多的BLOG 生根发芽:)

    数据库与数据仓库

    http://rdc.taobao.com/blog/dw/

    http://rdc.taobao.com/blog/dba/

     http://www.dbanotes.net

    http://blue-prince.spaces.live.com/

    http://WWW.ALIDBA.NET/

    http://www.orawh.com/

    (biti_rainy)  http://space.itpub.net/3505/

     http://www.hellodba.net/

    http://www.jianzhaoyang.com/

     

    http://xujt82.spaces.live.com/

    http://www.ningoo.net/

    http://hutuworm.blogspot.com/

    前端研发

    http://ued.taobao.com/blog/

    http://www.aliued.cn/

    http://ued.alipay.com/

    http://www.alisoftued.com/

    http://ued.koubei.com/

    JAVA研发

    http://rdc.taobao.com/blog/arch/

    http://www.blogjava.net/BlueDavy/archive/2008/11.html


     http://blog.csdn.net/yzhz/category/24108.aspx

    http://blog.csdn.net/cenwenchu79

                  http://www.blogjava.net/cenwenchu/

    http://davyyew.blogbus.com

     http://www.esbzone.net/

     http://amoeba.meidusa.com/wordpress/?p=14

    http://www.alinotes.cn/

    http://www.blogkid.cn/

    安全

    http://blog.csdn.net/kj021320

    http://blog.ph4nt0m.org/

    Linux C

    QA

     http://fafeng.blogbus.com/

    http://rdc.taobao.com/blog/qa/

    http://nmtcolin.itpub.net/category/5135/31300

  • [论坛] 并发用户数与think time

    2008-11-30 23:10:32

    by jack

    有位同学问道:1用户每秒发一次请求,一分钟计60次请求;4用户每4秒发一次请求,一分钟计也是60次请求,从请求的处理量上来看是完全一样的,那么还有什么区别呢?

    问题所举的例子中,不同的请求方式模拟出不同的效果:1用户的情况是第一秒1个请求,第二秒1个请求,第三秒还是1个请求……4用户的情况是第一秒4个请求,第二秒0个请求,第三秒是0个请求,第四秒是0个请求,第五秒又是4个请求……

    上面这样描述可能不太好理解,打个不是很恰当的比方来说明吧:

    比如我有10袋净重25kg的水泥,甲每次能背1袋,分10次全部从仓库背到工地,每次5分钟,总共50分钟搞定;乙每次能背2袋,分5次全部从仓库背到工地,每次10分钟,总共也是50分钟搞定。从结果上看,都是50分钟搞定10袋水泥;但是如果让我们说谁的力气大呢?毫无疑问大家都会说是乙。

    同样的评估并发性能也是如此,如果要评估的系统是支持多用户请求并行处理的(如web系统),就必须要注意这个问题。

  • web系统单用户与多用户请求的区别

    2008-11-30 22:58:22

    by jack

    前几天在某个技术分享会上,有人问起:单用户请求与多用户请求到底有什么区别?

    这是一个比较泛的问题,涉及面其实是比较多的,也是很多人都感到比较模糊的问题。

    从请求处理的各个环节来分析,涉及到的有网络连接、应用程序线程处理、操作系统线程处理。

    从网络连接上来说,当单个用户连接被复用时,其实tcp连接只建立了一次,之后通过连接保持一致使用当前连接;而4个用户发出请求时若连接未被复用,则出现建立多个连接的情况。主要是受web server的连接设置keep alive影响。

    应用程序线程处理就比较复杂:主要是多线程处理的机制,对于新用户的请求如果是创建新线程来处理,则每增加一个用户就会增加一个线程。

    还有一个层面就是操作系统的线程处理,也是主要取决于多线程处理的机制。

    具体各种情况的处理将会在今后的博文中逐一介绍。

  • [论坛] 并发用户数与单位时间事务数

    2008-11-30 22:10:53

    by jack

    近日听到有人提及性能测试的并发用户数,言及之时总以“每秒多少多少并发用户”云云,而提到“每秒事务数”时又无法弄清楚其与所谓“每秒并发用户数”的关系。

    其实“并发用户数”与“每秒事务数”是性能数据中不同性质的名词,没有直接关系。“并发用户数”针对的是时刻,比如我查看上午8时31分32秒这个时刻的在线人数是23,这个23就是这一时刻的“并发用户数”;而我提取31分到35分这5分钟的访问量是600,那么每秒平均事务数就是2了。

    但是“并发用户数”与“每秒事务数”也不是完全割裂的。

    比如有20个并发用户,每个用户4秒钟做一次访问,那么1分钟里每个用户访问15次,20个并发用户就做了300次,每秒平均事务数就是5。

    一般来说,当用户操作的样本数量足够多的时候,用户表现的操作会体现出规律与一致性,假设用户表现因子为α,可以近似的认为每秒事务数tps与并发用户数nu之间为一元关系

    tps=α×nu

    正确认识并发用户数和每秒事务数,是做好性能测试的充要条件。

  • 性能测试的问题分析和总结

    2008-11-28 23:52:29

     by qjy

    转载请保留:本文出自qaarchitech的51Testing软件测试博客:http://www.51testing.com/?170805


       
    今天给部门做了性能测试分享,内容讲的比较泛泛,人还有点小紧张,还需要多学习怎么分享才能取到好的效果,现在仅摘其中的一部分,分享出来,内容不一定全面~~仅作交流

    常见的性能问题

    1.最重要的性能问题是应用程序设计及与数据库的交互 
        应用程序设计:好的应用程序设计可能会获得优秀的响应时间(但不能确保),但差的应用程序设计很难获得好的性能。差的性能设计比如:不管怎么操作,让用户检索出大量结果集(比如50M)的程序运行效率不会高,大量数据的延迟会很明显。
    2.
    数据库设计
      
    物理和逻辑设计,涉及非常多的方面,俺也不懂,举一个简单的例子:一个测试问题,大数据量下列表展现(多表联合查询)问题不能满足性能需求。DBA修改了数据库设计采用汇总表去展现列表(单表查询),汇总表也方便创建索引。
    3.
    参数调整
    4.
    硬件环境(包括网络对性能的影响会比较大)

    5.
    其他,因素很多。

    就几个常见的性能问题,举例展开,性能问题非常多,也总结不全面,但可以经常回顾,分类汇总,逐步完善性能问题总结这部分工作。

    转载请保留:本文出自qaarchitech的51Testing软件测试博客:http://www.51testing.com/?170805

    一、数据库交互过多

    Ø       现象:单个操作发送给数据库sql的数据量过多,数据库延迟。

    Ø       发现方法:采用监控工具分析程序与数据库的交互(sql数量和响应时间),比如P6spy及类似工具。

    Ø       数据库交互与程序设计方式息息相关

    建议使用P6spy帮助去做数据库交互分析,截获页面操作的sql。P6spy使用具体请参考
    http://dodomail.javaeye.com/blog/117934
    http://blog.csdn.net/hennylee/archive/2007/03/07/1523410.aspx
    http://www.blogjava.net/itstarting/articles/48969.aspx

    二、列表效率低

    Ø       列表查询未使用索引。

    Ø       查询全部字段,而不是所需字段,带来额外的I/O和网络负担。

    Ø       分页算法效率低,甚至未使用分页。

    1.查询未使用索引
    此问题比较常见,通过查看sql的执行时间和I/O。查看查询计划可以清楚看出sql是否索引查询,或者全表扫描
     select  ID 
    。。 from B   where xxx        
    2.
    比如 Select xxx  from  where  UPPER(name)
    A
    在字段上使用函数,导致不使用索引,虽然Oracle是有基于函数的索引。更好的方式  a.update现有数据  b.改程序,直接改存储模式为大写的数据。
    3.冗余字段的优化
     select 
    。。。    from A   where 。。。。比如 where 条件查询的字段的长度较大,创建索引效果后不明显,考虑增加了冗余的字段,进行标识,结合在冗余字段上创建索引会比较快。
    4.
    分页算法,遇到的状况也比较混乱。。。。。好的分页算法要推广,公用。

    三、查询结果集过大

    Ø       返回全部的数据(建议从业务角度出发,分析返回全部的数据是否必要)

    Ø       空查询(默认条件查询)

    Ø       不规范的查询(where 11

    1.查询结果集(建议从业务角度优化系统)
    建议参考淘宝的一篇帖子
    http://rdc.taobao.com/blog/dba/html/187_optimize_from_business.html
    2.
    空查询(默认查询造成压力比较大,其实空查询可能是没有必要的)
    建议页面增加默认过滤条件
    3.Where 1
    1
    a、性能上的影响(可能会影响orale的查询计划)

    b、安全性的影响
    create table A tablespace tbs_temp as
      select * from B where 1<>1
    create table A
      as  select * from B where 1<>1
    Sybase
    不支持这样的语法,但是有:
    select * into A from B where 1 <> 1
    where 1 <> 1
    ,复制表的结构,但注意这样没有主键
    4.
    不规范的查询sql很多,建议多参考部门的相关规范,从规范的角度出发去发现问题。

    四、复杂查询sql (大数据量测试)

    Ø       复杂查询sql一定在大数据量下进行测试

    Ø       结合操作和sql本身效率进行测试。

    Ø       建议多与DBA配合

    如果你只使用小表进行测试(比如小于100条数据),那么在真实数据下会异常缓慢直至停滞。Sql的例子就不列出了,比较多,通常对于多表联合查询,复杂的sql都要在大数据量下测试。其实越复杂的东西越难维护和优化,建议对系统中复杂的sql都记录下来,可能是性能隐患。

    转载请保留:本文出自qaarchitech的51Testing软件测试博客:http://www.51testing.com/?170805

    五、数据库连接池

    Ø           未使用连接池,应用程序在建立数据库连接上消耗的时间较长,影响性能效率。

    Ø           连接池配置参数不当(通过测试确定合适的值)

    六、并发事务处理和死锁问题

    Ø         程序对事务并发处理上的错误。

    Ø         资源争用引起锁阻塞和死锁。

    Ø         SYBASE的锁模式为行锁,可以减小死锁发生的可能性。

    死锁或者锁阻塞,如何检查锁阻塞的大致步骤
    比如mysql 为例子
    1.Show  processlist
    ,查看有locked的进程
    2.
    查看阻塞进程执行的sql
    3.
    关掉程序,或者杀死进程,解掉死锁,不建议杀死进程,可能导致不完整的数据。

    4.
    查看sql问题,单独确认问题
    5.
    优化sql或者查程序问题

    还以一个实际问题中,sybase锁阻塞的例子
    环境维护发现锁阻塞,发现很慢,检查到有问题的sql
    1. sp_lock
    看到死锁

    2.
    查看阻塞进程信息
      
    select
      *  from  master..sysprocesses  where ipaddr =XXXX
    3.
    造成锁阻塞的进程是spid  1   2
    使用dbcc
      traceon(3604)
    dbcc sqltext(1)
    dbcc sqltext(2)
    查看到进程执行的sql
    select * from View
    (视图)   where ID = null (未列出原sql,仅举个例子)

    4.
    关掉程序,杀死进程,解掉死锁
    单独使用sql adv连接数据库,执行该sql,很慢。
    查看创建View的语法,sybase可以使用sp_helptext View,可以看到建视图的大致的sql
    create view
      as select xxxx   from A ,B  where A.ID*=B.ID and A.C=10
    查看sqlI/O和执行时间 set
      statistics time,io on,查看到sql具体的执行时间和I/O
    5.
    简单看了一下,试着在C字段上增加了索引

    再查询响应时间变小了和查询计划变了,有问题的就是这个查看视图的sql,可能是资源争用造成了死锁。

    七、页面过大,网络延迟

    Ø         页面中图形多且大

    Ø         使用比较大的控件等等

    Ø         建议参数WEB前端性能优化,推荐Yslow工具

    中国雅虎有相关使用Yslow的一个很好的ppt。建议参考,帖子可以看看,推荐《高性能网站建设指南》http://www.cnblogs.com/JustinYoung/archive/2007/11/20/speeding-up-web-site-14rule.html
    http://www.cnblogs.com/JustinYoung/archive/2007/11/28/speeding-up-web-site-yslow.html

    八、内存溢出、应用终止、服务器宕机等严重问题

    Ø       批量对数据进行操作,会返回大量数据给应用服务器占用了较多的应用服务器的内存,可能会导致应用服务器内存溢出。

    Ø       消耗服务器某种资源过多的操作可能会使服务器出现宕机和应用终止的情况。

    Ø       检查应用程序日志和操作系统的日志或者core文件

    九、参数调整和日志级别设置

    服务器的参数调整不合理。完善性能环境检查的各种checklist
    生产环境中日志级别应当设置的较高,不打印出sql语句和调试信息,额外的I/O会降低性能效率。

  • 软件需求分析使用的工具描述

    2008-11-24 20:03:16

    转载请保留:本文出自qaarchitech的51Testing软件测试博客:http://www.51testing.com/?170805

    1)原型设计模型工具交互原型设计软件 Axure RP Pro 5

    Axure RP 能帮助网站需求设计者,快捷而简便的创建 基于目录组织的原型文档、功能说明、交互界面以及带注释的wireframe网页,并可自动生成用于演示的网页文件和word文档,以提供演示与开发。
    Axure RP 的特点是:快速创建带注释的wireframe文件,并可根据所设置的时间周期,软件自动保存文档,确保文件安全。在不写任何一条html与javascrīpt语句的情况下,通过创建的文档以及相关条件和注释,一键生成html prototype演示。根据设计稿,一键生成一致而专业的word版本的原型设计文档。

    2)StarUML工具

    可绘制9款UML图:用例图、类图、序列图、状态图、活动图、通信图、模块图、部署图以及复合结构图等。
    完全免费:StarUML是一套开放源码的软件,不仅免费自由下载,连代码都免费开放。
    多种格式影像文件:可导出JPG、JPEG、BMP、EMF和WMF等格式的影像文件。
    语法检验:StarUML遵守UML的语法规则,不支持违反语法的动作。
    正反向工程:StarUML可以依据类图的内容生成Java、C++、C#代码,也能够读取Java、C++、C#代码反向生成类图。

    转载请保留:本文出自qaarchitech的51Testing软件测试博客:http://www.51testing.com/?170805

    3)Visio 工具

    Microsoft visio 可以建立流程图、组织图、时间表、营销图和其它更多图表,把特定的图表加入文件,让商业沟通变得更加清晰,令演示更加有趣。

    4)FreeMind 工具 思维导图软件

    Freemind是一实用的开源思维导图/心智(MindMap)软件.它可用来作为管理项目(包括子任务的管理,子任务的状态,时间记录,资源链接管理),笔记或知识库,文章写作或者头脑风暴,结构化的存储小型数据库,绘制思维导图,整理软件流程思路。
  • Spirng ibatis web 简单示例

    2008-11-24 19:20:13

    1)
    创建web工程
    spring-test工程文件
    2)
    需要jar包支持
    Spring-web.jar
    Spring-webmvc.jar
    Spring.jar
    Commons-io.jar
    Log4j.jar
    Commons-dbcp.jar
    Commons-lang.jar
    Commons-pool.jar
    Ibatis.jar
    Mysql-connector-java.jar
    3)
    创建配置文件

    文件名 web-inf
    描述
    web.xml
    Spring 配置加入

    <context-param>


    加载
    /WEB-INF/applicationContext.xml


    <servlet>
    接收mvc分发

    org.springframework.web.servlet.DispatcherServlet
    <param-value> /WEB-INF/roadrantz-servlet.xml


    <servlet-mapping> 对应的结尾名


    <url-pattern>*.do</url-pattern>


    监听器
    加载spring上下文
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>


    applicationContent.xml

    加载属性文件
    <
    bean id="propertyConfigurer"

    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">


    加载数据源文件
    <
    bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">


    关联ibatis
    class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">


    <property name="dataSource" ref="dataSource" />


    <property name="configLocation" value="/WEB-INF/roadrantz-ibatis.xml" />



    </bean>



    Spring-servlet.xml

    Mvc mapping对应文件applicationContent.xml加载过
    <
    bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">


    <prop key="/home.do">homePageController</prop>
    加载bean
    <
    bean id="homePageController" class="com.roadrantz.mvc.HomePageController" >


    <property name="sqlDao" ref="sqlDao"/>


    </bean>




    Spring-ibatis.xml

    加载 ibatis 配置文件,本文件在
    applicationContent.xml


    对应模板文件
    <
    bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">



    <property name="prefix">



    <value>/tpl/</value>



    </property>





    <property name="suffix">



    <value>.jsp</value>



    </property>



    </bean>
    <
    sqlMapConfig>



    <sqlMap resource="com/roadrantz/entity/testst.xml" />



    <sqlMap resource="com/roadrantz/entity/testst_msbv.xml" />


    </sqlMapConfig>
    Jdboc.properties

    jdbc.driverClassName = org.gjt.mm.mysql.Driver


    jdbc.password
    =
    admin


    jdbc.url
    =
    jdbc:mysql://localhost/mspring?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8


    jdbc.username
    =
    root






    4)
    创建java文件
    文件
    描述
    HomePageController
      需要
    extends SimpleFormController
    默认找 handleRequestInternal 方法

    Test
    实体文件,对应数据test属性值

    Test.xml

    Ibatis配置文件,对应 class和数据表文件配置
    <sqlMap namespace="test">



    <resultMap class="com.roadrantz.entity.Test" id="result">


    <result property="id" column="id" jdbcType="Integer"/>



    <result property="name" column="name" jdbcType="VARCHAR" />



    </resultMap>



    <select id="getAllTests" esultMap="result">



    select * from Testst



    </select>


    </sqlMap>
    Dao执行文件

    public List getAll() {



    return
    this.getSqlMapClientTemplate().queryForList("getAllTests", null);



    }


    Web-inf/tpl/

    模板文件
    return new ModelAndView("home","rants","test==========");
    对应文件名



    5)目录文件结构
    Project_test
      Src

         Com.test.dao

            SqlMapTestDao.java
         Com.test.dao.Impl

            SqlMapTestDaoImpl.java

        Com.test.dao.entity

            Test.java

        Test.xml

      WebContent

         Tpl/
            Home.jsp
          WEB-INF/

              Lib/
                 Spring-web.jar

    Spring-webmvc.jar
    Spring.jar
    Commons-io.jar
    Log4j.jar
    Commons-dbcp.jar
    Commons-lang.jar
    Commons-pool.jar
    Ibatis.jar
    Mysql-connector-java.jar

    Web.xml


    applicationContext.xml


    jdbc.properties


    log4j.properties


    spring -ibatis


    spring-servlet.xml

  • kill process(ruby)

    2008-11-24 09:35:52

    def kill_process(name)
            begin
              wmi = WIN32OLE.connect("winmgmts://")
              processes = wmi.ExecQuery("select * from win32_process where name='#{name}'")
              for process in processes
                process.terminate()
                sleep 0.2
              end
            rescue => err
              $LOG.fatal(err)
              raise err
            end
          end
  • bat获取ruby安装路径

    2008-11-24 09:19:50

    picassoWR的install程序希望在ruby安装完成后,获取ruby的安装路径并写入到path环境变量中,bat可以通过REG QUERY方法获取ruby的安装路径

    for /f "skip=4 tokens=1,2 delims=:" %%a in ('reg query HKLM\SOFTWARE\RubyInstaller /v Path') do (

      set RubyPathL=%%a

      set RubyPathR=%%b

    )
    set RubyPath=%RubyPathL:~-1%:%RubyPathR%

    将RubyPath写入Path环境变量,bat需要通过更新注册表的方式更新path环境变量

    REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v path /t REG_SZ /d "%PATH%" /f

  • 批处理抓取页面中图片对象

    2008-11-23 20:37:59

    By Wiston Li

    watir底层中很多集合类代码如:buttons, divs, links, spans等等,方便用户用each方法来枚举。

    例如下面代码,把所有image生成保存到本地。

    require 'watir'
    browser = Watir::IE.new
    browser.goto('http://twitter.com')
    
    idx = 0
    browser.images.each do |x|
      idx += 1
      location = 'c:\tmp\file-' + idx.to_s + '.jpg'
      x.save(location)
    end
    
  • 扩展watir底层,调用visible返回对象是否可见

    2008-11-23 20:31:08

    By Wiston Li

    在用developer toolbar inspect一个对象时,属性display= none or visibility= hidden 或其父对象是hidden时,此对象在页面上显示是invisible的。

    下面的方法扩展element类,并修复1.5.6bug,在写watir脚本时,即可调用object.visible?方法.

     

    class Watir::Element

     
      def visible?
     
        ōbject = document
        while object
          begin
            if object.currentstyle.invoke('visibility') =~ /^hidden$/i

              return false
            end
            if object.currentstyle.invoke('display') =~ /^none$/i

              return false
            end
            if object.invoke('isDisabled')
              return false
            end
          rescue WIN32OLERuntimeError
          end
          ōbject = object.parentElement
        end
        true
      end
    end

    watir脚本:

    require 'watir'
    include Watir

    ie = IE.new
    ie.goto("www.someplace.com")
    button = ie.button(:id, 'somebutton')
    if button.visible? '调用visible方法
      button.click
    else
      ie.close
    end

     

  • 获取选择框页面对象的value值

    2008-11-23 19:50:14

    By Wiston Li

    在对页面中选择框对象进行操作时,页面显示的对象对应其item属性,如:checkbox, radiobox,select list等,但程序逻辑判断处理时,实现上是取item对应的value值,那么watir自动化脚本时,如何取到相应的value?

    页面代码:

     <input type="radio" name="email_frequency" value="daily">Daily Email</
    input>
     <input type="radio" name="email_frequency" value="weekly">Weekly
    Email</input>
     <input type="radio" name="email_frequency" value="monthly">Monthly
    Email</input>

    watir脚本:

      def get_values_by_name(name)
        value_list = []
        @browser.document.getElementsByName(name).each do |el|
          value_list << el.attributes('value').value
        end
        return value_list
      end

    用上述方法即可访问到value。但其调用getElementsByName,会访问到所有对象,后续,将研究一下@o.invoke来试试,直接封装到底层,只是针对某个web对象来操作.扩展watir功能。

  • watir自动化测试结果报告输出

    2008-11-23 18:47:22

    By Wiston Li

    我们知道,ruby安装好后,其gem包已经安装log4r,在开发watir自动化脚本时可以引用,非常方便

    代码问题定位,log定制,异常栈输出。但是针对用例执行时对于检查点与步骤信息,可以用HTML加简单CSS

    友好显示输出结果,不过,要想做到很强大,最终还是要写到数据库中,方便查询和统计。

    引用代码:

    # Load classes
    require 'rubygems'
    require 'watir'

    # The main test
    begin
      # Create the new report
      r = CLReport.new()
      testReport = r.createReport('C:\\testlocation\\reports\\Examplescrīpt')

      # Start browser
      browser = Watir::IE.new
      browser.goto('http://www.blabla.com')

      # --- START TEST ---

      # Do a check and report the result
      if (1 > 0)
        r.addtoReport(testReport, 'Check if 1 is bigger than 0', 'PASSED', '1 is indeed bigger than 0')
      else
        r.addtoReport(testReport, 'Check if 1 is bigger than 0', 'FAILED', '1 is NOT bigger than 0!')
      end

      # Do another check and report the result
      if (2 > 1)
        r.addtoReport(testReport, 'Check if 2 is bigger than 1', 'PASSED', '2 is indeed bigger than 1')
      else
        r.addtoReport(testReport, 'Check if 2 is bigger than 1', 'FAILED', '2 is NOT bigger than 1!')
      end

      # --- END TEST ---

      # Close browser
      browser.close

      # Finish the report
      r.finishReport(testReport)
    rescue
      # Send crash info to report
      r.addtoReport(testReport, 'Test crashed with reason '+$!, 'FAILED', 'Test crashed!')

      # Finish the report
      r.finishReport(testReport)
    end

    CLReport类代码,请参见附件中(点文件菜单访问)。

     

  • 开源的质量控制工具 Sonar

    2008-11-23 17:58:41


    http://sonar.codehaus.org/documentation/

    http://www.javaread.com/article/show/195

     

    安装指南:http://docs.codehaus.org/display/SONAR/Installation+guide

    http://docs.codehaus.org/display/SONAR/Frequently+Asked+Questions

     

    下载

    http://sonar.codehaus.org/downloads/

     

    sonar 整合代码覆盖率/规则检查等数据WEB图形化展现。

    预先条件

    window xp 上环境变量PATH已经加入D:\apache-maven-2.0.9\bin

    D:\apache-maven-2.0.9\my-webapp>java -version

    java version "1.5.0_14"

    Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_14-b03)

    Java HotSpot(TM) Client VM (build 1.5.0_14-b03, mixed mode)

    D:\apache-maven-2.0.9\my-webapp>mvn -v

    Maven version: 2.0.9

    Java version: 1.5.0_14

    OS name: "windows xp" version: "5.1" arch: "x86" Family: "windows"

     

    安装

    安装在,D:\sonar-1.4.3\conf

    InstallNTService.bat 安装服务

    StartNTService.bat启动服务

    IEhttp://127.0.0.1:9000/ 初步测试。

     

    缺省用户名密码:admin/admin

    WEB 页面上创建DB 创建后可以看到D:\sonar-1.4.3\conf\ sonar.properties

    sonar.jdbc.url:                            jdbc:derby://localhost:1527/sonar;create=true

    sonar.jdbc.driverClassName:                org.apache.derby.jdbc.ClientDriver

     

    IE展现图如下:

     

     

    配置与maven2的关联

    $MAVEN_HOME/conf (如D:\apache-maven-2.0.9\conf)或者 ~/.m2 下的settings.xml 文件加入下面内容

     

    <profile>

                <id>sonar</id>

                <activation>

                    <activeByDefault>true</activeByDefault>

                </activation>

                <properties>

                                    

                     <sonar.jdbc.url>

                      jdbc:derby://localhost:1527/sonar

                    </sonar.jdbc.url>

                    <sonar.jdbc.driver>org.apache.derby.jdbc.ClientDriver</sonar.jdbc.driver>

                    <sonar.jdbc.username>sonar</sonar.jdbc.username>

                    <sonar.jdbc.password>sonar</sonar.jdbc.password>              

                    <sonar.host.url>http://127.0.0.1:9000/</sonar.host.url>

                   

                </properties>

            </profile>

     

    配置一个maven2 工程pom.xml

     

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

      <modelVersion>4.0.0</modelVersion>

      <groupId>com.mycompany.app</groupId>

      <artifactId>my-webapp</artifactId>

      <packaging>jar</packaging>

      <version>1.0-SNAPSHOT</version>

      <name>my-webapp</name>

      <url>http://maven.apache.org</url>

      <dependencies>

        <dependency>

          <groupId>junit</groupId>

          <artifactId>junit</artifactId>

          <version>3.8.1</version>

          <scope>test</scope>

        </dependency>

      </dependencies>

    </project>

     

     

    编译发布

     

     

    D:\apache-maven-2.0.9\my-webapp>mvn org.codehaus.sonar:sonar-maven-plugin:1.4.3:sonar -Dsonar.skipInstall=true

     

     

    重新刷新IE数据,漂亮的数据图表展现在面前。

  • [watir] 在watir中读取ini文件

    2008-11-23 16:29:10

                                                                   --------by nish

      在window系统中,ini文件是一个很重要的配置文件,很多软件都通过ini文件的方式来进行参数的配置。在参考了网上gdsx in #ruby-lang中的一部分代码,写了读取ini文件的函数,该函数支持正则等,同时改进了原先代码中不支持等于号后有"="的情况。代码如下:

    def read_ini_file(filename)
        input = ""
        File.open(filename){|f| input = f.read}
        tamed = {}
        
        # split data on city names, throwing out surrounding brackets
        input = input.split(/\[([^\]]+)\]/)[1..-1]
     
        # sort the data into key/value pairs
        input.inject([]) {|tary, field|
          tary << field
          if(tary.length == 2)
            # we have a key and value; put 'em to use
            tamed[tary[0]] = tary[1].sub(/^\s+/,'').sub(/\s+$/,'')
            # pass along a fresh temp-array
            tary.clear
          end
          tary
        }
     
        tamed.dup.each { |tkey, tval|
          tvlist = tval.split(/[\r\n]+/)
          tamed[tkey] = tvlist.inject({}) { |hash, val|
            array = val.split(/=/)
            k = array[0]
            v = array[1..-1].join("=")
            k = k.strip        
            v= v.strip unless v.nil?  
            v =" " if  v.nil?
            first = v[0,1]
            last = v[-1,1]
            flag = first + last
            case flag
            when "\"\""
              v = v[1..-2]
            when "//"
              v = /#{v[1..-2]}/
            end
            hash[k]=v
            hash
          }
        }
      
        tamed
      end


     

    假设ini文件如下:

    [test]

    key1 = /test/

    key2 = "xxxxx"

    [test2]

    key1 = xxxx

    key2 = yyyyy

     则通过上述函数,读取后的内容为(返回的结果为一个Hash)

    result={

     "test"={

            "key1" = /test/,

            "key2" = "xxxxx"

            },

    "test2"={

         "key1" ="xxxx",

         "key2" = "yyyyy"

     }

    }

  • [watir] watir中close方法的改进

    2008-11-23 16:22:18

                                     ------by nish

      在watir中,默认的close的方法是通过调用ole的quit方法来实现的。但是由于quit方法需要执行一定时间。在多次运行的过程中,经常会出现ole错误,远程连接已经断开的错误。出现这个错误的原因是因为close方法中的quit方法还没有将ole对象完全destroy从而导致。

      找到原因后,改进的方法也就很简单,就是在close方法中加入判断,知道要关闭的IE对象的ole对象完全destroy后才退出close方法。可以通过以下的代码实现:

     

        def close
          @closing = true
          @ie.quit
          begin
            while
              @ie.HWND
            end
          rescue WIN32OLERuntimeError
          end
        end   

      该方法通过在调用quit方法后,再去不断的调用hwnd方法,知道ole对象销毁报错后退出程序的执行。

  • 虚拟化技术与vmware简介

    2008-11-22 22:13:04

    之前做过一部分工作是测试环境的构建和维护,主要是利用虚拟机构建多样的测试环境。目前阿里巴巴主要是linux平台,虚拟机使用的是linuxXen(准虚拟化技术),vmware未必会用到,但虚拟化技术应用是趋势,在此把对虚拟机了解的一些情况分享出来,大家可以做个了解,希望也可以对广大的测试同行有所帮助。

      
    一、常见四种虚拟化技术及其对比(请参考高人的文章,原文在http://www.vpshosting.cn/vps/2007/0302/content_264.htm,我是了解和使用,算一名发烧友吧)
      
    虚拟技术1
    硬件分区:硬件资源被划分成数个分区,每个分区享有独立的CPU、内存,并安装独立的操作系统。主要用在大型服务器上。
       
    虚拟技术2-虚拟机技术:不再对底层的硬件资源进行划分,而是部署一个统一的Host系统。在Host系统上,加装了Virtual Machine Monitor,虚拟层作为应用级别的软件而存在,不涉及操作系统内核。虚拟层会给每个虚拟机模拟一套独立的硬件设备,包含CPU、内存、主板、显卡、网卡等硬件资源,在其上安装所谓的Guest操作系统。最终用户的应用程序,运行在Guest操作系统中。 
      
    虚拟技术3-准虚拟化技术:为了改善虚拟机技术(Virtual Machine Monitor)的性能,一种新的准虚拟化技术(Para-Virtualizion)技术诞生了。这种虚拟技术以Xen为代表,其特点是修改操作系统的内核,加入一个Xen Hypervisor层。它允许安装在同一硬件设备上的多个系统可以同时启动,由Xen Hypervisor来进行资源调配。
      
    虚拟技术4-操作系统虚拟化:最新的虚拟化技术已经发展到了操作系统虚拟化,以SWsoftVirtuozzo/OpenVZSun基于Solaris平台的Container技术为代表,其中Virtuozzo是商业解决方案,而OpenVZ是以Virtuozzo为基础的开源项目。他们的特点是一个单一的节点运行着唯一的操作系统实例。通过在这个系统上加装虚拟化平台,可以将系统划分成多个独立隔离的容器,每个容器是一个虚拟的操作系统,被称为虚拟环境(VEVirtual Environment),也被称为虚拟专用服务器(VPSVirtual Private Server)

      
    二、虚拟机的好处
       1.
    资源利用充分,有那么多服务器它们是否充分利用,或者没有那么多物理机器怎么办?利用虚拟机可以充分提高服务器的资源利用率,达到节约成本的目的。
       2.
    满足开发测试环境多样性的要求,通常不同的数据库和中间件,操作系统,简单组合,就有很多复杂多样的环境。虚拟机可以帮助你去完成这些环境
       3.
    备份方便:虚拟机的快照技术,让你随时恢复环境,备份可以拷贝虚拟机的几个文件,对非关键应用可以满足需求。
       4.
    容易部署,管理也方便(管理一个物理主机,其他均可远程管理) 
       5.
    安全,各个虚拟机之间是没有任何关系的。

       
    三、主要虚拟机软件的介绍
        Vmware
    ,业界的老大,EMC下的独立子公司。
        GSX Server
    (推荐):服务器版,面向小型企业、教育科研机构和开发人员。GSX 作为系统服务运行在windowslinux上。 
        ESX Server:
    企业服务器版 
    ESX Sever可以直接安装在物理服务器上面,然后在ESX上面安装虚拟机(其实ESX Server本身就在Linux基础上改的)EXSGSX性能要高很多,功能方面也高很多,例如在HA方面、虚拟SMP、资源分配、备份方面有很多企业级的特性,但是价格上也要高很多。
        Work Station
    :工作站版,面向个人用户。小型环境足够使用。
        
    其他工具如:集中管理工具
    VMware VirtualCenter、迁移工具VMware P2V Assistant(把应用从物理机器迁移到虚拟机器) Vmware Player vm workstation的免费版)vmvware  convert几分钟内可以将物理机转换为虚拟机 vmware infrastructureVM软件套装)
     
       Sun Solaris Zone-虚拟操作系统技术,相当于在Solaris上面虚拟出很多Solaris来,每个Solaris分配一定的资源,物理OS和虚拟OS现在只是支持Solaris 10,物理服务器硬件支持X86服务器和Sun的服务器。技术集成在solaris里面,需要做一些配置。
        微软
    VPCVirtual Server-微软是比较有实力的,这个也支持虚拟linux系统。
       
    其他如swsoftVirtuozzo采用了和vmware/vpc完全不同的技术(效率高于vmwareVirtuozzolinux上面有一个开源版本OpenVZ),其他还有一些开源的还有一些开源的虚拟机软件,例如bochsqemu等等。

    linux的Xen,linux的虚拟机,性能较高,这方面的知识需要多向wxc同学多学习和了解!

      
    四、vmware的软件使用,常见优化方法和常见错误
       
    使用很简单,建议参考虚拟机的帮助文档。仅介绍一些优化方法
      
    1给虚拟机指定固定的最大物理内存
       
    工具栏选择“编辑”-“参数”-“内存”-可以根据实际的使用情况选择“系统内存分配给虚拟机的方式”
      
    2)删除不用的虚拟设备
      
    工具栏选择“虚拟机”-“设置”,选择不会用到的设备删除,比如“音频”,“usb控制器”。
       3
    )安装VMware工具
       
    开启虚拟机,工具栏选择“虚拟机”-“安装VMwae工具”
       
    安装VMwae工具可以增强虚拟机界面显示和鼠标移动效果
       4
    虚拟机在创建磁盘时选择一次创建
     
    (不要使用自己扩充的那种模式,因为在虚拟机自己扩充的过程中可能会有一些监听扫描之类的工作影响效率),即在添加虚拟机硬盘时勾选马上分配所有磁盘空间
       5
    )虚拟机打开显卡加速

       
    安装了 vmware-tools 后,需要将显卡的硬件加速打开
      
    6虚拟机的磁盘整理和磁盘压缩
      
    整理你的虚拟磁盘会提高,磁盘压缩在安装vmware之后,使用可以压缩你的虚拟机磁盘(限动态分配大小的磁盘)。

       常见错误解决
       a
    vmware “经典错误9297解决方案
      
    提示错误
       VMware Workstation internal monitor error (bug 9297) *** 
      
    用记事本打开你的虚拟机虚拟配置文件(.vmx)(or .cfg),添加下边这行
       paevm = "TRUE"
      
    这个主要是因为:旧版VMWare不支持在x64处理器上安装物理地址扩展选项
      
    受影响系统:  Windows XP SP2, Windows Server 2003, Red Hat Enterprise Linux 4, Red Hat    Enterprise Linux 3 Update 3, and Solaris 10.

       b
    、无法打开虚拟机: XXX.vmx,该虚拟机似乎正在被使用
      
    解决方法:找到虚拟机系统的文件夹。在此文件夹下,将名字以“.lck ”结尾的文件夹全部重命名,重命名的名字随意改一个。然后再到VMWARE里启动你的VM。或者直接删掉“.lck ”结尾的文件夹,之后可以启动了。
       c
    、虚拟机快照恢复报错恢复快照时出错: 文件已存在
      
    解决方法:除了在虚拟机文件当前路径下vmware的日志,在操作系统的temp目录下也有vmwarelog,按照日志中提示的,删除(先备份)提示已经存在的文件,再还原快照即可。大意就是通过日志找到具体是那个文件提示已存在,然后备份或者删除掉那个文件,再还原快照即可。 

     
    五、vmware的软件下载
       
    直接到vmware网站去下载吧。最新的好像是Vmware6.0版本,相关vmware的认证有VCP(VMware认证专家)

      六、使用vmware,建议预先创建不同环境的虚拟机模板(预装好各种环境的虚拟机),在使用的时候拷贝虚拟机文件,大概几分钟就搞定一个测试基础环境。还有比如自己做练习和研究,使用虚拟机你就可以随意试验。

      
    推荐几个网站:
     
    中文网站:www.vware.cn
               www.xuniji.com
     
    英文网站:www.vware.com

     

     

  • samba和NFS区别-wxc

    2008-11-22 21:49:01

      samba基于tcp重新开发,使用的协议是netbios。微软不愿意交License费,在windows系统中对该协议重新进行了实现。samba和windows中的网络邻居都使用netbios协议。那么,samba自然主要用于在windows和unix之间共享资源。资源包括文件、打印机等等。
      NFS是SUN开发的,用于UNIX机器之间的资源共享。其设置相当容易,主要是配置/etc/exports文件,然后运行exportfs -a来共享出来。现在NFS已经成为UNIX/LINUX上的标配。
      从我的经验来看,nfs的效率要稍微高一些,只是差别不是太大。从配置来看,samba比较复杂,nfs比较简单。但是复杂有复杂的道理,它让我们能够灵活的配置。

1561/812345678>
Open Toolbar