Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

cuongld2
cuongld2

Posted on

     

Loadtest REST API with gatling opensource

Hi folks, today I'm gonna show you how to loadtest your rest api with gatling tool.

I.Why loadtest:

Load testing gives confidence in the system & its reliability and performance. Load Testing helps identify the bottlenecks in the system under heavy user stress scenarios before they happen in a production environment.

Alt Text

You can find out more about loadtest in thisguru99

II.What is gatling:

Gatling is a loadtest tool created based on Scala, Akka and Netty.

You can findout more information about gatling inofficial gatling site

Gatling provides the DSL (Domain specific language) for us to create the scenario and setup for loadtesting.

Below is the code snippet for a gatling simulation scenario.

classConcurrentRequestsextendsBaseSimulation{valscn:ScenarioBuilder=scenario("Check concurrentRequests for get song detail api").exec(http("Get song detail api").get(GeneralConfigs.COCCOCMUSIC_MOBILE_API_SONGS+"/"+EnvironmentConfigs.COCCOCMUSIC_MOBILE_API_TESTDATA_SONGDETAIL.zingmp3+"_"+"audio").check(status.is(200)))setUp(scn.inject(nothingFor(4),atOnceUsers(1),rampUsersPerSec(1)to(2)during(10)).protocols(mobileApiProtocol)).maxDuration(100).assertions(global.responseTime.max.lt(2000),global.successfulRequests.percent.gt(95))}
Enter fullscreen modeExit fullscreen mode

Or you can use the gatling frontline version (commercial version) inhere

Alt Text

III.What is Scala:

Scala stands for scalable language which compile to java byte code.
Scala is a multiparadigm language that supports both object-oriented and functional programming style.

Alt Text

You can find out more about Scala inhere

IV.Set things up:

1.IntelliJ:

For our loadtest project, we will need to use intelliJ (a product by Jetbrains) which targets supporting JVM languages.

You can download the IntelliJ fromhere

2.Maven:

We will use maven as a build tool for the project, so you will need to install maven.

Alt Text

Please download maven fromhere

After download, please set the system path to the bin directory of maven

3.Java jdk:

Please download jdk8 for stable version working with Scala and Gatling.

You can download fromhere

4.Scala sdk:

You can set the scala sdk directly in IntelliJ.
IntelliJ will automatically found the scala sdk version for you and suggest if you have not done so.

The Scala sdk version you should install is 2.12.10 for stability

Alt Text

V.Get your hands dirty in the real project:

1.Create a maven scala project in IntelliJ:

Go to File -> New project -> tick on create from archetype -> choose scala-archetype-simple

Alt Text

2.Pom file:

We will add dependencies for our project in the pom file.

Also, we add the mechanism so that for each profile we parse into maven commandline, it will choose the correct env config file for us.

The pom file would be like below, a little bit long (:D)

