JMeter进阶系列01--JMeter二次开发

JMeter二次开发--实现配置和运行UI自动化测试

  1. JMeter版本:3.3
  2. JMeter下载地址: https://archive.apache.org/dist/jmeter/binaries/ 
  3. Selenium版本:3.11
  4. JDK 1.8

>第1步:Maven工程创建

使用STS创建的Maven工程,忽略步骤

>第2步:pom.xml设置

 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 2     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 3     <modelVersion>4.0.0</modelVersion>
 4     <groupId>com.test</groupId>
 5     <artifactId>Jmeter</artifactId>
 6     <version>0.0.1-SNAPSHOT</version>
 7 
 8     <properties>
 9         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!-- 
10             源文件编码 -->
11         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!-- 
12             文件拷贝时的 -->
13         <maven.compiler.encoding>UTF-8</maven.compiler.encoding><!-- 编译时的编码 -->
14         <selenium-version>3.11.0</selenium-version>
15     </properties>
16 
17     <dependencies>
18         <!-- java jmeter依赖jar包 -->
19         <dependency>
20             <groupId>org.apache.jmeter</groupId>
21             <artifactId>ApacheJMeter_core</artifactId>
22             <version>3.3</version>
23         </dependency>
24         <dependency>
25             <groupId>org.apache.jmeter</groupId>
26             <artifactId>ApacheJMeter_java</artifactId>
27             <version>3.3</version>
28         </dependency>
29 
30         <dependency>
31             <groupId>org.seleniumhq.selenium</groupId>
32             <artifactId>selenium-java</artifactId>
33             <version>${selenium-version}</version>
34         </dependency>
35 
36         <dependency>
37             <groupId>org.seleniumhq.selenium</groupId>
38             <artifactId>selenium-server</artifactId>
39             <version>${selenium-version}</version>
40         </dependency>
41 
42         <dependency>
43             <groupId>org.seleniumhq.selenium</groupId>
44             <artifactId>selenium-remote-driver</artifactId>
45             <version>${selenium-version}</version>
46         </dependency>
47     </dependencies>
48 
49     <build>
50         <plugins>
51             <plugin>
52                 <groupId>org.apache.maven.plugins</groupId>
53                 <artifactId>maven-compiler-plugin</artifactId>
54                 <configuration>
55                     <source>1.8</source>
56                     <target>1.8</target>
57                 </configuration>
58             </plugin>
59 
60             <plugin>
61                 <artifactId>maven-assembly-plugin</artifactId>
62                 <configuration>
63                     <descriptor>src/main/assembly/assembly.xml</descriptor>
64                 </configuration>
65                 <executions>
66                     <execution>
67                         <id>make-assembly</id>
68                         <phase>package</phase>
69                         <goals>
70                             <goal>single</goal>
71                         </goals>
72                     </execution>
73                 </executions>
74             </plugin>
75         </plugins>
76     </build>
77 </project>
pom.xml

 

>第3步:添加assembly.xml用于导出工程的依赖

<!-- Copyright 1999-2011 Alibaba Group. Licensed under the Apache License, 
    Version 2.0 (the "License"); you may not use this file except in compliance 
    with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
    Unless required by applicable law or agreed to in writing, software distributed 
    under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES 
    OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
    the specific language governing permissions and limitations under the License. -->
<assembly>
    <id>assembly</id>
    <formats>
        <format>tar.gz</format>
    </formats>
    <includeBaseDirectory>true</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory>lib</outputDirectory>
        </dependencySet>
    </dependencySets>
</assembly>
assembly.xml

