以百度天气预报查询API 服务为例,创建Jmeter JavaSampler请求范例

本文涉及的产品
性能测试 PTS,5000VUM额度
简介: 最近在整理性能测试的一些入门文章,给同事们分享,介绍API 接口自动化和性能测试入门。下面将以百度天气预报查询API 服务为例,创建Java API 请求范例。1. API 服务信息参考文档:https://blog.

最近在整理性能测试的一些入门文章,给同事们分享,介绍API 接口自动化和性能测试入门。

下面将以百度天气预报查询API 服务为例,创建Java API 请求范例。

1. API 服务信息

参考文档:https://blog.csdn.net/younghaiqing/article/details/54799303

接口示例:http://api.map.baidu.com/telematics/v3/weather?location=北京&output=json&ak=amMXVSEUGt6yU95x4DQOC2Um

百度ak申请地址:http://lbsyun.baidu.com/apiconsole/key

接口参数说明:

 

返回结果:

 

 

2. 创建Java工程

2.1 分析API 服务接口

接口示例如下:

http://api.map.baidu.com/telematics/v3/weather?location=北京&output=json&ak=yourkey

输出的数据格式,默认为xml格式;当output设置为'json'时,输出的为json格式的数据。

通过观察接口示例,可以判断HTTP请求方式为GET——GET方法向URL添加数据。

 

2.2 写出API 服务请求

package com.ane56.tester;

import java.io.BufferedReader;  
import java.io.InputStream;  
import java.io.InputStreamReader;  
import java.net.HttpURLConnection;  
import java.net.URL; 

public class BaiduWeather_originalV1 {
    /* 
     * 根据城市名称查询天气 
     * @param city 
     *  
     * auther Jason Ma
     */
    
    //接口示例
    //http://api.map.baidu.com/telematics/v3/weather?location=北京&output=json&ak=yourkey
    //百度ak申请地址:http://lbsyun.baidu.com/apiconsole/key
    //输出的数据格式,默认为xml格式;当output设置为'json'时,输出的为json格式的数据
    
    private static String MYKEY = "amMXVSEUGt6yU95x4DQOC2Um";
    private static String ADDRESS = "http://api.map.baidu.com/telematics/v3/weather";
    
    public static void main(String[] args) {
        String city = "青浦";
        String httpArg = "location=" + city + "&output=" + "xml" + "&ak=" + MYKEY;
        
        String httpUrl = ADDRESS + "?" + httpArg;
        System.out.println("请求的地址是:" + httpUrl);
        
        BufferedReader reader = null;
        String result = null;
        StringBuffer sbf = new StringBuffer();
        
        try {
            URL url = new URL(httpUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            InputStream is = connection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            
            String strRead = null;
            while ((strRead = reader.readLine()) != null) {
                sbf.append(strRead);
                sbf.append("\r\n");
            }
            reader.close();
            result = sbf.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        System.out.println(result);
    }
}

 

3. 转化为Jmeter JavaSampler

下面将利用Eclipse创建Maven工程的方式,完成JavaSampler的编码工作。

3.1 创建Maven工程

在Eclipse左侧的Package Explore点击右键,依次选择New -> Other -> Maven -> Maven Project:

这里要注意,之前创建的API 请求类,不是一定要基于Maven工程,普通的Java Project就可以;

创建Maven Project是为了开发和调试Jmeter JavaSampler。

 

3.2 添加依赖

打开Maven工程的POM.xml文件,添加依赖包。我们需要的依赖包如下:

 - Junit:工程创建时已存在;

 - Jmeter:核心,作为JavaSampler请求;有三个组件需要添加:ApacheJMeter_core、ApacheJMeter_java、ApacheJMeter_components;

 - log4j-over-slf4j:为了解决调试阶段log4j红字报错,非必选,也可以用其他依赖包替代。

 完成后的POM.xml文件如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ane56.tester</groupId>
    <artifactId>Jmeter_JavaSampler</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    
    <name>Jmeter_JavaSampler</name>
    <url>http://maven.apache.org</url>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/org.slf4j/log4j-over-slf4j -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>1.7.25</version>
        </dependency>
         
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_core</artifactId>
            <version>3.3</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_java</artifactId>
            <version>3.3</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_components</artifactId>
            <version>3.3</version>
        </dependency>
        
  </dependencies>
</project>

 

3.3 理解Java Sampler的套路

首先:要实现AbstractJavaSamplerClient类,才能被Jmeter加载;创建名为“BaiduWeather_JavaSamplerV1”的Java类,

添加对AbstractJavaSamplerClient类的实现;完成后如下:

public class BaiduWeather_JavaSamplerV1 extends AbstractJavaSamplerClient {
……
}

其次:(对比LoadRunner脚本的结构:)

-        设置参数:getDefaultParameters,用于设置传入的参数;

-        初始化(init):setupTest,用于初始化性能测试时的每个线程;

-        执行迭代(action):runTest,为性能测试时的线程运行体;

-        完成退出(end):teardownTest,为测试结束方法,用于结束性能测试中的每个线程。

补充:调试脚本的main()方法。

 

3.4 详解getDefaultParameters()

在getDefaultParameters()代码段中,添加请求的参数;

作用:当Jmeter读取此JavaSampler后,能够读出请求的参数到列表:

 

注意:

在getDefaultParameters()代码段中,只需要添加参数项的名字,而不必要赋值。

通常我们会在Jmeter脚本中,对请求参数进行参数化。

 读取参数的代码(在runTest方法内):

 

3.5 详解runTest()格式

-        创建sampleResult:private SampleResult sampleResult;

-        给请求贴标签:sampleresult.setSampleLabel("Java请求");

-        把请求的信息,写到Jmeter的【察看结果树 – 请求】页面:

       sampleresult.setSamplerData(httpUrl);

       sampleresult.setDataType(SampleResult.TEXT);

-        发送请求时,开始计时:sampleresult.sampleStart();

-        收到应答后,结束统计响应时间:sampleresult.sampleEnd();

-        标记获得成功的应答,对应http 200:sampleresult.setResponseCodeOK();

-        把收到的应答内容,写到Jmeter的【察看结果树 – 响应数据】页面:

sampleresult.setResponseData("结果是:"+ result, "utf-8");

       sampleresult.setDataType(SampleResult.TEXT);

 

3.6 调试脚本的main()

1)首先要进行参数赋值,否则将直接使用getDefaultParameters()代码段中设置的参数默认值。建议赋值,与Jmeter的实际工作方式保持一致。

2)调用BaiduWeather_JavaSamplerV1,创建一次测试执行。

 

 

 4. 导出Maven工程

