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

发布新日志

  • [论坛] jmeter资源监控器开发——关键代码分析

    2008-07-31 22:14:50

    by jack

    代码分析也无需事无巨细皆列而剖之,只要找到关键所在也就是了;又不然列一堆的声明上来,纵然有人有耐心看下去,我也没耐心写下去啊。特别关注了三个类,Stats、MonitorPerformancePanel、MonitorGraph。分别是获取解析得到的数据、监控器面板显示和监视器上的图像绘制。下面选取了一些关键代码来进行分析:

    首先是Stats.java,下面是计算内存使用率的方法

    public static int calculateMemoryLoad(Status stat) {
      double load = 0;
      if (stat != null) {
       double total = stat.getJvm().getMemory().getTotal();
       double free = stat.getJvm().getMemory().getFree();
       double used = total - free;
       load = (used / total);
      }
      return (int) (load * 100);
     }

    很简单吧?就是获取total值和free值,然后计算内存使用率,那么它解析的是什么东西呢?我们取了一份tomcat上的status的xml,内容如下:

    <?xml version="1.0" encoding="utf-8"?><status><jvm><memory free='937000' total='5177344' max='66650112'/></jvm><connector name='http-8080'><threadInfo  maxThreads="40" currentThreadCount="2" currentThreadsBusy="1" /><requestInfo  maxTime="1715" processingTime="2819" requestCount="20" errorCount="2" bytesReceived="0" bytesSent="108662" /><workers><worker  stage="S" requestProcessingTime="0" requestBytesSent="0" requestBytesReceived="0" remoteAddr="127.0.0.1" virtualHost="localhost" method="GET" currentUri="/manager/status" currentQueryString="XML=true" protocol="HTTP/1.1" /><worker  stage="R" requestProcessingTime="0" requestBytesSent="0" requestBytesRecieved="0" remoteAddr="&#63;" virtualHost="&#63;" method="&#63;" currentUri="&#63;" currentQueryString="&#63;" protocol="&#63;" /></workers></connector><connector name='jk-8009'><threadInfo  maxThreads="200" currentThreadCount="4" currentThreadsBusy="1" /><requestInfo  maxTime="0" processingTime="0" requestCount="0" errorCount="0" bytesReceived="0" bytesSent="0" /><workers></workers></connector></status>

    这乱七八糟的,谁看得清啊,不要急,保存下来命名为.xml文件,扔到ie里再看一下

     

    其实上面那段代码所取的,就是这个xml里面的memory free和total。

    这个xml里这么多可以利用的内容,要是我们都解析出来,不就可以有很多资源数据了?有人也许会问,这些都是什么tread信息什么,又没有cpu啊,io之类的信息,解析出来也没用;要知道,这个xml文件你自己可以生成的,里面存什么数据,你自己怎么定义都行啊,定义好了,写一个动态更新这里面的数据的脚本或程序,再利用web去展现这个xml,jmeter不就可以取来用了?

    我们再看看MonitorPerformancePanel.java

     public static final String LEGEND_MEM = JMeterUtils.getResString("monitor_legend_memory_per"); //$NON-NLS-1$
     public static final ImageIcon LEGEND_MEM_ICON = JMeterUtils.getImage("monitor-orange-legend.gif"); //$NON-NLS-1$
    这两句就是设置监视器上显示的图例,是啥东西呢?就是这个:

    标识了图线的颜色和内容标签

    上面两句设置好了,要显示就要看下面这段的了:

      JLabel mem = new JLabel(LEGEND_MEM);
      mem.setFont(plaintext);
      mem.setPreferredSize(lsize);
      mem.setIcon(LEGEND_MEM_ICON);
      legend.add(mem);

    做过java的gui编程的朋友一定不会觉得陌生,呵呵

    再下来看一下MonitorGraph.java

      if (MEM) {
       int mmy = (int) (height - (height * (model.getMemload() / 10000.0)));
       int lastmmy = (int) (height - (height * (last.getMemload() / 10000.0)));

       g.setColor(Color.orange);
       g.drawLine(lastx, lastmmy, xaxis, mmy);
      }

    这段就是展现曲线的代码,可以产生如下的效果:

    用jmeter做过tomcat监控的人一定会觉得很熟悉。不过也许会问,为啥这个图像上曲线这么多呢,jmeter不是就四条么?

    呵呵,不忙,且听我慢慢道来。

  • [论坛] 我选老板的“四要”、“三不要”

    2008-07-29 13:39:02

    by jack

    有感于张亚勤的选人方法

    张亚勤曾任微软亚洲研究院院长,在挑选优秀研发人才上,有一套自己的看法。他说,他选才有四要,三不要。四要是要有好奇心,能否追根究柢;要有想像力、创造力;要有判断力;要看他的心态,是否有团队精神,有责任感,有恒心。至于有三种人则必不用,老是用负面态度看事情的人,这种人总是抱怨;玩世不恭的人,什么事情都不在乎;两面三刀,表里不一的人。

    亦有如下选老板的方法

    我选老板有四要,三不要。四要是要有好奇心,能否对我这个人表示好奇;要有想像力、创造力,想象我是极度优秀的人才、创造展现我能力的工作任务;要有判断力,能够判断我做的是好、更好还是最好;要看他的心态——被我骂了能不能冷静,是否有团队精神——出去吃东西他买单,有责任感——好事归我坏事自己担着,有恒心——无论我做什么都继续用我。至于有三种老板则必不跟,老是用负面态度看我的人,这种人总是抱怨我能力不足;玩世不恭的人,我做出什么成绩都不在乎;两面三刀,表里不一的人。

    一笑:)

  • [论坛] 关于jmeter源码编译的问题

    2008-07-28 15:23:43

    by jack

    有人问我,从apache Jakarta上下载的jmeter源码包打开后编译通不过。源码包是在http://jakarta.apache.org/site/downloads/downloads_jmeter.cgi上下在的

    这个问题在我刚开始做jmeter扩展的时候也遇到过。

    ant install编译错误截屏:

    提示很清楚,三方库缺失;只是可能不知道三方库哪里有。不用多想,binary包里找,肯定有,不然咋运行。

    解决方法很简单:从jmeter的binary包的lib目录里把三方库的jar包拷贝过来,再编译就可以了

    另外源码包里是没有jmeter的执行脚本和配置文件的,也要拷贝过来才能执行,在bin目录下

    注意:jmeter编译生成的bin目录下ApacheJMeter.jar和lib目录下的ext目录中的jar包以及bshclient.jar、jorphan.jar包,不要删除或覆盖。

    其实更简单的办法是直接从svn上拿代码,只读主干url是:

    http://svn.apache.org/repos/asf/jakarta/jmeter/trunk/

    拿下来的很完整,直接ant编译就可以了

  • OpenAPI 测试畅想

    2008-07-28 12:51:03

    淘宝网新近开放了TOP平台,阿里软件的同事们根据平台测试的实践编写了《互联网单元测试及实践》,阿里巴巴技术部也在实现Open API给第三方开发商的项目,国内互联网公司Open API开放状况参考http://fairyfish.net/2008/07/16/chinese- open-api/。本月程序员杂志Open API大篇幅占据版面。chinaunix专门开辟openapi专栏 http://bbs.chinaunix.net/forum-137-1.html
       这些信息都表明,OPEN API是增强网站个性化、定制化的方式之一,将成为主流网站的一个趋势。

    一种新的研发模式也必然对测试带来一定的影响。对于开放API的平台商而言,Open API本身的测试也会有自己个性化的特征。

    (1) 安全测试要求更高。由于涉及关键数据众多,在用户输入验证、输出展现、安全交互、权限系统设计方面的要求更高。防止SQL注入、命令注入、XSS、缓冲区溢出、整数溢出等主要安全问题围绕整个软件生命周期。

    (2) 流量、资源消耗、计费等监控粒度更加细致。

       从第三方开发商过来的请求流量设计方面必须足够聪明,做到有效控制DOS攻击。
       
       需要评估审核第三方开发商研发能力,加强对其管理。
       
       API调用需要大量计算资源,有效监控资源变化包括系统级别的资源(如CPU\IO\网路\内存\进程间通信\打开文件描述符、数据库的CRUD等)以及业务级别资源(页面响应时间、资源下载时间等),全方位的监控体系保证网站安全。

    (3) 性能测试的需求更加迫切。
        大规模的应用访问会让系统感受到PV的强烈冲刺。
        一般应用程序关注用户访问模式,Open API更为关注API自身的调用频率。各种性能profile工具将发挥极致威力
              
    (4)非常适合应用单元测试、应用代码覆盖以及做到daily build/test。

       由于提供给第三方开发商使用,其接口必然比较稳定,以及复用程度较高。从成本效益角度衡量,适合单元测试。同时借助代码覆盖率度量工具,增加测试用例。
       由于存在良好的单元测试代码,daily build/test体系建立将让BUG主动跳出来。
         
    (5)demo应用程序以及API函数说明书。
       
       demo程序以及API函数说明书同样需要测试。第三方开发商借助这些demo应用程序以及API函数说明书才能有效发挥开放API的威力,由于分处两地,为了减少沟通成本,demo程序以及说明书应该相当详备。

    (6) 部署模式测试。

       API部署范围不应局限于在PC/PC Serer上, Open API也应该部署在流行的google application engine平台以及Amazon AWS上进行测试,以满足不同层次的开发商需求。

    (7)支持的开发语言调用测试

       针对Open API声称支持的各种开发语言对应的API都做测试。每种语言的数据类型都有差异,这个微小差异有时会导致致命的问题。
      
    (8)架构设计文档本身的测试,核心代码尽早执行性能测试
       
        应该有资深的架构师尽早介入,评审关键应用的设计文档,在早期介入减少设计失误。

        核心代码尽早执行性能测试,避免后期大规模修改。
       
      欢迎各位朋友拍砖。
  • 搭建Discuz论坛以及mediawiki平台过程

    2008-07-22 21:12:50

    第1章        概述
    尝试搭建一个论坛以及wiki平台。

    软件版本分别是:

    httpd-2.2.6.tar.gz
    mysql-5.0.51a-linux-i686_2.tar.gz
    php-5.2.6.tar.gz
    Discuz!_6.0.0_SC_UTF8.zip
    mediawiki-1.11.1.tar.gz

    不上MemCache模块
    当然论坛也可以采用phpbb,免费的
    系统版本:Linux alitest144 2.6.9-42.ELsmp,gcc version 3.4.6.

    第2章        部署Mysql
    2.1        安装
    groupadd  mysql
    useradd   -g mysql  -d  /home/mysql  mysql
    tar  -zxvf mysql-5.0.51a-linux-i686_2.tar.gz  到/home/mysql下

    默认目录权限修正: (mysql运行时所需的目录)
    mkdir -p /var/lib/mysql
    chown -R mysql:mysql /var/lib/mysql
    mkdir -p /var/run/mysqld
    chown -R mysql:mysql /var/run/mysqld

    建立默认数据库
    cd /home/mysql
    ./scrīpts/mysql_install_db
    chown -R mysql:mysql /var/lib/mysql
    ln -s /var/lib/mysql/mysql.sock  /tmp/

    启动
            bin/safe_mysqld&
           
            注意这里编码格式是默认的utf-8.
    关闭
    mysqladmin -u root  -p  shutdown

    2.2        测试

    安装好后,root密码默认为空
    Mysql  -uroot  -p 进入


    第3章        部署Apache
    3.1        安装
    ./configure   --prefix=/usr/local/apache2    --with-mpm=prefork  --enable-so   
    3.2        测试
    http://10.0.4.144:80/index.html
    第4章        部署PHP
    4.1        安装(这个环节最多问题)
    网上的多篇文档都是有错误的,集中在MYSQL连接上。
    有一文章很好,http://www.blogjava.net/tufanshu/archive/2006/10/20/76389.html
    但php configure时指定的选项不正确。
    mediaWiki需要图形库zlib \ gd2的支持。

    Ldconfig –v |grep mysql
    Ldconfig

    ./configure --prefix=/usr/local/apache2/php5 --with-apxs2=/usr/local/apache2/bin/apxs  --with-mysql=/home/mysql/mysql-5.0.51a-linux-i686 --with-zlib   --with-zlib-dir=/url/local/zlib  --with-libxml-dir=/usr/local/  --with-gd=/usr/local/gd2 --with-jpeg-dir=/usr/local/jpeg6 --with-png-dir=/usr/local/libpng2   --with-config-file-path=/usr/local/apache2/php5/lib  --disable-debug --enable-safe-mode --enable-trans-sid --enable-short-tags --disable-posix --enable-exif --enable-ftp --enable-sockets


    make && make install
    cp /usr/src/php-5.1.6/php.ini-dist   /usr/local/apache2/php5/lib/php.ini


    修改apache 的httpd.conf文件:
    LoadModule php5_module        modules/libphp5.so
    AddType application/x-httpd-php .php
    DirectoryIndex index.html index.php


    另外,为了不显示目录,删除index
    <Directory "/usr/local/apache2//htdocs">
        #
        # Possible values for the Options directive are "None", "All",
        # or any combination of:
        #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
        #
        # Note that "MultiViews" must be named *explicitly* --- "Options All"
        # doesn't give it to you.
        #
        # The Options directive is both complicated and important.  Please see
        # http://httpd.apache.org/docs/2.2/mod/core.html#options
        # for more information.
        #
    Options FollowSymLinks
       
    </Directory>


    部分目录为了保护起来,可以利用认证

    bin/htpasswd  -c passwords wiki  生成密码,然后把下面这段放到httpd.conf
    <Directory /usr/local/apache2/htdocs/portal>
    AuthType Basic
    AuthName "Restricted Files"
    AuthUserFile /usr/local/apache2/passwords
    Require user wiki
    </Directory>


    不必修改php.ini
    4.2        测试PHP引擎
    Index.php放在/usr/local/apache2/htdocs,内容如下:

    <html>
    <head>
            <title>HP Test</title>
            <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    </head>
    <body>
            <h1>HP Test</h1>
            <p>
            <b>An Example of PHP in Action</b><br />
                    <?php echo "The Current Date and Time is: <br>";
                            echo date("g:i A l, F j Y.");?>
            </p>

            <h2>HP Information</h2>
            <p>
                    <?php phpinfo(); ?>
            </p>
    </body>
    </html>

    4.3        测试MYSQL连接
    Connect_mysql.php放在/usr/local/apache2/htdocs,内容:
    <?php
    $link = mysql_connect('localhost', 'qauser', 'qauser');
    if (!$link) {
        die('Could not connect: ' . mysql_error());
    }
    echo 'Connected successfully';
    mysql_close($link);
    ?>


    第5章        部署Discuz
    5.1        安装
    建立MYSQL数据库及用户

    Mysql  -uroot  -p
    Create database  db_aliqakb;
    grant all  privileges    on db_aliqakb.*   to  qauser@'localhost'   identified by 'qauser';
    grant all  privileges    on db_aliqakb.*   to  qauser@'10.0.%'   identified by 'qauser';
    flush privileges;

    在/usr/local/apache2/htdocs 目录下解压

    unzip   -d  discuz  Discuz\!_6.0.0_SC_UTF8.zip

    设置目录权限:
    Cd  /usr/local/apache2/htdocs/discuz/upload
    [root@alitest144 upload]# chmod  777 templates/
    [root@alitest144 upload]# chmod  777  templates/default
    [root@alitest144 upload]# chmod  777  templates/default/*.*
    [root@alitest144 upload]# chmod  777  attachments
    [root@alitest144 upload]# chmod  777  customavatars
    [root@alitest144 upload]# chmod  777  forumdata/
    [root@alitest144 upload]# chmod  777  forumdata/cache/
    [root@alitest144 upload]# chmod  777  forumdata/templates/
    [root@alitest144 upload]# chmod  777  forumdata/threadcaches
    [root@alitest144 upload]# chmod  777  forumdata/logs/
    [root@alitest144 upload]# chmod  666  config.inc.php

    修改config.inc.php内容

            $dbhost = 'localhost';                  // 数据库服务器
            $dbuser = 'qauser';                     // 数据库用户名
            $dbpw = 'qauser';                               // 数据库密码
            $dbname = 'db_aliqakb';                 // 数据库名
            $pconnect = 0;                          // 数据库持久连接 0=关闭, 1=打开

    // [CH] 如您对 cookie 作用范围有特殊要求, 或论坛登录不正常, 请修改下面变量, 否则请保持默认

            $cookiepre = '8AB_';                    // cookie 前缀
            $cookiedomain = '';                     // cookie 作用域
            $cookiepath = '/';                      // cookie 作用路径

    // [CH] 论坛投入使用后不能修改的变量

            $tablepre = 'cdb_';                     // 表名前缀, 同一数据库安装多个论坛请修改此处

    // [CH] 小心修改以下变量, 否则可能导致论坛无法正常使用

            $database = 'mysql';                    // 论坛数据库类型,请勿修改
            $dbcharset = 'utf8';                    // MySQL 字符集, 可选 'gbk', 'big5', 'utf8', 'latin1', 留空为按照论坛字符集设定

            $charset = 'utf-8';                     // 论坛页面默认字符集, 可选 'gbk', 'big5', 'utf-8'


    建立MYSQL数据库及用户
    Mysql  -uroot  -p
    Create database  db_aliqakb;
    grant all  privileges    on db_aliqakb.*   to  qauser@'localhost'   identified by 'qauser';
    grant all  privileges    on db_aliqakb.*   to  qauser@'10.0.%'   identified by 'qauser';
    flush privileges;


    网页上执行初始化安装动作

    http://10.0.4.144/discuz/upload/install.php

    中间某一步检查有错误的话导致无法成功导入数据


    管理员权限初始化设置论坛
    http://10.0.4.144/discuz/upload/
    比如admin/

    5.2        测试
    http://10.0.4.144/discuz/upload/

    第6章        部署mediaWiki
    6.1        安装

    建立Mysql数据库以及用户权限
    Create database wikidb;
    grant all  privileges    on wikidb.*   to  wikiuser@'localhost'   identified by 'wikiuser';
    grant all  privileges    on wikidb.*   to  wikiuser@'10.0.%'   identified by 'wikiuser';
    flush privileges;
    修改php5/lib/php.ini保存session信息
    session.save_path = "/tmp"
    解压并置执行权限

    Tar  -zxvf  mediawiki-1.11.1.tar.gz解压在 /usr/local/apache2/htdocs/mediawiki

    Chmod 777  config

    执行安装
    http://10.0.4.144/mediawiki/config/index.php




    数据库帐号同上。

    Siteconfig 选择language=zh_cn 中国大陆

    以及更改管理员账号、密码。

    提示成功后,

    Cd  /usr/local/apache2/htdocs/mediawiki/config
    Mv mv LocalSettings.php ..
    6.2        配置文件上传权限

    Vi   /usr/local/apache2/htdocs/mediawiki/LocalSettings.php
    ## To enable image uploads, make sure the 'images' directory
    ## is writable, then set this to true:
    $wgEnableUploads       = true;


    建立目录
    /usr/local/apache2/htdocs/mediawiki/images/public
    Chmod 777 /usr/local/apache2/htdocs/mediawiki/images



    http://10.0.4.144/mediawiki/index.php/Special:Upload
    可以支持jpg,png格式文件。
    6.3        更改首页信息
    更改/usr/local/apache2/htdocs/mediawiki/languages/messages/MessagesZh_cn.php内容

    6.4        URL编码
    默认是utf-8编码
    6.5        测试
    http://10.0.4.144/mediawiki/index.php
  • XPath在watir自动化测试中的应用

    2008-07-22 19:17:23

    1.1.   Xpath是什么?

    1, 为什么要用xpath

    watir支持对象属性操作上看,唯一较多document对象支持的识别属性,一个是ID 一个是xpath属性。

    从现在网站代码来看,很多对象是没有ID的,如果此时让开发为了自动化, 加这样的ID

    可谓是工程浩瀚。。。, 由下表,可得出结论:

     http://wiki.openqa.org/display/WTR/Methods+Supported+by+Element

    xpath表达式,是watir 强有力的标识web对象的方法。其内部原理是把页面HTML 转换成为

    XHTML,然后REXML来解析它,以致于可以用xpath表达式语言在文档结构中作查询定位。

    另外,用xpath可以让watir开发脚本,更简炼。

    最后,xpath可以操作html中扩展tag, watir不支持的tag操作

     

           基于以上三种原因,我们需要研究xpath技术。。。

     

    2, 工具

     Tutorial:

    http://www.w3schools.com/xpath/default.asp

     

    view xpath:

    安装firefox: http://www.mozillaonline.com/

    https://addons.mozilla.org/zh-CN/firefox/addon/1192?id=1192

    安装xpath checker: https://addons.mozilla.org/zh-CN/firefox/addon/1095?id=1095

     

    3, 包安装

    已上传到SVN

        1.2.  Xpath格式与语法

     总结一下,xpath查询需要搞清楚,以下三种语法

     1, Select Nodes (选择结点)

     2, Predicates(断言)

     3, 模糊与条件表达

     具体格式请参照: http://www.w3schools.com/xpath/xpath_syntax.asp

     

    注意:Unfortunately, there are different ways of dealing with XML and XPath in Internet Explorer based browsers and other browsers (like Mozilla based browsers).

     

    1.3.  应用场景

    1, watir 不支持的tag, 可以用element_by_xpath方法

    如:

    <html>

      <body>

        <map name="chart">

          <area shape="poly" coords="150,16,159,17,168,20,175,25,182,32,150,56,150,56" >

          <area shape="poly" coords="182,32,188,43,190,56,150,56,150,56" href="PieChart.html?category=Critical&pieIndex=0">  

        </map>

      </body>

    </html>

    脚本实现如下:

     

    # get the underlying object and execute click method

    ie.element_by_xpath("//area[contains(@href , 'PieChart.html')]/").click

      2, 使用xpath在标准HTML对象属性识别上

      <table>

      <tr>

        <td><img src="1.jpg">First Image</td>

      </tr>

    </table>

    <table>

      <tr>

        <td><img src="2.jpg">Second Image</td>

      </tr>

    </table>

    <table>

      <tr>

        <td><img src="3.jpg">Third Image</td>

      </tr>

    </table>

     

    若不用xpath, 实现只点击3.jpg的方法:

     

    ie.tables.each do |t|                      # since you don't have ID's, look at every table

      for i in 1..t.row_count                  # for every row in this table

        t[i].each do |cell|                    # for every column in this row, look at its contents

          if cell.image(:src, /3.jpg/).exists? # if true, this is your cell

            puts cell.text

          end

        end

      end

    end

     

     但是用xpath就是非常简练:

     

    ie.cell(:xpath, "//img[@src='3.jpg']/").click()

     

     

    3, tag中含有tag不识别的属性, IE没有报错

      

     <select foo="bar"> <option value="1">1< /option> < /select>

     如上对象是一个下拉框, 但若foo="bar"select tag不支持的,

    基于现有watir版本,不提供识别此对象的方法, xpath也可以访问到

    如:element = browser.select(:xpath, "//select[@foo='bar']")

    watir API来看,很多对象都支持xpath方法, 后面我也会不断补充应用场景

     

    1.4.  Xpath其它内置方法

     

    <<请参照watir 技术集锦>>

     

  • AUTOIT在watir自动化测试中的应用

    2008-07-22 19:15:06

    签于评估的目标,1 异常对象识别与操作 2, 框架移植.

    下面文档,简单罗列了我在技术评估时,经过自己学习,加工整理,总结的文档。由于时间急促不可能涉及方方面面,但常用基础的可以先从下面开始着手。。。,

     

    如果期望成为autoIT高手,最好还是参看其help文档,国外有专门招聘auitit做自动化的, 国内很少。

     

    1.      AUTOIT

    1.1.      AutoIT是什么?

    AutoIT是一款自由软件, 现在最新版本是autoit v3.

    从此介绍上看,其诞生目的就是为了解决某些语言,像 vbs and sendkeys, 在操作windows gui时不稳定,或无法实现的技术提供解决方案。其主要功能是用来模拟键盘和鼠标来进行windows 控件操作来实现操作自动化的目的。 与我们要做的自动化相关,具体有如下特征,

    A, 使用类basic 语法脚本

    B, 模拟键盘和鼠标操作

    C, 与标准windows控件交互

    D, 生成GUI

    E, com支持

    F, 正则表达式支持

    G, 调用外部dll windows api

    H, 独立装载,编译,运行,可打包成可执行的exe

     

    联系我们做自动化,脱离与iedocument对象的 windows对象,watir就力不从心,如:上传,下载,JS写的控件/第三方非web控件 alerts window,  JS pop up window, 几乎所有的非web, windows 弹出框都是。

     

    从了解watir底层代码,其解决windows对象识别与操作没有用其它技术,就是采用autoit

    最后,从搞自动化技术角度来看,autoit是一样非常强大的利器,不使用它非常遗憾。

    因为只要在win OS上操作,不管做web、还是windows自动化都需要它帮助, 在操作的稳定性

    与可能性上autoIT提供了相对较强的解决方案。

      

    1.2.  AutoIT安装与部署

     

    A, 下载:

    http://www.autoitscrīpt.com/autoit3/downloads.shtml

     

    b, 注册:

    先下载安装, 再找到AutoItX3.dll进行手工注册一下,

    注意:watir 1.5. 6在安装时,其安装目录里提供的AutoItX3.dll似乎不能正常工作

     regsvr32 D:\AutoIt3\AutoItX\AutoItX3.dll

     

    c, 讨论:

    http://www.autoitscrīpt.com/forum/index.php?

     

    1.3.  AutoIT SPY工具

     

    A, autoIT v3 window info 工具

    非常类似QTP object spy工具, 拖拽到要识别的windows control 对象上,

    会立即显示Title, class, Advanced(class), ID, ClassnameNN, ControlClick Coords:  

    Text等字段。这些属性对于操作windows对象,起到很好的标识作用。供autoiT中内置方法提供操作句柄 与操作引用.

     

    1.4.      AutoIT scrīpt

     

    Auto IT提供一整套的脚本语法,与程序开发规范.

    提供特定的数据类型,操作符与保留字, 条件语句与函数、子程序结构。

    其采用分号; 作为脚本注释。

     另外也提供基于命令行的 编译与运行环境, 不过可以用其自带IDE: sciTE, 缺点是

    不能debug.

     

    下面的操作方法, 将会在watir中比较常用到,

     

    1, MsgBox(0, "My First scrīpt!", "Hello World!")

    2, TestFunc()

    Func TestFunc()
        MsgBox(0, "My Second scrīpt!", "Hello from the functions!")
    EndFunc

     

    3, WinWaitActive ( "title", ["text"], [timeout] )/ WinClose("[ACTIVE]", "")

    4, ControlSend("Untitled - Notepad", "", "Edit1", "This is some text") /

    ControlClick("My Window", "", "[ID:254]")

    5, ControlFocus "title", "text", "controlID"

     6, 正则 StringRegExp( "test", "pattern" [, flag ] )

     7, Send "keys" [, flag]/ Sleep delay

     

     

    1.5.      应用场景

     

    更多的example请参考:autoit3\examples\helpfile\*.*

     1, 下载文件

     

    def save_file(filepath)

        ai = WIN32OLE.new("AutoItX3.Control")

        ai.WinWait("文件下载", "", 5)

        ai.ControlFocus("文件下载", "", "保存(&S)")

        sleep 1

        ai.ControlClick("文件下载", "", "保存(&S)", "left")

        ai.WinWait("另存为", "", 5)

        sleep 1

        ai.ControlSend("另存为", "", "Edit1",filepath)

        ai.ControlClick("另存为", "", "保存(&S)", "left")

        ai.WinWait("下载完毕", "", 5)

        ai.ControlClick("下载完毕", "", "关闭")

      end

    ie.span(:text, "导出Excel").click_no_wait

    save_file("C:\\abc.xls")

     

    有没有看到,每个autoit方法在call的时候都传入一些参数?

    我怎么知道的呢?都是从autoit sby工具获得的。。。

     

    2, 点击弹出框

     

    def check_for_popups

        autoit = WIN32OLE.new('AutoItX3.Control')

        #

        

        # Do forever - assumes popups could occur anywhere/anytime in your application.

        loop do

            # Look for window with given title. Give up after 1 second.

           

            ret = autoit.WinWait('Microsoft Internet Explorer', '', 1)

            #ret = WinActivate("Microsoft Internet Explorer", "")

            autoit.ControlClick("Microsoft Internet Explorer", "", "[CLASS:Button; INSTANCE:1]", 2)

            #强行点击,以使其获得focus

            puts(ret)

            #

            # If window found, send appropriate keystroke (e.g. {enter}, {Y}, {N}).

           

            if (ret==1) then autoit.Send("{Enter}") end

           

            #

            # Take a rest to avoid chewing up cycles and give another thread a go.

            # Then resume the loop.

            sleep(3)

        end

      end

     

     

    ie.button(:name, "btnUpload").click_no_wait

    sleep(20)

     

    $popup = Thread.new { check_for_popups }  # start popup handler

     

    at_exit { Thread.kill($popup) }

     

    还有很多例子,可以以此类推, 只要第1: 激活,第2步:获得焦点,第3步:就可以sendkey了。

    是不是已经搞定99.999%的问题了?

     

    注意:在watir中使用autoIT, 别忘记 require 'win32ole'

  • QTP编码问题

    2008-07-16 13:57:58

    by jiale

    前段时间有个同学问我他在记事本里编辑的QTP代码文件scrīpt.mts,在QTP里打开是乱码了,当时想到之前使用executefile方法执行vbs时出现“非法字符”错误是由于vbs文件非ANSI编码造成的。

    因此尝试将scrīpt.mts用记事本打开,并保存为ANSI编码格式,再用QTP打开,一切OK。

     

  • Valgrind 检测linux上c++内存泄露

    2008-07-15 21:51:19

    Linux c++上常用内存泄露检测工具有valgrind, Rational purifyValgrind免费。Valgrind 可以在 32 位或 64 PowerPC/Linux 内核上工作。

    Valgrind工具包包含多个工具,如Memcheck,Cachegrind,Helgrind, CallgrindMassif。下面分别介绍个工具的作用:

    Memcheck 工具主要检查下面的程序错误:

    • 使用未初始化的内存 (Use of uninitialised memory)
    • 使用已经释放了的内存 (Reading/writing memory after it has been free’d)
    • 使用超过 malloc分配的内存空间(Reading/writing off the end of malloc’d blocks)
    • 对堆栈的非法访问 (Reading/writing inappropriate areas on the stack)
    • 申请的空间是否有释放 (Memory leaks – where pointers to malloc’d blocks are lost forever)
    • malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
    • srcdst的重叠(Overlapping src and dst pointers in memcpy() and related functions)

    Valgrind不检查静态分配数组的使用情况。

    Valgrind占用了更多的内存--可达两倍于你程序的正常使用量。如果你用Valgrind来检测使用大量内存的程序就会遇到问题,它可能会用很长的时间来运行测试

    1.1.      下载安装

     http://www.valgrind.org

    安装

    ./configure;make;make install

    1.2.      编译程序

    被检测程序加入 –g  -fno-inline 编译选项保留调试信息。

     

    1.3.      内存泄露检测

    $   valgrind --leak-check=full --show-reachable=yes --trace-children=yes       ./iquery  -f ../conf/se.conf_forum    -t  ~/eragon/forum_thread_data/f.log   -NT  -cache 0

    其中--leak-check=full 指的是完全检查内存泄漏,--show-reachable=yes是显示内存泄漏的地点,--trace-children=yes是跟入子进程。当程序正常退出的时候valgrind自然会输出内存泄漏的信息。

     

    ==4591==

    ==4591== Thread 1:

    ==4591== Conditional jump or move depends on uninitialised value(s)

    ==4591==    at 0x805687B: main (TestQuery.cpp:478)

    ==4591==

    ==4591== Conditional jump or move depends on uninitialised value(s)

    ==4591==    at 0x8056894: main (TestQuery.cpp:478)

    ==4591==

    ==4591== Conditional jump or move depends on uninitialised value(s)

    ==4591==    at 0x80568AD: main (TestQuery.cpp:478)

    ==4591== Warning: set address range perms: large range 215212032 (noaccess)

    ==4591== Warning: set address range perms: large range 125145088 (noaccess)

    ==4591==

    ==4591== ERROR SUMMARY: 6 errors from 4 contexts (suppressed: 18 from 1)

    ==4591== malloc/free: in use at exit: 496 bytes in 2 blocks.

    ==4591== malloc/free: 928,605 allocs, 928,603 frees, 2,514,165,074 bytes allocated.

    ==4591== For counts of detected errors, rerun with: -v

    ==4591== searching for pointers to 2 not-freed blocks.

    ==4591== checked 10,260,564 bytes.

    ==4591==

    ==4591==

    ==4591== 144 bytes in 1 blocks are possibly lost in loss record 1 of 2

    ==4591==    at 0x4005906: calloc (vg_replace_malloc.c:279)

    ==4591==    by 0xB3671A: _dl_allocate_tls (in /lib/ld-2.3.4.so)

    ==4591==    by 0xD9491E: pthread_create@@GLIBC_2.1 (in /lib/tls/libpthread-2.3.4.so)

    ==4591==    by 0x8200C66: public_unit::CThread::start(void*) (Thread.cpp:25)

    ==4591==    by 0x80567C3: main (TestQuery.cpp:473)

    ==4591==

    ==4591==

    ==4591== 352 bytes in 1 blocks are still reachable in loss record 2 of 2

    ==4591==    at 0x40044F6: malloc (vg_replace_malloc.c:149)

    ==4591==    by 0xB9905E: __fopen_internal (in /lib/tls/libc-2.3.4.so)

    ==4591==    by 0xB9911C: fopen@@GLIBC_2.1 (in /lib/tls/libc-2.3.4.so)

    ==4591==    by 0x805940C: CSearchThread::run(void*) (TestQuery.cpp:363)

    ==4591==    by 0x8200D09: public_unit::CThread::thread_func(void*) (Thread.cpp:44)

    ==4591==    by 0xD94370: start_thread (in /lib/tls/libpthread-2.3.4.so)

    ==4591==    by 0xC0DFFD: clone (in /lib/tls/libc-2.3.4.so)

    ==4591==

    ==4591== LEAK SUMMARY:

    ==4591==    definitely lost: 0 bytes in 0 blocks.

    ==4591==      possibly lost: 144 bytes in 1 blocks.

    ==4591==    still reachable: 352 bytes in 1 blocks.

    ==4591==         suppressed: 0 bytes in 0 blocks.

     

    关键字在:ERROR SUMMARY, LEAK SUMMARY

    *                       "definitely lost" means your program is leaking memory -- fix it!

    *                       "possibly lost" means your program is probably leaking memory, unless you're doing funny things with pointers.

    *                       "still reachable" means your program is probably ok -- it didn't free some memory it could have. This is quite common and often reasonable. Don't use --show-reachable=yes if you don't want to see these reports.

    *                       "suppressed" means that a leak error has been suppressed. There are some suppressions in the default suppression files. You can ignore suppressed errors

     

    另外一种方式,激活加载调试器

    gcc -Wall   -g  -pg   -o get_XMLDOC  get_XMLDOC.c

    $ valgrind   --db-attach=yes  --leak-check=full       ./get_XMLDOC   ~/eragon/data/offer_gb.xml  1.xml  10

    ==8956== Memcheck, a memory error detector.

    ==8956== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.

    ==8956== Using LibVEX rev 1606, a library for dynamic binary translation.

    ==8956== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.

    ==8956== Using valgrind-3.2.0, a dynamic binary instrumentation framework.

    ==8956== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.

    ==8956== For more details, rerun with: -v

    ==8956==

    ==8956==

    ==8956== ---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ----

    ==8956==

    ==8956== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 12 from 1)

    ==8956== malloc/free: in use at exit: 1,953 bytes in 2 blocks.

    ==8956== malloc/free: 4 allocs, 2 frees, 2,657 bytes allocated.

    ==8956== For counts of detected errors, rerun with: -v

    ==8956== searching for pointers to 2 not-freed blocks.

    ==8956== checked 52,840 bytes.

    ==8956==

    ==8956== 1 bytes in 1 blocks are definitely lost in loss record 1 of 2

    ==8956==    at 0x40044F6: malloc (vg_replace_malloc.c:149)

    ==8956==    by 0x80488C0: main (get_XMLDOC.c:38)

    ==8956==

    ==8956== LEAK SUMMARY:

    ==8956==    definitely lost: 1 bytes in 1 blocks.

    ==8956==      possibly lost: 0 bytes in 0 blocks.

    ==8956==    still reachable: 1,952 bytes in 1 blocks.

    ==8956==         suppressed: 0 bytes in 0 blocks.

    ==8956== Reachable blocks (those to which a pointer was found) are not shown.

    ==8956== To see them, rerun with: --show-reachable=yes

    Profiling timer expired

     

    1.4.      检查性能瓶颈

    $valgrind --tool=callgrind ./iquery  -f ../conf/se.conf_forum   -s "forum_thread?q=mp4"

    ==4607==

    ==4607== Events    : Ir

    ==4607== Collected : 251772397

    ==4607==

    ==4607== I   refs:      251,772,397

     

    4607为进程号。

    $ ll

    -rw-------  1 search search   712159  7  9 22:31 callgrind.out.4607

    $ callgrind_annotate --auto=yes  callgrind.out.4607

    WARNING: header line 2 malformed, ignoring

        line: 'creator: callgrind-3.2.0'

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

    I1 cache:

    D1 cache:

    L2 cache:

    Timerange: Basic block 0 - 46942078

    Trigger: Program termination

    Profiled target:  ./iquery -f ../conf/se.conf_forum -s forum_thread?q=mp4 (PID 4607, part 1)

    Events recorded:  Ir

    Events shown:     Ir

    Event sort order: Ir

    Thresholds:       99

    Include dirs:    

    User annotated:  

    Auto-annotation:  on

     

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

             Ir

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

    251,772,397  PROGRAM TOTALS

     

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

            Ir  file:function

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

    54,769,656  ???:__mcount_internal [/lib/tls/libc-2.3.4.so]

    26,418,450  GBKNormalString.cpp:dictionary::CGBKNormalString::initNormalChars() [/home/search/eragon_yb/bin/iquery]

    22,820,690  ???:mcount [/lib/tls/libc-2.3.4.so]

    11,559,615  GBKNormalString.cpp:dictionary::CGBKNormalString::initCharKinds() [/home/search/eragon_yb/bin/iquery]

     

    更多说明参考:

    http://www-128.ibm.com/developerworks/cn/linux/l-pow-debug/

     

    1.5.      cache测试

    参考:http://www.wangcong.org/articles/valgrind.html

    [search@alitest146 /home/search/eragon_yb/bin]

    $ valgrind   --tool=cachegrind  ./iquery   -f ../conf/se.conf_forum   -s "forum_thread?q=mp3"

    ==8742==

    ==8742== I   refs:      267,968,791

    ==8742== I1  misses:         98,845

    ==8742== L2i misses:         13,382

    ==8742== I1  miss rate:        0.03%

    ==8742== L2i miss rate:        0.00%

    ==8742==

    ==8742== D   refs:      182,288,669  (120,222,370 rd + 62,066,299 wr)

    ==8742== D1  misses:        962,816  (    537,889 rd +    424,927 wr)

    ==8742== L2d misses:        707,813  (    340,925 rd +    366,888 wr)

    ==8742== D1  miss rate:         0.5% (        0.4%   +        0.6%  )

    ==8742== L2d miss rate:         0.3% (        0.2%   +        0.5%  )

    ==8742==

    ==8742== L2 refs:         1,061,661  (    636,734 rd +    424,927 wr)

    ==8742== L2 misses:         721,195  (    354,307 rd +    366,888 wr)

    ==8742== L2 miss rate:          0.1% (        0.0%   +        0.5%  )

     

    上面的是指令缓存,I1L2i缓存,的访问信息,包括总的访问次数,丢失次数,丢失率。

    中间的是数据缓存,D1L2d缓存,的访问的相关信息,下面的L2缓存单独的信息。Cachegrind也生成一个文件,名为cachegrind.out.pid可以通过cg_annotate来读取。输出是一个更详细的列表。Massif的使用和cachegrind类似,不过它也会生成一个名为massif.pid.psPostscrīpt文件,里面只有一幅描述堆栈使用状况的彩图。

     

    [search@alitest146 /home/search/Isearchv3_scrīpt_yb/tools]

    $ ll  cachegrind.out*

    -rw-------  1 search search  7283 Jul 11 11:21 cachegrind.out. 8633

     

    $  cg_annotate  --8633  --auto=yes  ~/isearch_yb/src/test/core/TestQuery.cpp                                                       

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

    I1 cache:         16384 B, 32 B, 8-way associative

    D1 cache:         16384 B, 64 B, 8-way associative

    L2 cache:         2097152 B, 64 B, 8-way associative

    Command:          ./iquery -f ../conf/se.conf_forum -s forum_thread?q=mp3

    Data file:        cachegrind.out.8633

    Events recorded:  Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw

    Events shown:     Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw

    Event sort order: Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw

    Thresholds:       99 0 0 0 0 0 0 0 0

    查看(1447) 评论(0) 收藏 分享 管理

  • linux文件系统安全性之chattr篇

    2008-07-15 12:51:46

      随着QA部门服务器的越来越多,一些重要的应用和主机直接暴露在网络中,或者INTERNET上,那么对于机器的安全性就提出了要求。常见的一种情况就是某些具有特殊权限的user进入系统后,随意修改文件,轻者导致数据丢失,重者导致系统崩溃,甚至有一些别有用心的入侵者会删掉自己的入侵log,让管理员无从查找。

      chattr是linux系统提供的一种增强文件系统安全性的系统调用。通过配置文件的属性来增强安全性,譬如:

    chattr +a log文件,表示log只能以append方式追加,任何入侵者都无法删除自己的纪录。

    chattr +i urfile: urfile文件不可以被删除、rename、modify,防止误操作很有用

    其它参数的使用可以参考man手册,同时配合lsattr显示文件的属性

  • 安全测试之windows后门程序监控--iceSword

    2008-07-15 11:57:31

    现在的系统级后门功能越来越强,一般都可轻而易举地隐藏进程、端口、注册表、文件信息,一般的工具根本无法发现这些“幕后黑手”,iceSword是一款基于win内核技术的软件,可以轻易的查看到所有的后门程序。

    绿色软件,免费,如下图:

  • 灵活运用find -exec和xargs

    2008-07-15 10:34:37

    exec 与 xargs的区别

    xargs:通过缓冲方式并以前面命令行的输出作为参数,随后的命令调用该参数

    若忽略 xargs 的 options 来看的话,
    cm1 | xargs cm2
    可以单纯看成: cm2 `cm1`
    因此, find .... | xargs rm 也可作 rm `find ...` 来处理.
    然而, 若 find 的结果太多, 可能会超过rm 可能接受的最大argument数量而失败.
    xargs优点:由于是批处理的,所以执行效率比较高(通过缓冲方式)
    xargs缺点:有可能由于参数数量过多(成千上万),导致后面的命令执行失败
    若换成 find .... -exec rm {} \; 的话,
    因为rm 是"逐个" item 去处理的, 则无此忧虑
     
    例子:(在当前目录下查找包含hello字符的文件)
     
    1。最傻方法:grep hello *  */*  */*/*
     
    2。使用exec
    [admin@b2b_search_115 test]$ find . -type f -print -exec grep "hello" {} \;
    ./file/test3
    hello
    ./test1
    hello
    ./test2
     
    3。使用xargs
    [admin@b2b_search_115 test]$ find . -type f -print | xargs grep hello     
    ./file/test3:hello
    ./test1:hello
  • 如何引入代码覆盖率度量提高测试质量

    2008-07-12 15:48:57

    by liangjz

    我们面临的困境
    1) 开发编写的单元测试代码可信度
    2) 功能测试或者自动化测试效果可信度

    为了提高测试过程的质量,是一个复杂系统过程。国外好些年前就引入代码覆盖率工具,比如
    EMMA/Clover。
    呵呵,据了解ebay中国的开发采用EclEmma。

    经过初步评估,针对java语言的EMMA 和针对 linux+ c/c++ +gcc的gcov/lcov都只能做到语句覆盖、函

    数覆盖、类覆盖。对于路径覆盖、条件覆盖等无法做。要做到更加精细,可以考虑结合Jester。

    代码覆盖率工具最让人震撼的是,无须单元测试代码,可以清楚看到执行过/未执行过的代码行,以及由

    宏观到微观的度量结果。另外引入代码覆盖率工具,无须修改代码,成本极低。

    这个结果对于开发而言,可以增加自己负责的模块的单元测试代码,或者去除死代码。
    对于测试而言,可以增加测试用例提高覆盖率,提高测试结果的信心度。

    尽管代码覆盖率工具有这样或者那样的不足,也极难做到100%覆盖,但综合权衡,引入工具还是有积极

    的意义。

    推广代码覆盖率的规划:

    1) 选取一个小型WEB应用代码覆盖工具,结果供测试工程师,分析代码覆盖率效益
    2) 大型项目应用代码覆盖工具
    3) 在研发部门推广EclEmma插件 和gcov/lcov
    4) 经过一段时间实践,在开发提交代码给测试时,要求一起提交代码覆盖率源文件。

    难点:

    1) 测试工程师面对未覆盖的代码行,要有阅读代码能力呼应到业务操作,以有针对性增加测试用例
    1) 加入代码覆盖率结果,意味对上游输出把握更加严格,要求研发部门经理和开发的意识转变以及实质性支持

    欢迎这方面有实践的朋友多提建议,谢谢

     

  • 采用EMMA对JMeter执行代码覆盖率分析

    2008-07-12 12:33:23

    by liangjz

    emma度量代码覆盖率不需要额外编写单元测试代码。
    支持JAVA GUI、JAVA CONSOLE、JAVA APP SERVER。

    一 安装与配置
    EMMA支持jdk1.2 或以上。

    下载: http://emma.sourceforge.net/
    在我的电脑里面设置CLASSPATH加入emma.jar.
    显示:
    E:\jakarta-jmeter-2.3.1\bin>echo %CLASSPATH%
    E:\alibaba\tools\emma-stable-2.1-lib\emma.jar;.


    二 收集应用的元信息

    这一步必须有.class文件或者包含.class文件的jar包。
    而且必须在应用执行的目录下进行(非源代码的路径),否则第四步收集信息时出现异常"emma ctl:

    coverage.get: RPC failure while executing [coverage.get]
    Exception in thread "main" com.vladium.emma.EMMARuntimeException: coverage.get:
    RPC failure while executing [coverage.get]
            at com.vladium.emma.ctl.CtlProcessor._run(CtlProcessor.java:242)"

     

    收集元信息(会改写ApacheJmeter.jar内容)
    java emma instr -m overwrite   -cp  ApacheJMeter.jar  -out coverage.em

    正常时当前目录生成coverage.em。

    三 执行应用程序

    jmeter.bat导致异常
    Exception in thread "main" java.lang.NoClassDefFoundError: com/vladium/emma/rt/R
    T
            at org.apache.jmeter.NewDriver.$VRi(NewDriver.java)
            at org.apache.jmeter.NewDriver.<clinit>(NewDriver.java)
    errorlevel=1

    分析确认由于java加载ApacheJMeter.jar包时ClassLoader顺序非预期,通过-

    Xbootclasspath/p:E:\alibaba\tools\emma-stable-2.1-lib\emma.jar  强制优先加载emma.jar。

    故修改jmeter.bat为
    %JM_START% %JM_LAUNCH%  -Xbootclasspath/p:E:\alibaba\tools\emma-stable-2.1-lib\emma.jar  %

    JVM_ARGS% %ARGS%   -jar "%JMETER_BIN%ApacheJMeter.jar" %JMETER_CMD_LINE_ARGS%

    再次启动jmeter.bat,出现提示

    EMMA: collecting runtime coverage data ...
    EMMA: runtime controller started on port [47653]

    netstat 检查47653端口处于Listening状态。

    在JMeter界面上操作。后台会记录代码执行状况

    四 收集代码行、函数、类覆盖信息

    在Jmeter不退出的情况下,执行
    java -cp %CLASSPATH%  emma ctl -connect localhost:47653 -command coverage.get,coverage.ec

    或者Jmeter正常退出的情况下,也会主动收集信息存放在默认的coverage.ec。

    五  生成报告

    java -cp %CLASSPATH%   emma report -r html -in  coverage.em,coverage.ec -

    Dreport.html.out.file=coverage.html -Dreport.metrics=class:50

  • gcov和lcov对linux c++分析代码覆盖率

    2008-07-09 16:19:17

    gcov伴随gcc 发布。gcc编译加入-fprofile-arcs -ftest-coverage 参数生成二进制程序,执行测试用例生成代码覆盖率信息。

    fprofile-arcs参数使gcc创建一个程序的流图,之后找到适合图的生成树。只有不在生成树中的弧被操纵(instrumented):gcc添加了代码来清点这些弧执行的次数。当这段弧是一个块的唯一出口或入口时,操纵工具代码(instrumentation code)将会添加到块中,否则创建一个基础块来包含操纵工具代码。gcov主要使用.gcno.gcda两个文件。
    .gcno
    是由-ftest-coverage产生的,它包含了重建基本块图和相应的块的源码的行号的信息。
    .gcda
    是由加了-fprofile-arcs编译参数的编译后的文件运行所产生的,它包含了弧跳变的次数和其他的概要信息。

    Gcov执行函数覆盖、语句覆盖和分支覆盖。

    Lcov则是上的gcov 结果展现的一个前端,可从 http://ltp.sourceforge.net/coverage/lcov.php 下载。可以将覆盖率信息转换成html 展现。

    安装lcovsu  - root;make install

    Makefile 在编译和link环节都加入 -fprofile-arcs -ftest-coverage 选项

    GCC = g++   -fprofile-arcs -ftest-coverage

    .SUFFIXES: .o .cpp

    iquery: $(LIBS) TestQuery.o

            $(GCC) $(LDPATH) -g       -o $@ TestQuery.o -lsearch -lupdate -lbuild -lstore -lanalysis -lconfig -ldocument -lmxml -lonline -lutility -ldictionary -lpublic -lpthread -lrt

    .cpp.o:

            $(GCC)  -c -g  $(INCLUDE) -DLINUX    -o $@ $<

           

     

    执行完iquery命令行。

    [search@b2b_search_211 core]$./iquery   -f  ~/eragon_yb/conf/se.conf  -s "offer_gb?q=mp3"

         

    对于apache module的代码覆盖率分析,必须是启动apache httpd进程,执行查询最后退出apache httpd进程才能收集到信息。

     

    [search@b2b_search_211 core]$ ll

    总用量 36120

    drwxrwxr-x  4 search search     4096  7  8 19:23 cpp

    -rwxrwxr-x  1 search search  8742605  7  8 20:06 ibuild

    -rwxrwxr-x  1 search search 13490318  7  8 20:06 idelete

    -rwxrwxr-x  1 search search 13711848  7  8 20:06 iquery

    -rw-rw-r--  1 search search     3115  7  8 20:04 Makefile

    drwxrwxr-x  3 search search     4096  7  8 19:23 test

    -rw-rw-r--  1 search search      893  6 12 18:18 TestAnalysis.cpp

    -rw-rw-r--  1 search search    10551  6 12 18:18 TestBuild.cpp

    -rw-rw-r--  1 search search    15080  7  8 20:06 TestBuild.gcno

    -rw-rw-r--  1 search search   115808  7  8 20:06 TestBuild.o

    -rw-rw-r--  1 search search     1143  6 12 18:18 TestConfig.cpp

    -rw-rw-r--  1 search search     5366  6 12 18:18 TestDelete.cpp

    -rw-rw-r--  1 search search    11204  7  8 20:06 TestDelete.gcno

    -rw-rw-r--  1 search search   252064  7  8 20:06 TestDelete.o

     

     

    生成: TestQuery.gcda TestQuery.gcno

     

    [search@b2b_search_211 core]$ gcov  TestQuery.cpp

    File `TestQuery.cpp'

    Lines executed:22.32% of 336

    TestQuery.cpp:creating `TestQuery.cpp.gcov'

     

     

    [search@b2b_search_211 core]$ ll

    总用量 36620

    -rw-rw-r--  1 search search     7024  7  8 20:08 allocator.h.gcov

    drwxrwxr-x  4 search search     4096  7  8 19:23 cpp

    -rw-rw-r--  1 search search    12827  7  8 20:08 GlobalDef.h.gcov

    -rwxrwxr-x  1 search search  8742605  7  8 20:06 ibuild

    -rwxrwxr-x  1 search search 13490318  7  8 20:06 idelete

    -rw-rw-r--  1 search search    44797  7  8 20:08 ios_base.h.gcov

    -rw-rw-r--  1 search search     4638  7  8 20:08 iostream.gcov

    -rwxrwxr-x  1 search search 13711848  7  8 20:06 iquery

    -rw-rw-r--  1 search search   128499  7  8 20:08 locale_facets.tcc.gcov

    -rw-rw-r--  1 search search     3115  7  8 20:04 Makefile

    -rw-rw-r--  1 search search    12684  7  8 20:08 MemCache.h.gcov

    -rw-rw-r--  1 search search    10158  7  8 20:08 MemPool.h.gcov

    -rw-rw-r--  1 search search     6524  7  8 20:08 new_allocator.h.gcov

    -rw-rw-r--  1 search search     5742  7  8 20:08 new.gcov

    -rw-rw-r--  1 search search     1844  7  8 20:08 QueryCache.h.gcov

    -rw-rw-r--  1 search search    44015  7  8 20:08 stl_algobase.h.gcov

    -rw-rw-r--  1 search search     8328  7  8 20:08 stl_construct.h.gcov

    -rw-rw-r--  1 search search    44016  7  8 20:08 stl_function.h.gcov

    -rw-rw-r--  1 search search    31113  7  8 20:08 stl_multiset.h.gcov

    -rw-rw-r--  1 search search    62978  7  8 20:08 stl_tree.h.gcov

    -rw-rw-r--  1 search search    10365  7  8 20:08 Svector.h.gcov

     

    [search@b2b_search_211 core]$ cat  TestQuery.cpp.gcov

     

            -:   47:static int  nAverageDocSize = 1024;        

    function _ZN9QueryStatC1EPKcxi called 0 returned 0% blocks executed 0%

        #####:   53:    QueryStat(const char* szQuery, n64_t d, n32_t docs){

        #####:   54:        query = szQuery;

        #####:   55:        dual = d;

        #####:   56:        docnum = docs;

            -:   57:    }

            -:   58:};

            -:   59:struct CmpQueryStat{

    function _ZN12CmpQueryStatclERK9QueryStatS2_ called 0 returned 0% blocks executed 0%

        #####:   60:    bool operator()(const QueryStat& a, const QueryStat& b){

        #####:   61:        return a.dual < b.dual;

            -:   62:    };

            -:   63:};

             1:  534:}

            

           #####表示未执行的行

          

    [search@b2b_search_211 core]$

    [search@b2b_search_211 core]$ ll *gcov*

     

    收集覆盖率数据生成app.info文件

    [search@b2b_search_211 core]$   lcov --directory  .   --capture --output-file app.info

    Capturing coverage data from .

    Found gcov version: 3.4.6

    Scanning . for .gcda files ...

    Found 1 data files in .

    Processing ./TestQuery.gcda

    Finished .info-file creation

     

    转换成html格式

    [search@b2b_search_211 core]$ genhtml  -o  results  app.info

    Reading data file app.info

    Found 18 entries.

    Found common filename prefix "/home/search/isearch_yb/src"

    Writing .css and .png files.

    Generating output.

    Processing file cpp/core/basis/GlobalDef.h

    Processing file cpp/core/search/QueryCache.h

    ...

    Writing directory view page.

    Overall coverage rate: 117 of 514 lines (22.8%)

     

    results目录tar  cvf 打包szwindows,打开

    总体报告:

     

    单个cpp文件的覆盖率:

     

     

    还可以看到具体的行执行情况

     

     

    另外再运行一组更丰富的查询日志,测试结果截然不同。

     

  • watir中,类似QTP object spy等方法替代实行

    2008-07-06 23:57:01

    by Wiston Li


    我们知道,QTP提供object spy工具,对象库录制功能,或描述性编程提供给我们快捷识别对象,
    一定程度上可以做到脚本批处理生成。相应的,我在想如此好的工具和技术,为啥watir没有支持?
    也许将来,在自动化同学与watir开发团队努力下,可满足这一需求。

    另一个问题抛出,是否为了准备watir脚本,我们一定要在那么冗长的代码,查找并挑选我们想要操作的对象?
    给出我的简单总结,

    1, 类似object spy工具,为微软为开发人员做的工具ie developer toolbar,可以借助它通过指针指示
    对象,在attribute view中找到相应属性。

    2,类似描述性编程,

    在cmd中运行irb,

    如: puts 2+2
    打印4,可以通过命令实现所见即所得,

    如:
    require ‘watir’
    ie=Watir::IE.start(‘http://localhost:8080’)
    ie.show_all_objects

    结果:

    -----------Objects in  page -------------
    text              name=name           id= 

    如:ie.text_field(:name, 'name').flash
    结果:使操控对象webedit框有黄色闪动效果.


    更有意思的是,当我把鼠标焦点移到某个webedit上,
    然后:
    irb> puts ie.show_active
    text         name=name          
    id=          value=             
    alt=         src=               
    innerText=
    => nil
    在这里,watir将帮助我们标识当前active的对象.
    对于button和其他对象,也可以通过tab key来实现焦点移动,
    再用alt + tab 激活irb窗口,用相同show active方法实现.

    再如:

    irb> puts ie.show_active
    submit              name=submit_logon  
    id=                 value=Login        
    alt=                src=               
    innerText=
    => nil


    irb> ie.text_field(:name, 'name').set(‘Test1’)
    => nil

    可以参照watir api对web edit对象进行内容清除,追加等.
    另外可以输出当前IE对象的HTML

    irb> puts ie.html
    <H1>
    <P align=center>Create the First Job </P></H1>
    <TABLE cellSpacing=0 cellPadding=3 border=0>
    <TBODY>
    <TR>
    <TD align=middle width="40%">
    <FORM id=job name=job action=job method=get><INPUT type=hidden value=22909012 name=session></INPUT>
    <TABLE cellSpacing=0 cellPadding=3 border=0>
    <TBODY>

    或只输出text :

    irb> puts ie.text
    Create the First Job
     Please create the first job

     Make it a background job
    If you make this job a background job, it will be a job that accumulates time when you're not doing any specific task. You'll start it in the morning,
     do your work - starting and pausing other jobs - then stop it when you're done for the day.
    Each time you pause another job, the background job will resume accumulating time.
    If you don't have a background job, you'll have to manage time more explicitly.
    => nil
    irb(main):024:0>


    对于页面中只有一个同特征对象时可以用index, 如:
    ie.text_field(:index, 1).set(‘Testing for Bugs’)

    irb> ie.button(:index,1).click
    => nil

    可以借用show_all_objects方法显示页面中所有对象
    也可以显示某一特定类型对象, 像:


    show_images Show all the images in the document
    show_spans Show all the span tags in the document
    show_labels Show all the labels in the document
    show_links Show all the links in the document
    show_divs Show all the div tags in the document
    show_frames Show all the frames in the document
    show_forms Show all the forms in the document

    如这里用ie.show_table作为示例
    irb> ie.show_tables
    Found 8 tables
    1  id=      rows=1   columns=3
    2  id=      rows=2   columns=1
    3  id=      rows=3   columns=1
    4  id=      rows=2   columns=1
    5  id=      rows=3   columns=1
    6  id=      rows=1   columns=1
    7  id=      rows=3   columns=1
    8  id=recent_records      rows=2   columns=1
    => nil

    我们可用flash方法来标识对象,
    irb> ie.table(:id , ‘recent_records’).flash

    也可以只显示特定table的html code,

    irb> puts ie.table(:id , ‘recent_records’).html

    <TABLE id=recent_records cellSpacing=0 cellPadding=3 width="66%" align=center border=1><TBODY>
    <TR bgColor=#66ffff>
    <TD align=middle colSpan=4>Recent Records </TD></TR>
    <TR bgColor=#ccffff>
    <TD>Testing for Bugs </TD>
    <TD>10:05 PM </TD>
    <TD>0.00 hours </TD>
    <TD><B>running</B> </TD></TR></TBODY></TABLE>

    这里可用ruby内置函数 to_a输出行记录数组,

    irb> irb(main):009:0> my_array = ie.table(:id , 'recent_records').to_a
    => [["Recent Records"], ["Testing for Bugs", "10:05 PM",

    以上可以看到,采用 show_XXX方法,枚举同特征对象,
    是否感觉到类似QTP:create descrīption.../ mic class='web object'/...的方法?

    类似,甚至可以通过修改底层show_XXX代码,来批处理生成脚本,
    如生成已经填值的text field操作脚本,呵呵...

     

     

     

     

     

     

     

     

     

     

     


     

  • 如何破解快速变化的web网站测试自动化困境?

    2008-07-05 19:09:47

      by liangjz

      网站业务复杂度倍增,为了改善由于开发改动一点内容,而QA需要大面积验证相关受影响的模块导致

    工作量剧增的状况,故引入网站自动化测试。

      目前针对网站主干流程核心业务做了粗粒度的验证。技术: qtp + 页面验证 + 数据库验证,业务流

    采用excel管理。 运行了一段时间,发现了一些BUG(自动化目的不是找BUG,而是一种质量保证手段)

    ,但更多的问题也引爆出来.

      经过和微软技术专家的交流,产品线的自动化测试特征如下:

    1) 微软强调单元级的验证粒度非常细致
    2) 微软强调每一个业务模块的数据输入都是全新创建而非利用系统原有数据;自动化退出时环境RESET
     

      我们问题主要集中在几块

    1) 业务经常变更,导致页面元素发生变化,需要及时调整自动化脚本。这个成本居高不下
    2) 自动化采用的脚本是依赖数据库原有的定制化的数据,有时候被QA测试时修改,干扰脚本运行。
    但如果全新创建,需要跨别的系统且需要人工审核的环节,这个成本也很高昂
    3) 目前的验证点粒度比较少, 但如果页面验证点颗粒很细,大多数时候页面元素不发生变化,这种验

    证效用大么?验证点增加也会带来脚本运行速度下降,维护成本增强等问题
    4) 自动化测试脚本主要用于项目发布前的回归验证。没有用到项目测试中,原因有需要更换一批新的数

    据、脚本需要更快速和业务变化同步等

     不知道其他业务型的互联网公司如何运作,让自动化脚本最大化发挥功效的?

     目前开发尚无单元测试代码,无法做到daily test。而开发没有清晰的API接口说明,开发和测试的工

    作边界不够清晰导致测试无法写单元测试。


     

  • windows利用task schedule和linux通信不得不说的几点

    2008-07-03 23:37:25

    最近随便玩玩的时候,遇到一件怪异的事情:

    脚本是:scp一个win下的文件到linux上(当然公钥事先打通的)

    表象是:在window下bat批处理文件单独run没有问题,免密码scp过去,但是放到task schedule上自动运行的时候,就出问题了,需要人工交互了。

    本想,这玩意不是和linux的crond一样吗,咋就不行呢,顿时郁闷的不行。

    后来用ssh -vvv调试了下,发现原来是task schedule模式下scp找不到密钥了,怎么回事呢?后来经过探索,发现win下的task schedule的默认用户是system,而当前的用户是administrator,豁然开朗。

    原来是这样的:直接批文件处理的时候,是admin用户去run,就在admin家目录下去找这个密钥

    放到task schedule下,默认system用户去run,结果在system家目录下没有该密钥。

    这样就很明朗了,于是用scp -i显式指定密钥的位置来搞定了,顿时很happy

    当然也有另外的解决方法,把密钥放在system用户的家目录下(目前还没有找到)

     

  • 自动化中特殊对象的变通处理

    2008-07-03 08:47:41

    by jiale

    在做自动化项目中碰到了怪异的对象,它是一个第三方提供的控件,被QTP识别为winobject,对操作进行录制结果是click了控件上的一个坐标:Window("").Window("").Page("").Frame("Frame").WinObject("ActiveX").Click 388,9,显然由于坐标受到页面大小的影响,成功回放几乎变成不可能,这有什么办法可以解决呢,我们发现可以使用tab键使控件得到焦点,于是想到了使用SendKeys,首先定位到可识别的对象使其获得焦点,然后SendKeys tab键使光标移动到需要输入的控件,再用SendKeys输入想输入的字符,ok,一切变得简单了
     好了,下面是SendKeys的使用方法
    Dim oWinApp
    Set ōWinApp=createobject("Wscrīpt.Shell")
    oWinApp.sendkeys InputText
    Set ōWinApp = nothing

     键盘给特殊键对应的入参
    Key   Argument
    BACKSPACE  {BACKSPACE}, {BS}, or {BKSP}
    BREAK   {BREAK}
    CAPS   LOCK {CAPSLOCK}
    DEL or DELETE  {DELETE} or {DEL}
    DOWN ARROW  {DOWN}
    END   {END}
    ENTER   {ENTER} or ~
    ESC   {ESC}
    HELP   {HELP}
    HOME   {HOME}
    INS or INSERT  {INSERT} or {INS}
    LEFT ARROW  {LEFT}
    NUM LOCK  {NUMLOCK}
    PAGE DOWN  {PGDN}
    PAGE UP  {PGUP}
    PRINT SCREEN  {PRTSC}
    RIGHT ARROW  {RIGHT}
    SCROLL LOCK  {SCROLLLOCK}
    TAB   {TAB}
    UP ARROW  {UP}
    F1   {F1}
    F2   {F2}
    F3   {F3}
    F4   {F4}
    F5   {F5}
    F6   {F6}
    F7   {F7}
    F8   {F8}
    F9   {F9}
    F10   {F10}
    F11   {F11}
    F12   {F12}
    F13   {F13}
    F14   {F14}
    F15   {F15}
    F16   {F16}


     

  • ntp常见问题的处理

    2008-06-30 11:52:44

    路径:
    linux:/etc/ntp.conf
    windows:%windir%/ntp.conf

    问题:

    ntpddate:no server suitable for synchronization found

    解决:

    1。确保server端的ntpd是run状态

    2。netstat -an|grep 123确保server端的ntpd是以udp方式开始服务

    3。iptables有没有禁止客户端的连接

    4。/etc/ntp.conf注释掉restrict default ignore (拒绝所有类型的ntp连接

    5。ntpd服务启动数分钟后(3-5分钟),才可以正常提供服务。

1564/8<12345678>