>第4步:创建基于PO的测试类:Login.java

  1 package com.test;
  2 
  3 import java.util.concurrent.TimeUnit;
  4 
  5 import org.apache.poi.util.SystemOutLogger;
  6 import org.openqa.selenium.By;
  7 import org.openqa.selenium.WebDriver;
  8 import org.openqa.selenium.WebElement;
  9 import org.openqa.selenium.interactions.Action;
 10 import org.openqa.selenium.interactions.Actions;
 11 import org.openqa.selenium.support.CacheLookup;
 12 import org.openqa.selenium.support.FindBy;
 13 import org.openqa.selenium.support.How;
 14 import org.openqa.selenium.support.PageFactory;
 15 import org.openqa.selenium.support.pagefactory.AjaxElementLocatorFactory;
 16 import org.openqa.selenium.support.ui.ExpectedCondition;
 17 import org.openqa.selenium.support.ui.ExpectedConditions;
 18 import org.openqa.selenium.support.ui.Select;
 19 import org.openqa.selenium.support.ui.WebDriverWait;
 20 import org.slf4j.Logger;
 21 import org.slf4j.LoggerFactory;
 22 
 23 /**
 24  * @author Wulei
 25  * @date 2018-4-26
 26  * 
 27  */
 28 public class Login {
 29     private WebDriver driver;
 30 
 31     public Login(WebDriver driver) {
 32         this.driver = driver;
 33         PageFactory.initElements(new AjaxElementLocatorFactory(driver, 30), this);//初始化元素时等待时间
 34     }
 35     
 36     @FindBy(id = "loginHtml:username")
 37     @CacheLookup 
 38     private WebElement userName;
 39     
 40     @FindBy(id = "loginHtml:password")
 41     @CacheLookup 
 42     private WebElement password;
 43     
 44     @FindBy(id = "loginHtml:domain")
 45     @CacheLookup 
 46     private WebElement domain;
 47     
 48     @FindBy(id = "loginHtml:userDomain")
 49     @CacheLookup 
 50     private WebElement userDomain;
 51     
 52     @FindBy(id = "loginHtml:loginBtn")
 53     @CacheLookup 
 54     private WebElement loginBtn;
 55     
 56     @FindBy(css = "ul.nav.navbar-nav.navbar-right.header-menu li:nth-child(3)")
 57     @CacheLookup
 58     private WebElement userIcon;
 59     
 60     @FindBy(css = "ul.nav.navbar-nav.navbar-right.header-menu li:nth-child(5)")
 61     @CacheLookup
 62     private WebElement logoutIcon;
 63     
 64     @FindBy(partialLinkText = "Logout")
 65     private WebElement logout;
 66     
 67     @FindBy(css = "div.errors ul li")
 68     @CacheLookup 
 69     private WebElement errorMsg;
 70     
 71     @FindBy(id = "si_searchAttrInput")
 72     @CacheLookup 
 73     private WebElement searchAttrInput;
 74     
 75     @FindBy(xpath = "//*[@id=\"userProfilePopup\"]/div/div/div[3]/button[@id=\"cancelBtn\"]")
 76     @CacheLookup 
 77     private WebElement closeBt;
 78 
 79     @FindBy(how = How.XPATH, using = "//*[@id=\"mainHeader\"]/div/nav/div[2]/ul[2]/li[3]/a")
 80     private WebElement profile;
 81 
 82     
 83     public void login(String userName, String password, String custId, String domain)
 84             throws Exception {
 85         this.userName.sendKeys(userName);
 86         this.password.sendKeys(password);
 87         this.domain.clear();
 88         this.domain.sendKeys(custId);
 89         Select select = null;
 90         for (int i = 0; i < 3; i++) {
 91             try {
 92                 select = new Select(userDomain);
 93                 select.selectByVisibleText(domain);
 94                 break;
 95             } catch (org.openqa.selenium.StaleElementReferenceException e) {
 96             }
 97         }
 98 
 99         loginBtn.click();
100         
101         try {
102             TimeUnit.SECONDS.sleep(2);
103         } catch (InterruptedException e) {
104             e.printStackTrace();
105         }
106 
107         PageFactory.initElements(new AjaxElementLocatorFactory(driver, 30), this);
108     }
109 
110     public boolean isLoggedIn() {
111         boolean result = true;
112         // check if input search box can be located
113         try {
114             new WebDriverWait(driver,5).until(ExpectedConditions.visibilityOf(searchAttrInput));
115         } catch (org.openqa.selenium.TimeoutException e) {
116             result = false;
117         }
118         return result;
119     }
120 
121     public String getErrorMsg() {
122         return errorMsg.getText();
123     }
124 
125     public Login logout() throws InterruptedException {
126         closeBt.click();
127         Thread.sleep(2000);
128         logoutIcon.click();
129         logout.click();
130         return this;
131     }
132 }
Login.java

>第5步:创建自动化测试类:AutoTest.java

 1 package com.test;
 2 
 3 import java.util.concurrent.TimeUnit;
 4 
 5 import org.openqa.selenium.WebDriver;
 6 import org.openqa.selenium.chrome.ChromeDriver;
 7 
 8 public class AutoTest {
 9     public static Boolean runTest(String url, String su) throws Exception {
10         WebDriver driver = new ChromeDriver();
11         driver.manage().window().maximize();
12         driver.manage().timeouts().implicitlyWait(12, TimeUnit.SECONDS);
13         driver.get(url);
14         Login loginObj = new Login(driver);
15         loginObj.login("admin", "admin*1", su, "LOCAL");
16         return true;
17     }
18 
19 }
AutoTest.java