4.1 导出依赖包

选中工程,点击右键,在菜单中选择Run As -> Run Configuration:

 

1)    首先在左侧的列表中,选择Maven Build,然后点击左上方的新建图标;

2)    输入操作的名字,在本例中是:Jmeter_JavaSampler_exportDependency;

3)    定位当前操作的工程路径;可以点击Workspace…的按钮来定位;

4)    输入操作的具体命令:在本例中是为了导出依赖:dependency:copy-dependencies;

5)    检查Maven Runtime的信息是否正确;

6)    点击Apply按钮完成保存;

7)    点击Run按钮、进行依赖包的导出。

等待完成后,到工程所在的路径\target\dependency目录,查看的依赖jar包:

 

 4.2 导出测试类

导出测试类有两种方式:

1)Maven install命令:该命令会在工程所在的路径\target文件夹下,生成与工程同名的jar文件,如Jmeter_JavaSampler-0.0.1-SNAPSHOT.jar。

      不推荐这样的方式,因为这将导出工程中所有的类,不够精确。

2)直接导出单个接口测试类,注意是符合Jmeter JavaSampler的那个类。

      具体方法是:在Eclipse左侧的Package Explore选中该类,点击右键,选择Export:

输入要导出JAR file的路径和名称,点击Finish按钮,完成导出操作。

 

5. 在Jmeter创建测试计划

5.1 准备工作

首先,要将导出的依赖包,拷贝到jmeter\lib目录下。推荐将整个dependency文件夹拷过来,然后再引入到测试计划。

这样的好处在于大量的依赖包中存在与原有jmeter\lib目录下的同名或不同版本的干扰。如下图:

 

然后,将单独导出的接口测试类的jar文件复制到jmeter\lib\ext目录下,如下图:

这里的jar文件有个问题,先卖个关子,在后面分析解决思路。

完成后,进入下一环节。

 

5.2 创建测试计划

启动Jmeter,在测试计划的主窗口的靠下位置,添加依赖到classpath中;

通过点击浏览按钮,定位到依赖包的文件夹,全选所有的jar文件,点击打开按钮:

 

 

第一步完成后,添加线程组,并添加Java请求;

 

 

在类名称的下拉菜单中,找到我们开发的测试类BaiduWeather_JavaSamplerV1:

 

 

 5.3 调试脚本

填写请求参数,填充原本为空的参数、缺省值可以替换也可保留:

 

 

添加一个监听器 – 察看结果树,以便查看脚本调试的结果:

 

点击刚刚添加的察看结果树,将主画面切换到结果树:

 

 

