没有进入TC前,在自己做过的一些小型项目中(或者根本不能称其为项目,只不过是自" />

几个测试用到的framework和tools

系统 1538 0
最近一阶段,由于项目的需要,粗略的看了看测试用到的几种framework和tools,胡乱写了些东西,主要针对自己对于这几种framework的理解,这里只起到抛砖引玉,具体细节请查看每个framework自己的官方网站

啊?“测试”有这么重要? <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

       

        没有进入 TC 前,在自己做过的一些小型项目中(或者根本不能称其为项目,只不过是自己写的一些程序)基本没有做过比较体系的测试,更不用提应用一些 framework 或是一些工具来进行测试,那时候的测试往往就是在一定的位置上 print 出结果,与预期的结果相比较,从而知道程序的对错。进入 TC 后,发现每一个开发团队都有各自的 QA ,而且有些团队 QA 的人数并不少于开发人员,测试的重要性在这里可见一斑。阅读了一些关于测试的文章,尤其是 X-Programming 的一些材料后,才认识到测试工作如此重要。“ Program a little, test little , 貌似平淡无奇的一句话,但却是所有项目尤其是企业级项目成功的保证。从某种程度上说, QA 肩负着比开发人员更重的使命。

        鉴于测试有如此重要的地位,而且我有可能(只是有可能而已)参与 GTSS 的测试项目,所以近一个星期以来一直在对“测试”进行研究。粗略的学习了一下用于测试的一些 framework 和工具,其中包括 JUnit, JMeter, HttpUnit, JWebUnit, 并下 Fund Connect 近期完成的 Performance Test 进行了研究。

 

想把学到的东西给大家看看

 

        我的习惯是把一个阶段学习到的东西总结一下,将其变成文字,这样才能对学到的东西加深印象,也在成文过程中发现不明白不理解的地方。往往我写出的东西,都是给自己看的,加深个印象也就算了,但是这次为什么想和大家分享呢?并非炫耀自己有多么能干,学了多少东西,因为我深知看我这篇东西的人各个都比我能干,每一个人懂得都比我多。主要原因是:和大家不同,我不是做技术出身,只是单纯对技术有兴趣,想深入了解技术,由于专业知识的欠缺,肯定在学习和应用过程中会出现很多偏差,理解上也会有很多不对的地方,希望大家及时指出,我好及时更正。

       好了不多罗嗦了,开始正题!(欢迎大家拍转)

 

JUnit 单元测试的基础

 

        我可以大言不惭地说, JUnit 本身是一个相当简单的框架,想必各位也对其做过一些研究,所以直接给出一个自己写的简单的例子,来说明 JUnit 的特点。

 

// Money.java:

 

public   class  Money  {

        
private   int  amount;

        

        
public  Money( int  i) {

               amount 
=  i;

        }


        

        
public   int  amount() {

               
return  amount;

        }


        
public  Money addMoney(Money mon) {

               
return   new  Money(mon.amount() + this .amount());

               

        }


// The key point here

        
public  boolean equals(Object o) {

               
if (o instanceof Money)

                       
return  ((Money)o).amount()  ==   this .amount();

               
else  

                       
return   false ;

        }


}
 

 

// TestMoney.java

 

import junit.framework.
* ;

 

public   class  TestMoney extends TestCase {

        Money m11;

        Money m12;

        Money m13;

        
protected   void  setUp() {

               m11 
=   new  Money( 11 );

               m12 
=   new  Money( 12 );

               m13 
=   new  Money( 13 );

        }


        

        
public   void  testEquals() {

               Assert.assertEquals(m11,
new  Money( 11 ));

               

               Assert.assertEquals(m11,
new  Money( 11 ));

        }


        

        
public   void  testAdd() {

               Money m23 
=   new  Money( 23 );

               Assert.assertEquals(m11.addMoney(m12),m23);

               Assert.assertEquals(m11.addMoney(m12),m11);

               

        }


        

        
public   static   void  main(String args[])  {

               junit.textui.TestRunner.run(TestMoney.
class );

        }


        

}


        看到这里你可能会骂我把小孩子都能写出的东西贴到这里来丢人,其实就是这么个简单的例子足以说明 JUnit 的运作原理。 class Money 重载了方法 equals(), 就是为了进行 Money 对象之间的比较。这样的比较在 JUnit 中是通过断言的方式进行的,由于基础类 TestCase 继承于 Assert 类,从而继承了 Assert 类提供的所有断言方法。所以一句话概括, JUnit 是通过断言机制进行底层对象间的比较来判断功能正确与否的。你可能会抬杠的说:“不仅是对象吧, JUnit 也可以比较两个 int 或者其他的 primitive data 啊!”,但在 OO 的理论中, Java 中的 primitive data 也应该是对象(如 SmallTalk 中的实现),但 Java 出于对性能的考虑,对 primitive data 没有采取类的实现方式,但同时也给出了各个 primitive data wrapper class

最初认识到 JUnit 的这样的工作原理,我有些失望怀疑它能否胜任复杂的商业逻辑的测试,看到了 Fund Connect performance test 中测试 service 部分的代码,我这样的疑虑被消除了。下面节选一段代码说明:

public   class  AdminServiceTest extends TestCase

{

        
private   static  Log log  =  LogFactory.getLog(AdminServiceTest. class );

        
private   static  ServiceFactory factory;

        
protected   static  AdminService ds;

        
private   static  ServiceConfigurator serviceConfig;

        
private  Statement stmt;

        
private  ResultSet rs;

        
private  String sConnStr;

        
private  String sqlStr;

        
private  Connection conn = null ;



    
/**/ /* *

     * Constructor for AdminServiceImplTest.

     * @param arg0

     
*/


    
public  AdminServiceTest(String arg0)

    
{

        super(arg0);

    }
    

             
protected   void  setUp() throws Exception

            
{

                 
// ……

             }


             
protected   void  teardown() throws Exception

             
{

                 
//  …..

             }


 

             
public   void  testGetFundProcessors()

            
{

        

sqlStr 
=   " select distinct Fund_Processor_uid from                               FUND_PROCESSOR_INSTR_XREF  " ;

               
try   {

                       rs 
=  stmt.executeQuery(sqlStr);

                       List result 
=  (List)ds.getFundProcessors();

                       
int  i  =   0 ;

                       
while (rs.next()) {

                               i 
++ ;

                       }


                       assertEquals(i, result.size());

                       

               }
  catch  (SQLException e)  {

                       e.printStackTrace();

               }
  catch  (AdminServiceException e)  {

                       e.printStackTrace();

               }
       

               }


               
// ……

            }



 

          从这个例子中可以看到,无论是多么复杂的逻辑( testGetFundProcessors )最终都能转化成底层对象通过断言的比较(红色字体部分)。“ Everything is object. , JUnit 的工作原理决定了它应该是单元测试的基础。

         另外,我也看了一下 JUnit 的源码,代码并不是很多多,由于应用了一些模式,使其结构设计较好。例如: TestCase 类中,在设计 run ()方法的继承问题时,应用了 Template Method Pattern 对于多个 test 方法,要有针对性地生成相应的 TestCase ,应用了 Adapter Pattern ;等等。大家有兴趣的,可以对其源码进行研究。

 

强大的测试工具 JMeter

        我看过的所有的 Apache 的项目,都很成功。 JMeter 也不例外,说其强大,我个人认为有以下三个原因:

1、 较为友好的图形用户界面,易于测试人员使用,只要明白其中的原理用 JMeter 作测试是件愉快的事情而且它能够方便的生成测试脚本。

2、 ThreadGroup 概念的引进,这个概念在 JMeter 是相当重要的,之所以 JMeter 能够完成对各种不同服务器的压力测试与性能测试,也仰仗着 ThreadGroup 。在一个 ThreadGoup 中可以规定应用的线程数量( Number of Threads 每一个线程代表一个用户),也可以规定用户行为的重复次数 (loop count) 。在企业级应用的测试中,模拟多个用户同时执行操作或同时处理数据的操作,利用 ThreadGroup 可以轻松实现。

3、 JMeter 将大量的 Test Target 作了非常好的封装 , 用户可以直接使用这些封装好的部件 , 大大减少了测试的工作量。比如测试 WebService 用的 WebService SOAP Request 测试网页的 HttpRequest ,测试数据库连接的 JDBC Request 等等。测试工作进而简化成了选择组建,将各个组建有逻辑的组织在一起的过程。

        对于 JMeter 的强大以及其应用方法,因为大家都懂,所以我在这里不多说了。下面谈谈个人认为 JMeter 的不足之处。为了更清楚的说明这个问题,我将结合 Fund Connect 项目中,对于 Server Performance Test 的一些 JMeter 脚本进行阐述。其中的一个 Requirement 如下:

 

Investors submit trades via GUI

 

Description : 15 investors log into FundConnect via GUI. Each investor submits 20 orders via a file upload.

Precondition: 20 investor institutions and 20 investors (one investor per investor institution) are set up in FundConnect.

Step: A JMeter script will execute the following steps: Log In à Start in Investor Home à Upload Multiple Orders à Select upload file à Submit file à Return to Investor Home.

Note: Each investor should upload a different file. The script should record the average time to execute the entire loop (Investor Home to Investor Home).

 

        想必大家对这个需求再清楚不过了(毕竟刚完成测试工作)。用 JMeter 测试中有一个关键的组件(其余省略不说了):

HttpRequest

Name /fundconnect/FCUploadOrdersServlet

 

Send Parameters With the Request

Name                         value

thisURL                     /inv/upload_orders.jsp

submitURL               /inv/upload_orders_summary.jsp

cancelURL               /adm/index.jsp

 

Send a file with request

File name: D:\datatest\datatest\20order_upload\testdata\uploadorders_20_acct1.csv

Parameter Name: uploadfile

MIME Type: application/octet-stream

 

     这个 Request 是向 FCUploadOrdersServlet 发出,其间传递了三个参数和一个文件,完成上传 order 文件的工作。这个需求到此也就结束了,但大家有没有想过,如果把需求改成 : 15 investors log into FundConnect via GUI. Each investor submits 20 orders via web page. 即如果要求这 15 个投资者通过 web (非上传文件方式)递交 20 不同的 order ,模拟这样的测试该如何进行呢? JMeter 针对这样的 Web 页面操作的测试,实现起来比较复杂。(如果谁认为不对,可以联系我,把你的方法告诉我)。我个人认为做 Web Application 页面上的功能测试,使用下面谈到的两个框架,实现起来比较简单。

 

Web Application 自动化测试 FrameWorks HttpUnit     JWebUnit

 

HttpUnit 本身并没有测试功能 , 说白了 , 它不过包含了一些类库 , 可以用来模拟出一个浏览器 ( WebConversation ) 并可以模拟用户在网页上的多种行为。 HttpUnit 没有测试的功能,所以它要结合 JUnit 来完成 Web 测试的工作,例如下面是一段简单的代码:

import junit.framework.TestCase;

import com.meterware.httpunit.WebResponse;

import com.meterware.httpunit.WebConversation;

import com.meterware.httpunit.WebForm;

import com.meterware.httpunit.WebRequest;

 

public   class  SearchExample extends TestCase  {

 

   
public   void  testSearch() throws Exception  {

      
// 模拟浏览器

      WebConversation wc 
=   new  WebConversation();

      
// 对google主页发出request,并得到response

      WebResponse resp 
=  wc.getResponse(  " http://www.google.com " );

      
// 从Response中抽取出第一个table

      WebForm form 
=  resp.getForms()[ 0 ];

      
// 在搜索的text field called q中填写”HttpUnit”

      form.setParameter(
" q " " HttpUnit " );

      
// 点击提交按钮

      WebRequest req 
=  form.getRequest( " btnG " );

      resp 
=  wc.getResponse(req);

      
// 通过反馈回来的response来判断叫做HttpUnit的link是否存在

      assertNotNull(resp.getLinkWith(
" HttpUnit " ));

      
// 模拟点击连接的功能

      resp 
=  resp.getLinkWith( " HttpUnit " ).click();

      
// 通过title来判断返回的reponse的title是否为HttpUnit

      assertEquals(resp.getTitle(), 
" HttpUnit " );

      assertNotNull(resp.getLinkWith(
" User's Manual " ));

   }


}



你可以发现上面的一个例子, 已经完成了对于在 google 中查找 HttpUnit 关键字的测试。

在此基础上, JWebUnit 更近一步,它实际上是建立在 HttpUnit JUnit 框架之上,将二者功能结合、重构后的产物。同时, JWebUnit 提供了更加易用的 API 来模拟用户对 web 界面的操作,同样是上面的代码, JWebUnit 的实现如下 :

import net.sourceforge.jwebunit.WebTestCase;

 

public   class  JWebUnitSearchExample extends WebTestCase  {

 

   
public  JWebUnitSearchExample(String name)  {

      super(name);

   }


 

   
public   void  setUp()  {

      getTestContext().setBaseUrl(
" http://www.google.com " );

   }


 

   
public   void  testSearch()  {

      beginAt(
" / " );

      setFormElement(
" q " " httpunit " );

      submit(
" btnG " );

      clickLinkWithText(
" HttpUnit " );

      assertTitleEquals(
" HttpUnit " );

      assertLinkPresentWithText(
" User's Manual " );

   }


}




      我相信不用加任何注释 , 大家也可以轻松的理解每一步操作。接下来我应用了 JWebUnit 测试了 Fund Connect web 页面上的一些功能 , 下面列出了以 Admin 身份登陆 , 对增加 Fund 这样一个功能的测试 :

 

import net.sourceforge.jwebunit.WebTestCase;

import org.xml.sax.SAXException;

import com.meterware.httpunit.HttpUnitOptions;

import com.meterware.httpunit.WebConversation;

import com.meterware.httpunit.WebResponse;

 

public   class  AdminTest extends WebTestCase {

    
public   static   void  main(String [] args) {

               junit.swingui.TestRunner.run(AdminTest.
class );

        }


        
public   void  setUp() {

               
// get rid of Java Script check

               HttpUnitOptions.setExceptionsThrownOnScriptError(
false );

               
// set the base url for this test

               getTestContext().setBaseUrl(
" http://tcsunfire04.zdus.com:9220 " );

               
// set username and password to get through SiteMinder         authentication

               getTestContext().setAuthorization(
" bos.ssb.dwf " " 123 " );

               
// set the cookie required

                getTestContext().addCookie(
" SMCHALLENGE " " YES " );

 

        }


               

        
public   void  testSiteMinder() {

               
// test wether test can get through SiteMinder or not

               beginAt(
" /fundconnect/adm " );

               assertTitleEquals(
" Global Link Fund Connect " );

        }


        
/**/ /*

         *Test for adding a new Fund

         *Fund long name: star's Fund

         *Fund short name: starFund

         *Fund Provider: Starhero

         
*/


        

        
public   void  testAddFund() {

               beginAt(
" /fundconnect/adm/maintfunds_funddet.jsp?add=new " );

               
// Fill in the add fund form

               setFormElement(
" fundInstrumentLongName " , " star's fund " );

               setFormElement(
" fundInstrumentName " , " starFund " );

               setFormElement(
" fundInstrumentCode " , " 123567 " );

               selectOption(
" fundCodeType " , " ISO " );

               selectOption(
" timeZone " , " (GMT+08:00) Asia/Shanghai " );

               selectOption(
" fundProviderIndex " , " Starhero " );

               selectOption(
" settlementCurrency " , " USD -- US Dollar " );

               selectOption(
" partialShares " , " No " );

               setFormElement(
" contactName " , " Brooks " );

               setFormElement(
" contactPhoneNumber " , " 13989472700 " );

               selectOption(
" investmentType " , " Short Term " );

               selectOption(
" assetClass " , " EQUITY " );

               selectOption(
" industry " , " DEVELOPED " );

               selectOption(
" countryRegion " , " UNITED STATES " );

               selectOption(
" benchmark " , " AUD LIBID " );

               selectOption(
" domicileCountry " , " United States " );

               setFormElement(
" defaultPrice " , " 50 " );

               

               selectOption(
" fundInstrumentCountries " , " United States " );

               selectOption(
" institutionSelect " , " lon.ssb " );

                       

               setFormElement(
" cutoff " , " 22:00 " );

               selectOption(
" cutoffType " , " Hard Cutoff " );

               
// submit the form

               submit(
" sbmtSubmit " );

                
// According to the fund's long name and fund's short name to assert

                
// that fund is added

                assertTextPresent(
" star's fund " );

                assertTextPresent(
" starFund " );

               

        }
    

}


 

        由此看出 , JWebUnit 可以完成 Web 页面上复杂应用的测试。可以在以后的项目中逐渐使用。

 

  写在后面      

 

        首先得感谢你,能够耐得住性子看到这里,浪费了你宝贵的时间深表歉意。以上就是我对近期对于测试工具及 FrameWork 研究的小结,有不对或不妥之处还请指正。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

                                                                                                                                    小川

          <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /><date year="2005" day="12" month="7">7/12/2005</date>

几个测试用到的framework和tools


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论