Jmeter效能測試之如何寫Java請求測試案例類__Java

來源:互聯網
上載者:User
一. 引言:

最近工作中的一個項目要求做效能測試,該項目由提供服務的幾個應用組成,選用的架構是阿里巴巴公司開源的服務架構Dubbo。關於Dubbo的介紹,網上也有很多資料,本人只是做了粗略的瞭解,沒有深入研究,相關資料地址如下:http://www.iteye.com/magazines/103,http://alibaba.github.io/dubbo-doc-static/User+Guide-zh.htm#UserGuide-zh-%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95%E6%8A%A5%E5%91%8A,http://www.oschina.net/p/dubbo, 應用執行個體(含源碼):http://blog.csdn.net/wilsonke/article/details/39896595,http://download.csdn.net/detail/u012049463/6338227

Jmeter(官網:http://jmeter.apache.org/download_jmeter.cgi)做為一款開源的效能測試工具,提供了詳細的使用者操作手冊、demo以及api文檔,一直都是我們做效能測試的首選,不過之前大多做的都是Http請求的測試,對介面形式的Java請求測試並沒有實踐過。最快的學習方法就是從網上找例子,依葫蘆畫瓢就成,的確我也是這麼乾的,雖然網上類似的文章也很多,不過這裡還是想對自己的實踐過程做個記錄。^^ 二. 本文: 1. 怎麼寫Jmeter介面測試的java測試類別

其實,Jmeter已經給我們提供了一個java sampler測試案例類的架構了,在api文檔(軟體包的apache-jmeter-2.11/docs/api/index.html路徑下)中我們可以看到org.apache.jmeter.protocol.java.sampler包中有一個介面JavaSamplerClient和一個抽象類別AbstractJavaSamplerClient,我們的測試案例類只要實現它提供的介面或者直接繼承這個抽象類別就可以了。

JavaSamplerClient介面定義了四個方法:

getDefaultParameters() 用於擷取介面的參數;runTest(JavaSamplerContext context) 用於寫具體的測試案例,類似於LR的Action,在抽象類別AbstractJavaSamplerClient並沒有寫該方法的實現,測試案例當然是要我們自己去寫實現了;setupTest(JavaSamplerContext context) 初始化方法,類似於LR的init和Junit中的setUp();teardownTest(JavaSamplerContext context) 類似於LR的end和Junit中的tearDown()。

費了這麼多話,還是趕緊用上面網上的例子(http://download.csdn.net/detail/u012049463/6338227)來說明下吧,建立一個Java項目(最好是maven項目,這樣打包方便),引入Jmeter中lib\ext基礎包:ApacheJMeter_java.jar、ApacheJMeter_core.jar就可以開始編寫測試類別了。

本例中,服務端提供的服務介面和具體實作類別

package com.huangjie.dubbo_Service.service;public interface IProcessData {      public String setAge(String age);      public String sayHi(String name);  }
package com.huangjie.dubbo_Service.service.impl;import com.huangjie.dubbo_Service.service.IProcessData;public class ProcessDataImpl implements IProcessData {        /*       * @see com.xxx.bubbo.provider.IProcessData#deal(java.lang.String)      */      @Override    public String setAge(String age) {          try {              Thread.sleep(1000);          } catch (InterruptedException e) {              e.printStackTrace();          }          return "You are " + age + "years old!";      }      @Override    public String sayHi(String name) {          try {              Thread.sleep(1000);          } catch (InterruptedException e) {              e.printStackTrace();          }          return "Hi:" + name;      }  }

用戶端JavaSampler測試案例類

package com.huangjie.dubbo_Consumer;import org.apache.jmeter.config.Arguments;import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;import org.apache.jmeter.samplers.SampleResult;import org.apache.log.Logger;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.huangjie.dubbo_Service.service.IProcessData;public class JmeterInterfaceTest extends AbstractJavaSamplerClient{    private static String label_name = "dubbo_consumer";//定義label名稱,顯示在jmeter的結果視窗         private static final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath*:applicationConsumer.xml");     private static IProcessData demoService = null;    private Logger log = getLogger();    @Override    public void setupTest(JavaSamplerContext arg0) {        log.info("測試案例開始執行...");        //定義測試初始值,setupTest只在測試開始前使用        demoService = (IProcessData) context.getBean("demoService");    }    @Override    public Arguments getDefaultParameters() {        //參數定義,顯示在前台,也可以不定義        Arguments params = new Arguments();               params.addArgument("name", "Tom");        params.addArgument("age", "23");        return params;    }        @Override    public SampleResult runTest(JavaSamplerContext arg0) {        boolean success = true;        SampleResult sr = new SampleResult();        sr.setSampleLabel(label_name);        sr.sampleStart();//用來統計執行時間--start--        try {            String name = arg0.getParameter("name");            String msg = demoService.sayHi(name);            Thread.sleep(5000);            System.out.println(msg);            sr.setResponseMessage(msg);            sr.setResponseCode("1000");        } catch (Exception e) {            success = false;        }finally{            sr.sampleEnd();//用來統計執行時間--end--            sr.setSuccessful(success);        }        return sr;    }        @Override    public void teardownTest(JavaSamplerContext arg0){        log.info("測試案例執行結束...");    }}

說明:

首先,getDefaultParameters()方法是用來定義參數的,這裡我們定義了name和age兩個參數並賦了預設值”Tom”和“23”,這樣在jmeter建立的java請求中選擇上面的測試類別就能看到這兩個參數了,並且參數值也是可以任意修改的。

接著,仔細看會發現,測試類別裡面我們只調用了sayHi()這個方法,並沒有調用服務端提供的setAge()方法,之所以不在一個測試案例裡面去調用兩個測試方法是因為我們這裡的目的是去測試單一的情境,也就是如果要分別測這兩個方法那就得再建一個測試案例類,其它部分的代碼都可以不變,只要把實現方法替換一下就可以了。因此,我們會想,如果一個介面提供n種方法,那麼我們就要寫類似的n個類,雖說複製粘貼很容易,但這樣就會產生一堆類檔案,感覺很冗餘,這裡可以用Java的反射機制來實現方法的動態調用。簡單的說就是,在runTest()方法中不寫死具體用例調用的方法,而是由Java反射機制通過輸入參數來決定。改寫上面的測試案例類如下:

先寫一個抽象類別來繼承AbstractJavaSamplerClient,裡面唯寫動態調用的方法,其它方法還是在用例類裡面重寫。

package com.huangjie.dubbo_Consumer;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;import org.apache.jmeter.samplers.SampleResult;public abstract class AbstractServiceClient extends AbstractJavaSamplerClient{        public Object invokeRunTest(String testName,  JavaSamplerContext  context , SampleResult  sampleResult){                Method[] methods = this.getClass().getMethods();        for (Method method : methods) {            if (method.getName().equalsIgnoreCase(testName)) {                try {                    return method.invoke(this, context, sampleResult);                } catch (IllegalArgumentException e) {                    e.printStackTrace();                } catch (IllegalAccessException e) {                    e.printStackTrace();                } catch (InvocationTargetException e) {                    e.printStackTrace();                }            }        }        return null;    }    }

測試案例類繼承上面的動態方法引動過程的抽象類別

package com.huangjie.dubbo_Consumer;import org.apache.jmeter.config.Arguments;import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;import org.apache.jmeter.samplers.SampleResult;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.huangjie.dubbo_Service.service.IProcessData;public class DynamicMethodInvokeTest extends AbstractServiceClient{    private static String label_name = "dubbo_consumer";//定義label名稱,顯示在jmeter的結果視窗         private static final ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("classpath*:applicationConsumer.xml");     private static IProcessData demoService = null;        @Override    public void setupTest(JavaSamplerContext context) {        //定義測試初始值,setupTest只在測試開始前使用        super.setupTest(context);        demoService = (IProcessData) cxt.getBean("demoService");    }    @Override    public Arguments getDefaultParameters() {        //參數定義,顯示在前台,也可以不定義        Arguments params = new Arguments();               params.addArgument("name", "Tom");        params.addArgument("age", "20");        params.addArgument("testName", "setAge");        return params;           }        @Override    public SampleResult runTest(JavaSamplerContext context) {        String testName = context.getParameter("testName");        SampleResult sr = new SampleResult();        super.invokeRunTest(testName, context, sr);        return sr;    }        public void setAge(JavaSamplerContext context, SampleResult sr){        boolean success = true;        sr.setSampleLabel("setAge");        sr.sampleStart();        try {            String age = context.getParameter("age");            String msg = demoService.setAge(age);            Thread.sleep(5000);            System.out.println(msg);            sr.setResponseMessage(msg);            sr.setResponseCode("1000");        } catch (Exception e) {            success = false;        }finally{            sr.sampleEnd();            sr.setSuccessful(success);        }    }        public void sayHi(JavaSamplerContext context, SampleResult sr){        boolean success = true;        sr.setSampleLabel("sayHi");        sr.sampleStart();        try {            String name = context.getParameter("name");            String msg = demoService.sayHi("Hi,"+name);            Thread.sleep(5000);            System.out.println(msg);            sr.setResponseMessage(msg);            sr.setResponseCode("1001");        } catch (Exception e) {            success = false;        }finally{            sr.sampleEnd();            sr.setSuccessful(success);        }    }        @Override    public void teardownTest(JavaSamplerContext context){        super.teardownTest(context);    }}

這裡我們新增了一個參數testName,通過這個參數來決定具體調用哪個用例方法。這樣,我們就實現了在同一個類裡面寫不同的測試案例了,感覺優雅多了,哈哈。 二. Jmeter中建立Java Sampler Test Plan

想要在Jmeter中執行上面寫的測試案例,有以下幾個步驟:

1. 把項目打成jar包,方法1用eclipse或者myeclipse的export直接匯出jar包,方法2用maven的package或這install指令打包,這裡建議用maven來管理項目,打包方便並且不會出錯,我試過用IDE直接export出jar包,但執行的過程中報找不到spring的bean設定檔,用maven打包沒有出現這種情況。

2.將打好的jar包放到Jmeter的lib/ext路徑下,運行Jmeter,在建立的Java請求Sampler中就能找到自己寫的測試案例類了。

3.把項目依賴的所有jar包拷貝到Jmeter的lib路徑下,因為跑自己的測試案例可能用到這些jar中的類,否則執行過程中會報找不到class。如果是maven項目,則可以通過執行指令mvn dependency:copy-dependencies 把項目中所有依賴的jar匯出到項目的target/dependency檔案夾中,然後拷貝到Jmeter的lib下。

4.運行Jmeter按照具體的效能指標和情境,開始建立你的測試計劃吧。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.