#pomfile<projectxmlns="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/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>coccoc-music</groupId><artifactId>mobile-api-perf</artifactId><version>1.0-SNAPSHOT</version><inceptionYear>2008</inceptionYear><properties><scala.version>2.12.10</scala.version><gatling.version>3.3.1</gatling.version></properties><repositories><repository><id>scala-tools.org</id><name>Scala-ToolsMaven2Repository</name><url>http://scala-tools.org/repo-releases</url></repository></repositories><dependencies><dependency><groupId>org.scala-lang</groupId><artifactId>scala-library</artifactId><version>${scala.version}</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.4</version><scope>test</scope></dependency><dependency><groupId>org.specs</groupId><artifactId>specs</artifactId><version>1.2.5</version><scope>test</scope></dependency><dependency><groupId>io.gatling</groupId><artifactId>gatling-test-framework</artifactId><version>3.3.1</version></dependency><!--https://mvnrepository.com/artifact/io.gatling/gatling-core --><dependency><groupId>io.gatling</groupId><artifactId>gatling-core</artifactId><version>3.3.1</version></dependency><!--https://mvnrepository.com/artifact/io.gatling.highcharts/gatling-highcharts --><dependency><groupId>io.gatling.highcharts</groupId><artifactId>gatling-highcharts</artifactId><version>3.3.1</version><type>pom</type></dependency><!--https://mvnrepository.com/artifact/io.gatling.highcharts/gatling-charts-highcharts --><dependency><groupId>io.gatling.highcharts</groupId><artifactId>gatling-charts-highcharts</artifactId><version>3.3.1</version></dependency><!--https://mvnrepository.com/artifact/com.typesafe.play/play-json --><dependency><groupId>com.typesafe.play</groupId><artifactId>play-json_2.12</artifactId><version>2.8.1</version></dependency><!--https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-antrun-plugin --><dependency><groupId>org.apache.maven.plugins</groupId><artifactId>maven-antrun-plugin</artifactId><version>1.8</version></dependency></dependencies><build><testSourceDirectory>src/test/scala</testSourceDirectory><plugins><plugin><groupId>io.gatling</groupId><artifactId>gatling-maven-plugin</artifactId><version>3.0.5</version></plugin></plugins></build><profiles><profile><id>dev</id><build><plugins><plugin><artifactId>maven-antrun-plugin</artifactId><executions><execution><phase>clean</phase><goals><goal>run</goal></goals><configuration><tasks><!--copyfiledbofprofileandiWealthfortestenvironment--><deletefile="src/main/resources/env.json"/><copyfile="src/main/resources/env.dev.json"tofile="src/main/resources/env.json"/></tasks></configuration></execution></executions></plugin></plugins></build></profile><profile><id>stag</id><build><plugins><plugin><artifactId>maven-antrun-plugin</artifactId><executions><execution><phase>clean</phase><goals><goal>run</goal></goals><configuration><tasks><!--copyfiledbofprofileandiWealthfortestenvironment--><deletefile="src/main/resources/env.json"/><copyfile="src/main/resources/env.stag.json"tofile="src/main/resources/env.json"/></tasks></configuration></execution></executions></plugin></plugins></build></profile><profile><id>prd</id><build><plugins><plugin><artifactId>maven-antrun-plugin</artifactId><executions><execution><phase>clean</phase><goals><goal>run</goal></goals><configuration><tasks><!--copyfiledbofprofileandiWealthfortestenvironment--><deletefile="src/main/resources/env.json"/><copyfile="src/main/resources/env.prd.json"tofile="src/main/resources/env.json"/></tasks></configuration></execution></executions></plugin></plugins></build></profile></profiles></project>
Enter fullscreen modeExit fullscreen mode

3.Project structure:

main package:

We only define the resources file in the main package

The tree is like:

Alt Text

File env.json is the file where we store real env usage for current run
env.{env_name}.json is the files to store env for each environment
general.json is the file to store general config value

test package:

We will have the below package:

  • configsTo store configuration files to get value from config file in resources folder above

For example : The code below demonstrate how to store config value to the variable and use that in our test script

packagecoccocMusic.configsimportcoccocMusic.models.{Environments,PlaylistDetail,SongDetail}importutils.FileUtilsInternalimportplay.api.libs.json.JsonobjectEnvironmentConfigs{valfileUtilsInternal=newFileUtilsInternaldefenvironment():Environments={valjsonEnvironments=fileUtilsInternal.parseFileToJson(System.getProperty("user.dir")+"\\src\\main\\resources\\env.json")valenvironmentsValue=Json.fromJson[Environments](jsonEnvironments)environmentsValue.getOrElse(Environments).asInstanceOf[Environments]}finalvalCOCCOCMUSIC_MOBILE_API_DOMAIN:String=environment().coccocMusic.mobile.api.domainfinalvalCOCCOCMUSIC_MOBILE_API_BASICAUTH_USERNAME:String=environment().coccocMusic.mobile.api.basicAuth.usernamefinalvalCOCCOCMUSIC_MOBILE_API_BASICAUTH_PASSWORD:String=environment().coccocMusic.mobile.api.basicAuth.passwordfinalvalCOCCOCMUSIC_MOBILE_API_TESTDATA_PLAYLISTDETAIL:PlaylistDetail=environment().coccocMusic.mobile.api.testData.playlistDetailfinalvalCOCCOCMUSIC_MOBILE_API_TESTDATA_SONGDETAIL:SongDetail=environment().coccocMusic.mobile.api.testData.songDetailfinalvalCOCCOCMUSIC_MOBILE_API_TESTDATA_PLAYLISTSBYCATEGORY:Int=environment().coccocMusic.mobile.api.testData.playlistsByCategory}
Enter fullscreen modeExit fullscreen mode
  • executions: to store our test scenario