在调试前,需要保存脚本成.jmx文件。点击保存按钮,将脚本存放到合适的位置。

点击上方工具条内的启动按钮,查看测试结果:

Text区域,每执行一次请求,就自动增加一条记录到尾部。

右侧的区域,有三个Tab页,方便查看测试请求和响应。我们分别查看一下,注意判断响应数据是否为正确的。

请求页面:

没问题,确实与预期的一样。

再看响应数据页面:

显示error -3, No result available,出错了。

 

5.4 解决问题

解决步骤:

先将请求内容,放到浏览器中,查看是否能获得正确的天气预报信息:

成功了,说明API 服务没问题,请求内容也没问题。是哪里不对呢?

首先想到的,是否因为百度天气预报API对不是浏览器访问的Request做了屏蔽?类似与反爬虫策略。那就需要在请求时,补全HTTP Header信息。

那么HTTP Header信息哪里能查看?

这里可以利用Chrome浏览器的开发工具,按F12后,刷新一下,浏览器会自动录制整个请求和应答。

 

这样就能捕获到HTTP Header信息,将它们逐条复制下来。在Jmeter的线程组下面添加一个配置元件 - HTTP头信息管理,再逐条添加进去。

再次执行脚本,错误依旧如此。

思路错了吗?其实没有,方法是正确的,再想想。

 

正确的方法如下:

仔细查看一下Request RUL,如下图:

和浏览器的地址栏中的内容比较一下,“location=上海”在Request中,被替换成了“location=%E4%B8%8A%E6%B5%B7”。

这是汉字没有转码所导致的:我们从Jmeter发出的汉字不是URL编码的格式。

 

再想想,我们在Eclipse调试接口脚本的时候,应答信息和浏览器中显示的内容是一样的;这意味着从Eclipse发出的Request,已经被自动转码了,有点坑啊!

 因此,我们需要对城市名称的汉字进行转码,而且要在接口请求的代码里完成。

为完成转码功能,需要再增加一个依赖:

import java.io.UnsupportedEncodingException;

runTest方法修改后,为如下图所示:

这里增加了一个转码的步骤,将接收到的城市名称从汉字转码为URL格式的。执行一下看看效果:

 

成功了!

重新将接口测试类导出成jar文件,删除先前存在于jmeter\lib\ext下的同名文件;再拷贝一遍。

Jmeter也要重启才会刷新Java请求中的类列表。

重启后,打开之前保存的脚本,再次运行调试;执行成功。

 

 

以上就是从API 接口请求,转化为Jmeter的JavaSampler的编写方法。完整代码如下:

package com.ane56.tester;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
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;

public class BaiduWeather_JavaSamplerV2 extends AbstractJavaSamplerClient {

    private SampleResult sampleResult;
    private String parameter;
    
    /** Holds the result data (shown as Response Data in the Tree display). */
    private String resultData;
    
    private String httpArg_city;
    private String httpArg_outputType;
    
    SampleResult sampleresult = new SampleResult();
    
    /**
     * JMeter界面中可手工输入参数,代码里面通过此方法获取
     */
    public Arguments getDefaultParameters() {
        // 设置参数,并赋予默认值
        Arguments params = new Arguments();
        params.addArgument("httpUrl", "");
        params.addArgument("httpArg_city", "上海");
        params.addArgument("httpArg_outputType", "xml");
        params.addArgument("mykey", "");
        //System.out.println("Default params list: " + params);

        return params;
    }
    
    /**
     * 执行runTest()方法前会调用此方法,可放一些初始化代码
     */
    @Override
    public void setupTest(JavaSamplerContext arg0) {
        //parameter = arg0.getParameter("parameter");
        
        sampleresult.setDataEncoding("utf-8");

        long start = System.currentTimeMillis();
    }
    
