Hi, 如果有任何想法与我沟通, 请用: lifr_nj 在 msn.com

发布新日志

  • Jmeter之测试数据参数化

    2010-07-21 17:40:18

    * jmeter参数化之一: 分类

    jmeter的参数化分为四种

    1) 所有环境配置常量
        比如server address, port, etc.
        作用范围是所有testcase

    2)  关于test压力的配置参数
        比如thread number, loop number, etc.
        作用范围是特定的testcase

    3)  virutal user特定的量, 一般是测试逻辑相关的数据
        比如user name, password, etc
        作用范围是某一个vu, 但是无论loop是多少, 值都是一样的

    4)  每次引用都不一样的量, 一般是测试逻辑相关的数据
        比如queryKey, etc
        没有作用范围, 每一次对该变量的引用都是不一样的.

    * jmeter参数化之二: 静态量

    对于第一种和第二种来说, 为了达到最好的参数化效果,需要下面两步.
    1) 创建环境配置参数文件,  和压力配置参数文件, 在调用jmeter的时候把参数传入
    jmeter -t mytc1.jmx -q testenv.properties -q mytc1.properties

    2) 创建testplan级别的UserDefinedVariables
    为上面两个文件里的每一项创建一个条目, 比如
       serverAddr  ${__P(serverAddr, www.abc.com)}
       threadNum   ${__P(threadNum, 1)}
    这样做的好处是, 在ide里调试的时候, 即使没有配置文件, testplan仍旧可以运行, 使用此处定义的"缺省值"


    * jmeter参数化之三: virtual user特定的量

    使用Pre Processor -> User Parameters控件. 该控件参数的形式是
    VariableName User1 User2 ... Usern
    loginName    LUcy  Dean  ... Jack
    passWord     123   231   ... 321
    每个virutal user取的值永远都是一样的, 无论loop是多少

    * jmeter参数化之三: 每次引用都不一样的量

    最重要的是CSVDataSet, 这样你可以使用外部的datasource. 使用CSVDataSet需要注意两点
    1) csv文件和jmx文件要在同一个目录
    2) csv的column名字(也就是引用的名字)需要配置, 在Variables Name配置项, 名字用逗号','分隔.

    另外还有随机数Random Variable, 可以是virutal user特定,也可以是每次引用都不一样, 取决于你的配置.
  • Jmeter小技巧

    2010-07-21 17:36:25


    * 当使用Proxy server来record request的时候, 如果字符串已经在User Defined Variables控件里定义, 那么jmeter会做自动替换.
    比如web site是www.example.com, 而在你的UserDefinedVariable里定义了
                 site www.example.com
    那么所有出现www.example.com的地方, 都被自动替换成了${site}

    * 使用CSV data set
    在使用csv dataset的时候, 数据文件的columns必须被配置.
    比如数据文件包括用户和密码两个columns,
    jack    abc123
    lucy    xyz234
    那么配置此csv dataset控件的时候, variable names可以是"USER,PSWD", 然后可以通过${USER}, ${PSWD}来引用


    * 设置启动jmeter的jvm的heap size
    设置环境变量如下
    set JVM_ARGS=-Xms256m -Xmx512m



  • WATIR小技巧

    2010-07-20 10:04:52

    *通过子节点定位父节点
    有时候我们想得到的节点并不好定位, 但是它的某个子节点比较好定位. 这时候就要1)先找到子节点, 2)然后回溯到父节点.
    比如下面是一个tree node的结构
    <table><tbody>
        <tr>
            <td><a><img src="plus.gif"/></a></td>
            <td><span>NodeABC</span></td>
        </tr>
    </tbody></table>

    任务是点击<a><img src="plus.gif"/></a>展开此节点, 但是因为此tag并不好定位, 所以采取的定位路径是
      <span>NodeABC</span> 到 <tr> 到 <a><img .../></a>

    ruby code:
        sp = $b.span(:text, "NodeABC")
        tr = sp.parent.parent
        tr = Watir::TableRow($b, :ole_object, tr.old_object)
        if tr.image(:src, /plus/).exists? then tr.links[1].click end


    注意:
    1. 向上回溯会用到一个API Watir::Element.parent
    2. 通过上面得到的父节点是Element实例, 如果要使用特定tag类型的方法, 还需要"通过Element"构造"特定tag的实例"

    * 让WATIR更好的支持ajax
    WATIR开发之初并没有考虑到支持ajax, 所以你必须自己负责检测某个元素已经就绪.如下面的代码所示:
    btn = $b.button(:id, "btn1")
    Watir::Waiter.wait_until(10, 1) { btn.exists? }
    btn.click

    这样虽然可行, 但是代码显得啰嗦了点. 后来看了源码, 觉得可以通过覆盖Element的assert_exists?方法来改进一下.

    因为几乎所以元素的操作,比如click, set, ...都会调用assert_exists?方法,所以可以在此方法内做wait, 如下所示
    module Watir
        class Element
            def assert_exists
              Watir::Waiter.wait_until(10, 1) { exists? }
              unless ole_object
                raise UnknownObjectException.new(
                 Watir::Exception.message_for_unable_to_locate(@how, @what))
              end
            end
        end
    end

    这样, 上面的测试代码就可以简化为一行代码.
    $b.button(:id, "btn1").click

    注意: 本方法只是小范围测试通过. 不能保证所有情况下都好用.

  • 此贴用来跟踪rfint ta项目中的经验,教训和体会

    2009-11-24 16:07:27


       RFint是目前team测试的项目。它的大部分testcase已经ready,并开始了manualtest。现在要开始自动测试的开发。

    测试环境

        * 一台celerra cabinate,包括至少两个datamover
        * 一台clariion作为后台storage
        * 若干linux client
        * 若干solaris client
        * 若干windows client
        * 也许还有hpunix client


    1. 分层
    主要分成3层。

    最上层(distribution runner)
        主要负责处理“在多个client上运行测试”的问题。具体包括测试程序的deploy,execution and report generation。
        用ssh/scp来处理网络通信,用nfs/cifs server来处理文件共享/交换的问题。(don't invent wheels)
        这一层用bash开发

    中间层(test runner)
        中间层包装test这样一个概念。test是一系列相关testsuite/testcase的集合
        test里所有的testsuite/testcase共享相同格式的testenv, testconf
        test里所有的testsuite/testcase共享library,实现代码重用。
        中间层还向最上层提供了统一的调用接口
        中间层可以用任何合适特定test的语言开发(向上的接口基于cli)
        test的范围的划分是考验经验的。小的test更容易理解,但代码重用性低。

    最下层(test logic implemenation)
       具体的testsuite and testcase, 执行实际的测试逻辑
       在testsuite层次,所有的testcase可以共享testconf,setup,cleanup和library
       一般和中间层使用相同的开发语言

    1. 从自动化测试的角度,测试可以分成两种
    一种是数据驱动的,这是程序擅长的。
    一种是过程驱动的,这是人类擅长的。

    一般regular的testcase容易数据驱动
    一般negative的testcase都是过程驱动的

    应该尽可能把过程驱动的testcase转化为数据驱动的testcaes。

    1. 如何把过程驱动的testcae转化为数据驱动的testcase
    构造更通用的测试环境,满足更多的testcase
        比如有两个关于文件copy的case,一个是在folder内部copy,一个事跨folder copy,那么构造一个多folder的环境,就能满足这两个testcase的要求

    构造更丰富的操作集合,包括多个testcase中的操作
        比如一个testcase是关于文件写操作,另外一个是关于文件读操作,那么构造一个既包括文件写又包括文件读的操作集合,就能实现这两个testcase的覆盖要求

    关键字驱动
        有时候,仅仅是data还不足以覆盖所有的测试。这时,可以加少量能“影响”测试逻辑的关键字(keyword)。
        比如对于文件写有“同步”和“异步”两种,那么可以加入对应的关键字。但增加这样的关键字会提高测试逻辑的复杂性,所以一定要把握好度。

    通过上面的方式,可以程序擅长的方式处理更多的testcase。
       
    1. 自动化测试case和手工测试case不用一一对应
    由上可见,自动化的case和手工测试的case很不一样,完全不应该一一对应。

    1. 写简单的程序
    最上层和中间层通过cli的方式调用,它们完全是独立的。

    中间层和最下层是API级的,需要小心不要让他们联系太多。现在中间层只为最下层提供testenv, testconf和common library.

    1. testresult打印到testlog里
    没有专门的test result文件,而是打印到testlog里。这样的好处是
        简化了log的管理,framework的代码更简单
    劣势是需要另外的程序来从testlog中吧result parse出来,在重新格式化。

    1. setup/cleaup在那里执行的问题
    在test level有setup和cleanup,这没有什么问题,但到底是testsuite还是testcase level加入setup/cleanup,这是一个问题。

    现在的方案是在testsuite level。也就是在开始运行testsuite里的testcase之前,执行setup,然后依次执行testcase。 而不是,在运行每一个testcase前都运行setup。
    这样的好处是,testcase可以实现自己的setup/cleanup,但framework不负责管理他们。






Open Toolbar