【Gatling 菜鸟实践】Maven+Gatling实现性能测试脚本开发过程和总结

背景:最近在朋友圈,有不少人在使用Gatling性能测试工具,都说相比jmeter开源工具有不少优势,于是在IntelliJ IDEA开发工具中实践和体验了一番maven+Gatling的性能测试,实践如下:

1、搭建IntelliJ IDEA、scala、maven、Gatling环境,请自行百度。但需注意2点
   (1)、IntelliJ IDEA的maven项目中新建scala class时,无法显示出来,参考地址设置:

     https://blog.csdn.net/program_anywhere/article/details/53728186

  (2)、JDK版本要1.8版本以上

2、参数化数据Test_data.csv文件存放的位置,如图:

3、新建testcase.scala文件,编写脚本如下:

(注:1、新增scala class 必须继承Simulation ,否则无法执行 ;2、有人注意到,为啥会有多个URL地址,是因为我们系统采用的是前后端分离,前端地址和后台接口地址不一样;3、我采用了场景分离,可以随意定义执行那个,比较灵活 ;4、scala关于在打印响应值和获取关联参数日志,目前实践发现,在check后,保存到session指定参数中,至于原因,目前未了解不深,不做解释;5、脚本中未设计ssl设置,如有需要,可参考英文论坛地址实践:https://groups.google.com/forum/#!topic/gatling/iQUFQbFLbtA(有时需要跨域查看);6、关于feed参数化时,迭代方式一样要多实践,得到自己想要的;7、参数引用的方式“${参数名}”)

package basic

import io.gatling.core.scenario.Simulation
import io.gatling.core.Predef._
import io.gatling.http.Predef._
class testcase01  extends Simulation{

   private val public_url = "http://ip地址"  //后台接口地址

  /**发送home请求
    * Get请求
    * response返回值为html
    */
   object Home{
     val home = exec(http("Home_request")    //设置请求名称,可随意定义
       .get("http://ip地址")                 //前端请求地址
            .check(status.is(200))          //判断http status
            .check(bodyString.saveAs("Get_bodys"))  //获取response中body所有值,并存入session中Get_bodys参数
            .check(header("ETag").saveAs("Get_header"))  //获取response的header中某个参数值,注:一般用于获取cookies的值
            .check(regex("<meta http-equiv=content-type content=\"(.*)\">").saveAs("Get_parm"))  //采用regex获取html中某个值
     )
       .pause(2)  //设置思考时间2s
       //修改session中信息
       .exec(session =>{
            val header_value = session("Get_header").as[String]   //获取session中参数和对应值
            val session_id =  header_value.split("/")(1)  //获取关联值处理
            session.set("Get_session_id",session_id)      //对session中添加一个新参数,并给新参数赋值
     }
     )
       //打印session信息
       .exec{ session => println(session)
            session
     }
   }

  /** 发送登录请求
    * POST请求
    * 发送Form方式
    *  response返回值为json
    */
   object Login{
    //feed有4种迭代取值方式:
    // 1、queue(顺序取值,直到取完,所以要注意并发虚拟用户数与参数值一致,否则报异常),缺点:不适合持续迭代,只适合一次性并发场景
    // 2、random(随机取值,会重复取值),缺点:取值存在重复,不适合唯一性取值的场景
    // 3、shuffle 网上资料有这个参数,但是在脚本编写时,无法引用,表示不知如何引用到
    // 4、circular(参数一旦用完,从头开始)
    val feeder = csv("D:\\gatling\\src\\test\\resources\\data\\Test_data.csv").circular
    val Content_type = Map("Content-Type" -> "application/x-www-form-urlencoded")   //定义header
    val login = feed(feeder)
       .exec(http("Login_request")
           .post( public_url + "/user/login")
           .headers(Content_type)
           .formParam("username","${login_name}")
           .formParam("pwd","${password}")
           .check(status.is(200))
           .check(jsonPath("$..token").exists)     //判断json中是否存在key
           .check(jsonPath("$..token").saveAs("Get_token"))  // 方法1:获取token值,并将值存入session中Get_token参数
         //.check(regex("\"token\":\"(.*)\"").saveAs("Get_token"))  // 方法2:获取token值,并将值存入session中Get_token参数
           .check(jsonPath("$..*").saveAs("Get_body"))  //方法1:获取response中body所有值,并存入session中Get_body参数
        // .check(bodyString.saveAs("Get_body"))  //方法2:获取response中body所有值,此方法获取的结果与jsonPath("$..*")类似
           .check(header("Date").saveAs("Get_header"))  //获取response的header中某个参数值
     )
       .pause(3)   //设置思考时间3s
       //修改session中信息
       .exec(session =>{
            val token_value = session("Get_token").as[String]   //获取session中Get_token参数值
  session.set("Get_tokens",token_value)      //对session中添加一个新参数,并给新参数赋值
}
)
//打印session信息
.exec{ session => println(session)
  session
}
}

  /** 发送登录请求
    * POST请求
    * 发送JSON方式
    * response返回值为json
    */
  object Login_json{
    val feeder = csv("D:\\gatling\\src\\test\\resources\\data\\Test_data.csv").circular
    //val Content_type = Map("Content-Type" -> "application/json")
    val Content_type = Map("Content-Type" -> "application/x-www-form-urlencoded")
    val login = feed(feeder)
      .exec(http("Login_request")
          .post( public_url + "/user/login")
          .headers(Content_type)
          .body(StringBody("{\"username\":\"${login_name}\",\"pwd\",\"${password}\"}")).asJSON
          .check(status.is(200))
          .check(jsonPath("$..token").exists)     //判断json中是否存在key
          .check(jsonPath("$..token").saveAs("Get_token"))  // 方法1:获取token值,并将值存入session中Get_token参数
    )
      .pause(3)   //设置思考时间3s
      //修改session中信息
      .exec(session =>{
          val token_value = session("Get_token").as[String]   //获取session中Get_token参数值
          session.set("Get_tokens",token_value)      //对session中添加一个新参数,并给新参数赋值
    }
    )
      //打印session信息
      .exec{ session => println(session)
          session
    }
  }

  /**发送退出系统请求
    * POST请求
    */
  object Exit_system{
     val loginout = exec(http("loginout")
         .post(public_url + "/user/loginout")
               .formParam("token","${Get_token}")
     )
   }

  /*******设置场景******/
    //设置场景1
  val scn = scenario("wo玩的就是任性...")     //设置场景名称,可随意定义
      .exec(Home.home,Login.login,Exit_system.loginout)  //调用用例
   //设置场景2
  val scn1 = scenario( "wo扯的都是淡...")
      .exec(Login.login)

  /*******执行场景策略******/
/* setUp(
     //执行多个场景
    //scn.inject(atOnceUsers(1)),
    //scn1.inject(rampUsers(2) over(1))
  )*/
  setUp(
     //执行单场景
    scn1.inject(constantUsersPerSec(2) during(10))   //每秒运行2个虚拟用户,持续运行10s
  )
}

4、pom.xml:

注:pom.xml中需修改<simulationsFolder>src/test/scala/basic</simulationsFolder> 中场景存放的路径,以及<simulationClass>testcase01</simulationClass> 中执行场景class类,否则采用maven执行指定场景

<?xml version="1.0" encoding="UTF-8"?>
<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>gatling</groupId>
	<artifactId>gatling_test</artifactId>
	<version>1.0</version>

	<properties>
		<maven.compiler.source>1.7</maven.compiler.source>
		<maven.compiler.target>1.7</maven.compiler.target>
		<scala.version>2.11.7</scala.version>
		<encoding>UTF-8</encoding>

		<gatling.version>2.1.7</gatling.version>

		<scala-maven-plugin.version>3.2.2</scala-maven-plugin.version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>io.gatling</groupId>
				<artifactId>gatling-app</artifactId>
				<version>${gatling.version}</version>
			</dependency>
			<dependency>
				<groupId>io.gatling</groupId>
				<artifactId>gatling-recorder</artifactId>
				<version>${gatling.version}</version>
			</dependency>
			<dependency>
				<groupId>io.gatling.highcharts</groupId>
				<artifactId>gatling-charts-highcharts</artifactId>
				<version>${gatling.version}</version>
			</dependency>
			<dependency>
				<groupId>org.scala-lang</groupId>
				<artifactId>scala-library</artifactId>
				<version>${scala.version}</version>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>io.gatling.highcharts</groupId>
			<artifactId>gatling-charts-highcharts</artifactId>
		</dependency>
		<dependency>
			<groupId>io.gatling</groupId>
			<artifactId>gatling-app</artifactId>
		</dependency>
		<dependency>
			<groupId>io.gatling</groupId>
			<artifactId>gatling-recorder</artifactId>
		</dependency>
		<dependency>
			<groupId>org.scala-lang</groupId>
			<artifactId>scala-library</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<!-- Run all [matching] tests] on mvn test -->
				<groupId>io.gatling</groupId>
				<artifactId>gatling-maven-plugin</artifactId>
				<version>${gatling.version}</version>
				<configuration>
					<simulationsFolder>src/test/scala/basic</simulationsFolder>
					<!--<includes>-->
					<!--<include>com.jane.DemoOne</include>-->
					<!--</includes>-->
					<!--<excludes>-->
					<!--<exclude>Demo.scala</exclude>-->
					<!--</excludes>-->
					<simulationClass>testcase01</simulationClass>
				</configuration>
				<executions>
					<execution>
						<phase>test</phase>
						<goals>
							<goal>execute</goal>
						</goals>

						<configuration>
							<jvmArgs>
								<jvmArg>-Dgatling.http.ahc.connectTimeout=6000000</jvmArg>
								<jvmArg>-Dgatling.http.ahc.requestTimeout=6000000</jvmArg>
								<jvmArg>-Dgatling.http.ahc.sslSessionTimeout=6000000</jvmArg>
								<jvmArg>-Dgatling.http.ahc.pooledConnectionIdleTimeout=6000000</jvmArg>
								<jvmArg>-Dgatling.http.ahc.readTimeout=6000000</jvmArg>
							</jvmArgs>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>