>第6步【核心】:创建类继承AbstractJavaSamplerClient

 1 package com.test;
 2 
 3 import org.apache.jmeter.config.Arguments;
 4 import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
 5 import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
 6 import org.apache.jmeter.samplers.SampleResult;
 7 
 8 public class CustomJMeter extends AbstractJavaSamplerClient{
 9       
10     @Override
11     public void setupTest(JavaSamplerContext args) {
12 
13     }
14     
15     @Override
16     public Arguments getDefaultParameters() {
17             Arguments params = new Arguments();  
18             params.addArgument("Url", "https://10.30.2.151/phoenix/login-html.jsf"); // 定义一个参数,显示到Jmeter的参数列表中,第一个参数为参数默认的显示名称,第二个参数为默认值 
19             params.addArgument("Org", "super");
20             params.addArgument("Name", "wulei");
21             return params;  
22     }
23 
24     @Override
25     public SampleResult runTest(JavaSamplerContext context) {
26         SampleResult sr = new SampleResult();
27         try {    
28             sr.sampleStart();
29 
30             String arg1 = context.getParameter("Url"); 
31             String arg2 = context.getParameter("Org"); 
32             AotuTest.runTest(arg1, arg2);
33             sr.setSampleLabel("结果");
34             sr.setResponseData("返回结果:"+AotuTest.runTest(arg1, arg2), "UTF-8");
35             sr.setDataType(SampleResult.TEXT);
36             sr.setSuccessful(true);
37         } catch (Exception e) {
38             sr.setSuccessful(false);
39             e.printStackTrace();
40         }finally {
41             sr.sampleEnd();// jmeter 结束统计响应时间标记
42         }
43         return sr;
44     }
45 
46     @Override
47     public void teardownTest(JavaSamplerContext context) {
48         // TODO Auto-generated method stub
49         super.teardownTest(context);
50     }
51 }
52   
CustomJMeter.java

创建完毕后的过程结构如下图:

 

>第7步:Maven打包package,并查看打包结果

>第8步:将包移到JMeter的对应目录中

Jmeter-0.0.1-SNAPSHOT.jar  --------复制到------>JMeter目录:apache-jmeter-3.3\lib\ext

Jmeter-0.0.1-SNAPSHOT-assembly.tar.gz --------将压缩包里面的lib目录下的全部jar包复制到------>JMeter目录:apache-jmeter-3.3\lib

结果如下图:

>第9步:运行JMeter的java请求,运行用例

运行后会自动运行测试代码(打开Chrome浏览器并登陆系统)查看结果如下:


代码CustomJMeter.java详解

CustomJMeter.java继承AbstractJavaSamplerClient类后,重写了如下方法:

1.setupTest方法:运行JMeter取样器前执行的操作,初始化一些操作,可以为空。

@Override
public void setupTest(JavaSamplerContext args) {

  //TODO

}

2.teardownTest方法:取样器的回收方法,可以为空。

@Override
public void teardownTest(JavaSamplerContext context) {
  // TODO Auto-generated method stub
  super.teardownTest(context);
}

3.getDefaultParameters方法【重要】:定义JMeter传递的参数,也就是JMeter的JAVA请求显示的参数列表。可以设置默认值。

@Override
public Arguments getDefaultParameters() {
  Arguments params = new Arguments(); //初始化参数
  params.addArgument("Url", "https://10.30.2.151/phoenix/login-html.jsf"); // 定义一个参数,显示到Jmeter的参数列表中,第一个参数为参数默认的显示名称,第二个参数为默认值
  params.addArgument("Org", "super");
  params.addArgument("Name", "wulei");//这里定义了3个参数并都设置了默认值
  return params;
}

对应JMeter的显示:

4.runTest【最重要】方法:定义取样器的运行的内容和设置取样器的返回结果

@Override
public SampleResult runTest(JavaSamplerContext context) {
  SampleResult sr = new SampleResult();//初始化取样器的返回
  try {
    sr.sampleStart();//开始运行取样器

    String arg1 = context.getParameter("Url");        //获取JMeter运行时传递的实际参数值
    String arg2 = context.getParameter("Org");           //获取JMeter运行时传递的实际参数值
    AotuTest.runTest(arg1, arg2);              //运行自动化测试,并将参数传递到测试方法中
    sr.setSampleLabel("结果");               //参考下图:定义取样器的结果标签,查看结果树中可以查看
    sr.setResponseData("返回结果:"+AotuTest.runTest(arg1, arg2), "UTF-8"); //参考下图:setResponseData,结果会显示在响应结果框中
    sr.setDataType(SampleResult.TEXT);          //参考下图:设置结果的数据类型为TEXT
    sr.setSuccessful(true);                //参考下图:定义测试结果,可以判断定义
  } catch (Exception e) {
    sr.setSuccessful(false);
    e.printStackTrace();
  }finally {
    sr.sampleEnd();// jmeter 结束统计响应时间标记
  }
  return sr;
}


写在最后

JMeter二次开发的本质很简单就是重写方法,打包和运行。这里的例子是使用的是自动化测试,大家可以忽略例子本身,而只关注继承类的实现。网络上很多的例子都是实现加法,减法等运算。实际是一样的。只不过测试类的区别。

 

posted @ 2018-05-08 14:22  爱寂寞撒的谎言  阅读(371)  评论(0编辑  收藏  举报