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

发布新日志

  • setup JMeter plugin development environment with Eclipse

    2010-06-25 11:08:51

    suppose $PrjHome is the project root directory

    • download JMeter binary and JMeter source
    • build up project directors as below
    Note only folders making sense in this guide is listed.
    <pre>
        $PrjHome
            |- src         # source code folder
            |- bin         # class files folder
            |- lib         # jars folder
            |- jmeter      # jmeter  binary copied here
                 |- bin
                 |- lib
                     |- ext
                     |- ...
    </pre>    

    • create and apply user library JMeterLibJar containing all jars in $PrjHome/jmeter/lib/*.jar
    • create and apply user library JMeterJar containg all jars in $PrjHome/jmeter/lib/ext/*.jar and $PrjHome/jmeter/bin/ApacheJMeter.jar
    • in Eclipse Package Explorer panel, right click on $ProjHome/JMeterJar/ApacheJMeter_core, select "Properties", click on "Java Source Attachment", then set soure for this jar.
    repeat this step against other JMeter jars if necessary(gererally, you will do it against ApacheJMeter_java.ar)

    • edit $PrjHome/jmeter/bin/jmeter.properties, find line "search_path" and set value as below
    <pre>search_paths=./bin
    # Note that here '.' refers to $PrjHome, ./bin is where the plugin classes files go to
    # Eclipse by default set project home as working directory when running a java application.
    </pre>

    • create a scrip to launch JMeter
    <pre>
        public class JMeterStart {
        
        public static void main(String[] args) {
            System.setProperty("jmeter.home", $PrjHome/jmeter);

            JMeter jmeter = new JMeter();

                    jmeter.start(new String[]{});

                    //if nongui. -n nongui, -t testScriptPath
            //jmeter.start(new String[]{"-n", "-t", "$Somewhere/test.jmx"});
        }
       
    </pre>

    • create source files of your jmeter plugin, say  FooRequest, and it's a java sampler.

    • run 'JMeterStart', see JMeter window appearing. add 'thread group', then add 'java sampler', in dropdown list check  FooRequest present
     
  • 正则表达式之Multiline和Dotall模式

    2010-04-21 10:59:41


    一直以来把Multiline和Dotall模式混淆了,奇怪怎么一直都没有出问题?人品?
    不过出来混总是要还的, 今天和一个同事讨论一个正则表达式终于"出丑"了.然后才把二者搞清楚.

    * multiline
    如果regexp里出现了^或者$, 那么by default只会匹配第一行. 设置了Multiline,会匹配所有行.
    比如
    • regexp: /^.*AAA.*$/
    • src: "abcBBBdef\nsdfAAAfff\nsdf"
    • without Multiline: 匹配失败
    • with Multiline: 匹配成功

    所有, 在regexp里出现了^$, Multiline才有意思, 否则是没有意义的.

    * dotall
    默认情况下, .不会匹配换行符, 设置了Dotall模式, .会匹配所有字符包括换行符
    比如
    • regexp: /BBB.*AAA/
    • src: "abcBBBdef\nsdfAAAfff\nsdf"
    • without Dotall: 匹配失败
    • with Multiline: 匹配成功


  • 过早优化是万恶之源,无论是性能优化还是代码结构优化,还是算法优化

    2009-11-17 21:31:16

    过早优化是万恶之源,无论是性能优化还是代码结构优化,还是算法优化,还是其他什么乱七八糟到优化。

    所以我拥护unittest,refactory, and xp.
  • 推荐:infoQ: 动态函数是语言精粹

    2009-05-18 14:14:45

    可以从这里下载免费电子版: http://www.infoq.com/cn/minibooks/javascript-practise

    强烈推荐给编程语言爱好者,但对编程语言的本质理解并不是很透彻,不是计算机科班出身的人,比如像我这样的。

    把以前很多关于“编程语言”里不很明确的东西都厘清楚了。
  • Backup strategies of Rainfinity QA team

    2009-03-23 15:47:18

    Problem statement
    Raininity QA team puts all important stuffs on a Linux file server. With the data volume increasing over time, to ensure the safety of these data is becoming a big concern.

    How it works
    There are three backup strategies designed to respectively apply for three different kinds of data.

    1) Personal data files
    Personal data files always are small in size and tend to change frequently.
    In this case, files will be packaged and compressed to a tgz file and copied to backup server once per week. In addition, an incremental backup will be taking place every night to backup only those changed in daytime.

    2) Product build files.
    Product build files are downloaded from build server located in US. Generally, QA engineers are likely to install the product of the latest a few builds.
    In this case, files will be copied directly to backup server as they have been compressed already. Another task is maintaining only a certain number of build on either file server or backup server. For example the latest 10 builds on file server, and the latest 50 builds on backup server. This can meet almost all product installation requirements.

    3) Software repository
    In software repository, OS installers, Vmware images, and test tools are preserved. Software repository includes a huge amount of files and quite a few of them are big files (over 100m in size). Files are rarely changed, but new files are added from time to time.
    In this case, mirror is the best backup strategy. The software repository folder will be scanned once per day to find out newly added files and mirror them to backup server.

    The backup strategies are implemented in SHELL script. In nearly one year of running, it is considered a simple but effective solution meeting backup requirements of Rainfinity QA team.
  • Rainfinity ATS成功之道

    2009-02-15 19:01:26


    Rainfinity ATS无疑是一个成功的ATS。它值得学习的地方不在于它的编码,而在于针对ATS这种特定软件,设计师在设计时做出的一些正确的决定对于我具有启发作用。

     

    总的来说,RainfinityATSKISS的又一个例证。 Keep It Simple and Stupid(K.I.S.S)

    1)  只关注系统最核心的功能。但对这个功能做非常充分的测试。RainfinityATS不想做瑞士军刀,而是只专注某一个功能的外科手术刀。设计任何ATS系统的时候我想都要把这个作为一个原则。如果测试的要求比较多,一个测试系统不能满足,那么宁愿另开炉灶,开发一个新的系统,也不要把所有的功能挤在一个系统里。

    2)  强制要求一个特定的环境,而不是让自己聪明来适应环境。RainfinityATS的初始配置工作非常麻烦,因为很多东西都要为它准备好。但好处是一旦配置好了,就能稳定的运行。

    3)  另外一个优点是充分利用了已有的工具,并且通过命令行和这些工具传递控制信息。这种方式是unix下面的惯用方式。它的好处是提高了模块间的独立性,相对于API调用。

     

    即使如此,Rainfinity ATS里面还是有一些失败的设计。这些设计几乎在所有ATS系统中都可见。保持对这些失败之处的警惕对设计人员来说是很重要的。

    1) 在错误的地方实现一个功能

    比如action groupAction group的出发点是好的,把action集合起来,定义为一个named group,然后直接引用此group即可。但是action group的问题是

    action group的功能非常简单,也就是一些action名字的集合。没有必要专门的一个类来处理。而且它导入间接性影响了理解testcase。也就是它的好处并不能抵消它带来的缺点。

    实际上action group的概念是有意义的,但它放在了错误的层内。它完全可以在testcase的层次来处理,而不用在ATS的框架里面。

     

    2)仅仅因为头脑发热而实现一个功能

    RainfinityATS里面还有一些脚本,比如到bugzilla查询bug的脚本。看得出来费了很多精力来开发,但几乎很少使用。因为即使亲自动手做这样的工作也是非常简单的。如果没有迫切的需要人们都懒得学习新的东西,所以使用率不高也在情理之中了。所以开发脚本的时候,如果它的用户是team所有的成员,那么一定不要头脑发热就开发,而是充分了解team成员的需求,在大部分人都有强烈的需求的情况下再动手。特别是这个脚本具有下面的特点的时候。

    1)  开发此脚本需要较大的投入

    2)  开发此脚本需要对已有的系统做一定的修改

     

     

     

     

  • 用好一个技术就要了解其缺点

    2009-02-12 22:05:42


    如果在你对问题的理解中,你想不出至少 3 样可能出错的东西,那么你并没有真正的理解这个问题。

                                                       ---摘自"你的灯亮着吗"


    做的项目越多,越能体会到没有所谓好的技术坏的技术”,只有合适的技术不合适的技术”。


    至少现在,在计算机界还没有通吃的技术. 设计人员应该根据解决的问题的不同,选择不同的技术;在软件的不同的层次,选择不同的技术; 根据对技术的掌握程度,选择不同的技术;

     

    条条道路通罗马,用不同的技术或技术组合都可以实现某一个功能. 最好的实现不是因为使用了最先进的技术”,也不是实现了“最复杂最全面的功能”,而是在功能和简单之间取得平衡的设计


    所以我们要用好技术,那么一定要既看到其优点,又了解其缺点.下面是对我了解比较多,也比较认可的技术的一些分析。这些分析是不全面的,写此文最重要的目的是提醒自己,以后在选择某种技术的时候,一定要分析其优缺点。

     

     

    优点

    缺点

    面向对象

    抽象数据结构(Abstract Data Structure)提供了一种更贴合现实世界的思考方式。

    每一个class有自己的名字空间,避免了面向过程程序的名字冲突。

    并不是所有的问题都是适合面向对象的思考方法。比如一段文本处理过滤程序。

    虽然继承也是面向对象技术里的标准功能,但继承带来的问题是信息被分离(分别在父类和子类中),程序更难理解和掌控。

    接口

    多态特性(动态绑定)提高了抽象的能力。提出了面向接口编程的概念。更好的隐藏了变化。

    增加了接口类的定义。

    面向接口的分析对分析人员的能力有更高的要求。设计不良的面向接口程序增加了系统的复杂性。

    面向接口比面向对象适合更大型的程序,更重型。所以面向过程的系统和小型的面向对象的系统不应该使用。

    增加抽象层

    增加抽象层可以提高灵活性,兼容变化。所谓“任何问题都可以通过增加抽象层来解决。”

    多了一层抽象层,系统的复杂性就增加了。“Unix编程环境“建议不要超过3层。

    模块化

    模块化的目标是只提供接口,而隐藏实现细节。

    模块化通过分而治之而提高了软件处理复杂问题的能力

    因为模块化隐藏了细节,外界没有机会了解其内部结构。所以对模块化的程序的健壮性,日志纪录有更高的要求。否则一旦模块内部出现问题,调用者就只能骂娘了。

    命令行

    相对于通过API调用其他模块的功能,通过命令行调用其他程序的功能实现了更高层次的隔离性。

    命令行的控制参数的传递没有API的函数参数直接,而且调用效率会更低

    管道

    管道通过输入输出链接程序是一个伟大的发明。

    1)使得程序的独立性更强,所以unix下面有很多实现单一任务的小程序。

    2)信息传递的有效性。管道实际上是一种信息处理的模式。而事实证明,有相当多的问题都可以在这种模式下解决,特别是unix下的系统管理。

    3)信息传递的简单性。一个输入一个输出,介质是没有格式的流。

    管道能解决的问题具有明显的特征。所以,不能适用于管道的地方不能也用管道去解决。

    管道之间传递控制参数比较困难。管道不是在同一个shell里运行,所以只能在管道之间共享只读参数。如果管道里面的程序修改了变量,下一个程序并不能看到。

     

  • 自动化不是灵丹妙药

    2009-02-11 22:50:23

    一天和同事聊天,他试图实现一个功能,让一个程序在系统重启后能自动启动,并且加载指定的配置。


    我分析了一下发现实现这个功能会比较复杂,主要是涉及多处配置文件的修改。回头再看看,发现这个系统很少会重启,可能一年就45次。于是我建议他放弃这个想法。因为维护配置文件会成为一个负担,考虑到系统重启的频率,这会是得不偿失。


    但是看来他并不以为然。他说他的目标是这些配置工作完全不用人来参与,“最好是在家里动一个手指所有的配置工作都自动化的为我做好了”。看到他信心满怀的样子,我不愿意扫他兴。但我相信如果即使有一天他真正实现了这个目标,维护这个自动化系统也会让他寝食难安。


    这样悲观的看法,我想在两三年前我肯定没有。那个时候我像他一样对“自动化”抱有无限美好的期望,好像只要测试自动化了,软件测试工作马上变得和“公务员一样轻松”,只需要动一下指头,所有的testcase都自动化得跑起来。


    但随着做了更多的自动化测试项目,也看了更多的成功和失败的案例。对自动化的特点了解得来越多,对自动化的期望也在一直不断的下降。


    这种看法的变化,我倒觉得是越来越贴近真实的“自动化测试”。


    如果要充分利用一个工具,一定要了解其特点。现在在业界,自动化软件测试就像一个人见人爱的香馍馍。自动化测试好像已经和“高科技”,“高测试效率”,“成熟的测试team这些褒义词联系了起来。在这种一边倒的氛围下,自动化程序的缺点和不足和必须要付出的代价被掩盖了起来。


    认识自动化的不足,我觉得首先要转变的一个想法是“自动化测试并不是用来发现bug的”。原因很简单,自动化测试基于testcase,但所有的bug中只有大约1/4是仅仅按照testcase来测试就能发现的,其它的bug,来自于聪明的“人”的经验,分析,发散思维和说不清道不明的“灵光一闪”,而这些特性对于自动化程序来说完全是无能为力。所以,幻想“动一下手指”,所以的bug都被自动化程序发现出来是完全不可能实现的。


    自动化另外一个特点是自动化本身也是程序,也需要投入大量的人力来实现。一个软件买出的copy越多,它的价值越大。对于自动化测试程序来说,它运行的次数越多,它的价值越大。有下面一些原因都可能减少自动化测试程序运行的次数,甚至导致自动化项目的失败。


    1)测试产品功能或界面变化频繁

    2)自动化的case本身不需要频繁的测试,比如安装过程或者一些非核心的功能

    3)自动化程序不稳定,容易跑“死”掉


    看到了一些自动化测试程序因为这些原因而效果大打折扣,我对“自动化一切”的热度慢慢退烧了。


    最后一个需要注意的自动化测试程序的特点是,自动化测试程序不是商业产品,它的用户都是专业人士,所以它不用商业产品那样高的扩展性,灵活性,可配置性,友好的交互性。因为这些特性的得来是要付出高昂的代价的,那就是人力投入和软件的复杂度大大增加。对于设计师来说,如果要在这些特性和简单中选择的话,一定要选择简单。


    1)对于错误处理要简单直接,而不要灵活和聪明。打印错误并直接退出是最好的选择,不要试图猜测错误的根源并试图从错误恢复。这里包括用户输入,环境错误等。

    2)对于环境设置,要求单纯一些,不要去兼容环境变化。一般来说测试环境都是有测试人员在维护。试图兼容环境可能导致代码大大增加。

    3)对于自动化测试的代码来说,也不要用太炫的设计技巧和复杂的设计模式。因为自动化测试的代码最好能被使用它的测试人员读懂,甚至能做简单的修改和排错,这样能提高自动化测试的次数。


    对自动化期望不能太高和自动化程序不要设计得太完美,是我对自动化测试程序设计和使用过程中获得的最深刻的体会。

     

     

  • 过度设计

    2009-02-11 22:47:42


    我觉得我一直都有过度设计的倾向。对面向对象,接口编程,抽象层,设计模式,插件化。。。所有提高软件灵活性,可配置性的技术都乐此不彼。后来发现使用这些技术本身也是有代价的,那就是增加了软件的复杂性。再后来,读了“unix编程艺术“,我发现我的问题不仅仅是没有对技术做全面的评估,而且在解决问题的思路上也是误入歧途。


    不得不承认,所有这些新技术确实能取得“自我欣赏”的效果,但事隔一段时间后再重读代码,也有“摸不着头脑”的效果。如此反复几次,我才发现了是这些抽象的层,数据结构让我难以抓住程序是如何实际解决问题的。


    在以前我认为事情的发展是这样的:软件要解决的问题越来越复杂,所以软件变得越来越复杂,为了降低复杂性,人们发明了新的技术。


    但事情的另一面是,新的技术本身比旧的技术要复杂。也就是新技术本身也引入了复杂性。


    所以要做出正确的设计,需要评估新技术引入的复杂性和降低的复杂性。以前的我,只看到事情的一面而不顾另一面,难免会出现所谓的过度设计。


    另外一个更根本的问题值得我反思,这种复杂性是必需的吗?有些情形,这种复杂性完全是自找的


    1)没有找到解决问题的巧妙的方法

    或许多了解一点,或许转变一下思路,就有非常简单而且巧妙的方法来解决问题。而且以效率最高的方式。

    关于圆珠笔的故事,关于左右手不能同时操纵机器的故事,关于剔除空肥皂盒的故事。这些故事都说明了,一个巧妙的解决问题的方法的令人惊叹的效果和效率。


    2)试图让程序更聪明

    如果你读了unix编程环境,你就会理解KISSkeep it simple and stupid)是一个多么智慧的箴言。与其让程序兼容变化,不如让这个地球上最聪明的人来处理变化。


    我曾经写了一段程序来处理ftp传输文件,后来想到如果能兼容scp会更酷,加入scp的过程中,发现如果加一个抽象层来处理所有能传输文件的协议还会更酷。最后的结果是代码由几行变成了几百行。而且事实是,从来没有用户试图用scp来传输文件。

    所以这种复杂性完全是自找的。也是完全可以避免的。


    现在如果让我在程序的功能和程序的简单直接做出选择,我首先选择简单。

  • 关于c++和其他一些语言的废话

    2007-07-27 11:03:25

    关于c++和其他一些语言的废话

    我的语言学习历程是这样的,最开始在大学里学习c,然后自然发展到c++。c语言做过比较大的项目,开发单片机上的驱动。c++没有做过大项目,当时觉得学得还不错了,现在回头看,除了设计方面不说,即使c++语言本身,也有很多地方也没有搞清楚。

    大学毕业一年后,开始转到Java。java是一门无论语法还是库得设计都很清晰的语言,Java特别适合开发大型程序。它的这些优点都说的太多了。在它这个级别,可能c#是唯一的对手,不过我对c#还一无所知。

    这几年,也学习了一些脚本语言,用的最多的是Ruby和Javascrīpt。我个人观点是,Ruby是脚本语言里设计最好的语言,当然相比perl和python它出现最晚。Ruby的语言我觉得有两个特点最让人赞叹
    1)核心小而精干,想想一个事实是,它的private和public竟然都实现为一种函数,而不是语言本身的内在特性。这就使得在它上面添加新的特性比较容易,不会侵入语言核心。
    2)Ruby可能是脚本语言里面对lambda支持最精彩的,lambda本身的特性使得很多问题有了优美的解决方式。想想它的Collection库。

    相对于Ruby,perl的优势是互联网上庞大的library,但它不愧号称hacker的语言,语法实在是不敢恭维。

    Python最大优势是“看上去更简单的语法”。但这点优势也在被它自己慢慢丢弃。看看它不断往语言里面加入的东西。

    在Web client端运行的语言你几乎没有选择,只能是javascrīpt。不要对我说还有VBscrīpt,我认为VB这样的语言在这个世界大行其道简直是一个奇迹,一个MS用它的垄断和金钱砸出来的一个变态的奇迹。javascrīpt据说是最被低估的语言,c的语法外衣,函数式语言一样的动态特性。javascrīpt可以写出一个c程序员永远想不到的代码样式,看看prototype库。我建议我们都用prototype库,用它的风格写代码。一个ruby程序员会发现它非常熟悉。:)

    对函数式设计语言也有相当的兴趣,这是一个完全不同的世界,我还是初学者。对一个语法完美主义者来说,scheme肯定是最佳学习选择,但实用的机会不多。能接触到的最多的是emacs的elist和autocad的visual lisp。这些场合的lisp都是作为象sh一样的脚本调用application环境的命令,不知道高阶函数和延迟求值这些特性做应用开发能不能用上。

    说了这么多废话其实都是因为这几天又重新学习c++,总是把c++和java对比,感触很多。最主要的感觉有两个,
    1)c++太复杂。它支持4种风格的设计:c语言风格,抽象数据结构(Abstract Data Type), 面向对象设计和范型程序设计。单独的每一种都不算复杂,但要支持了4种风格,不可避免的c++成为一门复杂的语言。听说它的设计者都不指望人们能完全弄懂它。我想对应用者来说我应该,不排斥任何一种,但尽量使用最基本最简单的东西。在某种实现方式可能变得复杂或使用高级技巧的时候,保持警惕,宁可多写一些简单的代码,而不要”通用“但”精妙“的代码。

    2)内存管理。内存管理可能永远是c/c++程序员的恶梦。为人称道的Loki的smartpointer可能设计很高妙(其实我并没有真正读懂),但我认为它使用了对我来说太复杂的技术。我的原则是首先考虑在栈上申请对象,因为系统会为我释放对象,如果要在堆上申请对象,那么设计一个factory,在同一个地方申请和释放对象。
Open Toolbar