</project>

5、执行:

(1),直接执行maven 执行(注:需要配置运行环境,路径:Run-->Edit Configurations..-->点击+,选择maven,在command line中输入:clean package -P test)

(2)、调试脚本执行:可以直接,右键选择“Engine”,再选择"Run Engine",在Engine执行框中,按回车键,再选择第几个执行场景,如果只有一个场景,按回车键即可

6、结果:由于当前测试应用系统要求性能较低,未发现啥性能问题,故不贴出分析过程和图标了,请各位见谅!

总结:

1、scala脚本开发,有一定难度,需要一定开发功底。

2、Gatling还缺少一些必要报表,比如TPS、吞吐量。

3、后续可集成到jenkins上,做持续集成。

4、Gatling相对于jmeter的优越性,暂时未能体会到,故后续慢慢摸索和探究,也希望其他大咖来讨论。

5、Gatling的国内网站较少资料,需要多看官网和国外论坛之类资料:比如

官网(重要):https://gatling.io/docs/current/http/   

https://groups.google.com/forum/#!msg/gatling/FjjUi4hHoFs/C0nhb1yCz7MJ

https://blog.csdn.net/lb245557472/article/details/80967889

http://www.360doc.com/content/17/0222/11/28952034_631079492.shtml

https://my.oschina.net/u/3613710/blog/1554937

http://www.mamicode.com/info-detail-2159295.html

https://blog.csdn.net/qq_37023538/article/details/54950827

http://www.bigerhead.com/2016/11/330.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值