for example the scenario for test our home screen api:

packagecoccocMusic.executions.homeScreen.scenariosimportcoccocMusic.configs.GeneralConfigsimportcoccocMusic.setup.BaseSimulationimportio.gatling.core.Predef._importio.gatling.core.structure.ScenarioBuilderimportio.gatling.http.Predef._classConcurrentRequestsextendsBaseSimulation{valscn:ScenarioBuilder=scenario("Check concurrentRequests for homescreen api").exec(http("Get playlists and songs").get(GeneralConfigs.COCCOCMUSIC_MOBILE_API_HOMESCREEN).check(status.is(200)))valfromUsers:Double=Integer.getInteger("fromUsers",1).toDoublevaltoUsers:Double=Integer.getInteger("toUsers",1).toDoublevalduringSeconds:Integer=Integer.getInteger("duringSeconds",1)setUp(scn.inject(nothingFor(4),atOnceUsers(1),rampUsersPerSec(fromUsers)to(toUsers)during(duringSeconds)).protocols(mobileApiProtocol)).maxDuration(100).assertions(global.responseTime.max.lt(2000),global.successfulRequests.percent.gt(95))}
Enter fullscreen modeExit fullscreen mode

Above we define the endpoint for our api : GeneralConfigs.COCCOCMUSIC_MOBILE_API_HOMESCREEN