    @Override
    public SampleResult runTest(JavaSamplerContext arg0) {
        
        sampleresult.setSampleLabel("Java请求");
        
        String httpUrl = arg0.getParameter("httpUrl");
        String location = arg0.getParameter("httpArg_city");
        String outputType = arg0.getParameter("httpArg_outputType");
        String mykey = arg0.getParameter("mykey");
        
        //对汉字转码,否则在Jmeter测试时,获得错误响应
        try {
            location = java.net.URLEncoder.encode(location, "utf-8");
        } catch (UnsupportedEncodingException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        String httpArg = "location=" + location + "&output=" + outputType + "&ak=" + mykey;
        httpUrl = httpUrl + "?" + httpArg;
        System.out.println("HttpURL is: " + httpUrl);
        
        BufferedReader reader = null;
        String result = null;
        StringBuffer sbf = new StringBuffer();
        
        sampleresult.setSamplerData(httpUrl);
        sampleresult.setDataType(SampleResult.TEXT);
        
        try {
            sampleresult.sampleStart();
            sampleresult.getStartTime();
            
            URL url = new URL(httpUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            InputStream is = connection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String strRead = null;
            while ((strRead = reader.readLine()) != null) {
                sbf.append(strRead);
                sbf.append("\r\n");
            }
            reader.close();
            result = sbf.toString();
            System.out.println("结果是:"+ result);

            sampleresult.setResponseCodeOK();
            sampleresult.setResponseMessage("Java Sampler Response is done. ");
            sampleresult.setResponseData("结果是:"+ result, "utf-8");
            sampleresult.setDataType(SampleResult.TEXT);
            
            sampleresult.setSuccessful(true);
        } catch (Exception e) {
            sampleresult.setSuccessful(false);
            e.printStackTrace();
        } finally {
            sampleresult.sampleEnd(); // jmeter 结束统计响应时间标记
            sampleresult.getEndTime();
        }
        
        return sampleresult;
    }
    
    /**
     * 执行runTest()方法后会调用此方法.
     */
    @Override
    public void teardownTest(JavaSamplerContext arg0) {
        long end = System.currentTimeMillis();
    }
    
    /**
     * 主函数;打jar包之前,记得注释掉main
     */
    
    public static void main(String[] args) {
        Arguments params = new Arguments();
        params.addArgument("httpUrl", "http://api.map.baidu.com/telematics/v3/weather");
        params.addArgument("httpArg_city", "上海");
        params.addArgument("httpArg_outputType", "json");
        params.addArgument("mykey", "amMXVSEUGt6yU95x4DQOC2Um");
        
        JavaSamplerContext arg0 = new JavaSamplerContext(params);
        
        BaiduWeather_JavaSamplerV2 test = new BaiduWeather_JavaSamplerV2();
        test.setupTest(arg0);
        test.runTest(arg0);
        test.teardownTest(arg0);
        System.exit(0);
    }
    
}

 

相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
相关文章
|
1月前
|
缓存 前端开发 中间件
[go 面试] 前端请求到后端API的中间件流程解析
[go 面试] 前端请求到后端API的中间件流程解析
|
1月前
|
开发框架 缓存 .NET
并发请求太多,服务器崩溃了?试试使用 ASP.NET Core Web API 操作筛选器对请求进行限流
并发请求太多,服务器崩溃了?试试使用 ASP.NET Core Web API 操作筛选器对请求进行限流
|
1月前
|
存储 缓存 运维
平稳扩展:可支持RevenueCat每日12亿次API请求的缓存
平稳扩展:可支持RevenueCat每日12亿次API请求的缓存
35 1
|
27天前
|
存储 Kubernetes API
【APIM】Azure API Management Self-Host Gateway是否可以把请求的日志发送到Application Insights呢?让它和使用Azure上托管的 Gateway一样呢?
【APIM】Azure API Management Self-Host Gateway是否可以把请求的日志发送到Application Insights呢?让它和使用Azure上托管的 Gateway一样呢?
|
27天前
|
API C#
【Azure API 管理】APIM如何实现对部分固定IP进行访问次数限制呢?如60秒10次请求
【Azure API 管理】APIM如何实现对部分固定IP进行访问次数限制呢?如60秒10次请求
|
27天前
|
存储 API
【Azure API 管理】为调用APIM的请求启用Trace -- 调试APIM Policy的利器
【Azure API 管理】为调用APIM的请求启用Trace -- 调试APIM Policy的利器
|
28天前
|
存储 安全 API
【Azure API 管理】在APIM中使用客户端证书验证API的请求,但是一直提示错误"No client certificate received."
【Azure API 管理】在APIM中使用客户端证书验证API的请求,但是一直提示错误"No client certificate received."
|
28天前
|
安全 API
【Azure API 管理】Azure API Management通过请求中的Path来限定其被访问的频率(如1秒一次)
【Azure API 管理】Azure API Management通过请求中的Path来限定其被访问的频率(如1秒一次)
|
28天前
|
API
【Azure API 管理】在 Azure API 管理中使用 OAuth 2.0 授权和 Azure AD 保护 Web API 后端,在请求中携带Token访问后报401的错误
【Azure API 管理】在 Azure API 管理中使用 OAuth 2.0 授权和 Azure AD 保护 Web API 后端,在请求中携带Token访问后报401的错误
|
1月前
|
JavaScript 前端开发 定位技术
百度地图JavaScript API v2.0创建地图
百度地图JavaScript API v2.0创建地图
28 0