Get the input fromUsers, toUsers, duringSeconds from commandline, auto set to 1 if not defined (-DfromUsers={value} -DtoUsers={value} -DduringSeconds={value}

  • models:To define models for the environments and general configurations (Remember we got json file for resources, so models make total sense)

For example like below:

packagecoccocMusic.modelsimportplay.api.libs.functional.syntax._importplay.api.libs.json.{JsPath,Reads}importplay.api.libs.json._caseclassEnvironments(coccocMusic:CoccocMusic)caseclassCoccocMusic(mobile:Mobile)caseclassMobile(api:Api)caseclassApi(domain:String,basicAuth:BasicAuth,testData:TestData)caseclassBasicAuth(username:String,password:String)caseclassTestData(playlistDetail:PlaylistDetail,songDetail:SongDetail,playlistsByCategory:Int)caseclassPlaylistDetail(nhaccuatui:String,zingmp3:String)caseclassSongDetail(nhaccuatui:String,zingmp3:String)objectBasicAuth{implicitvalbasicAuthReads:Reads[BasicAuth]=((JsPath\"username").read[String]and(JsPath\"password").read[String])(BasicAuth.apply_)}objectTestData{implicitvaltestDataReads:Reads[TestData]=((JsPath\"playlistDetail").read[PlaylistDetail]and(JsPath\"songDetail").read[SongDetail]and(JsPath\"playlistsByCategory").read[Int])(TestData.apply_)}objectPlaylistDetail{implicitvalplaylistDetailReads:Reads[PlaylistDetail]=((JsPath\"nhaccuatui").read[String]and(JsPath\"zingmp3").read[String])(PlaylistDetail.apply_)}objectSongDetail{implicitvalsongDetailReads:Reads[SongDetail]=((JsPath\"nhaccuatui").read[String]and(JsPath\"zingmp3").read[String])(SongDetail.apply_)}objectApi{implicitvalapiReads:Reads[Api]=((JsPath\"domain").read[String]and(JsPath\"basicAuth").read[BasicAuth]and(JsPath\"testData").read[TestData])(Api.apply_)}objectMobile{implicitvalmobileReads:Reads[Mobile]=(__\"api").read[Api].map(Mobile.apply)}objectCoccocMusic{implicitvalcoccocMusicReads:Reads[CoccocMusic]=(__\"mobile").read[Mobile].map(CoccocMusic.apply)}objectEnvironments{implicitvalcoccocMusicReads:Reads[Environments]=(__\"coccocMusic").read[CoccocMusic].map(Environments.apply)}
Enter fullscreen modeExit fullscreen mode
  • setup :

We will set the BaseSimulation class for after use.

Example code below for setting the domain and basic auth:

packagecoccocMusic.setupimportcoccocMusic.configs.{EnvironmentConfigs,GeneralConfigs}importio.gatling.core.Predef._importio.gatling.http.Predef._importio.gatling.http.protocol.HttpProtocolBuilderclassBaseSimulationextendsSimulation{valmobileApiProtocol:HttpProtocolBuilder=http.baseUrl(EnvironmentConfigs.COCCOCMUSIC_MOBILE_API_DOMAIN+GeneralConfigs.COCCOCMUSIC_MOBILE_API_PREFIX+GeneralConfigs.COCCOCMUSIC_MOBILE_API_VERSION).basicAuth(EnvironmentConfigs.COCCOCMUSIC_MOBILE_API_BASICAUTH_USERNAME,EnvironmentConfigs.COCCOCMUSIC_MOBILE_API_BASICAUTH_PASSWORD)}
Enter fullscreen modeExit fullscreen mode
  • utils:This is where we define the utility we make for our project

Example for the utils to parse the json file to json object:

packageutilsimportplay.api.libs.json.{JsValue,Json}importscala.io.SourceclassFileUtilsInternal{defparseFileToJson(pathName:String):JsValue={valbufferSource=Source.fromFile(pathName)varjsonFormat:JsValue=nulltry{valsource:String=bufferSource.getLines.mkStringjsonFormat=Json.parse(source)}finally{bufferSource.close()}jsonFormat}}
Enter fullscreen modeExit fullscreen mode
  1. Run the scenario:

For example we can run the scenario for home screen api like below:

mvn clean gatling:test -Pdev -Dgatling.simulationClass=coccocMusic.executions.homeScreen.scenarios.ConcurrentRequests -DfromUsers=10 -DtoUsers=14 -DduringSeconds=20

Let me explain in detail

mvn clean : to clean the target folder

gatling:test to run the test

-Pdev : this is to remove the content in env.json file, and parse the content from env.dev.json to env.json (You can definitely change to -Pstag or -Pprd for different environment)

-Dgatling.simulationClass=coccocMusic.executions.homeScreen.scenarios.ConcurrentRequests : this to specify the simulationClass to run the test

-DfromUsers=10 -DtoUsers=14 -DduringSeconds=20 : this is to define the number of users to users, the duration for ramping up the requests

  1. The report file:

Will look like this where you can see the details for overall or for specific request (located in target/gatling/scenario_name/index.html)

Alt Text

VI.Source code:

The source code for the project you can findhere in github

That's it. I hope it helps

Peace as always!!!

Notes: If you feel this blog help you and want to show the appreciation, feel free to drop by :

This will help me to contributing more valued contents.

Happy coding!!!

Top comments(1)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
srkanpu profile image
srkanpu
  • Joined

This article is very good.. can you please add the git link it seems like it is broken

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Learning ishard work, but everything you learn is yours and will make subsequent learningeasier.
  • Location
    Hanoi, Vietnam
  • Joined

More fromcuongld2

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp