From 3d195408e17ba9762ae481e5e2ba7dad0f6caf46 Mon Sep 17 00:00:00 2001 From: Stelios Anastasakis Date: Sun, 29 Dec 2024 20:20:12 +0200 Subject: [PATCH] [SCALA-568] Added gatling simulation for testing against a server with a steady load --- scala-gatling/README.md | 6 ++++ .../gatling/ChainRequestsProvider.scala | 31 +++++++++++++++++++ .../baeldung/gatling/PeakLoadSimulation.scala | 31 +++++++++++++++++++ .../baeldung/gatling/ScenariosProvider.scala | 31 +++++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 scala-gatling/README.md create mode 100644 scala-gatling/src/test/scala/com/baeldung/gatling/ChainRequestsProvider.scala create mode 100644 scala-gatling/src/test/scala/com/baeldung/gatling/PeakLoadSimulation.scala create mode 100644 scala-gatling/src/test/scala/com/baeldung/gatling/ScenariosProvider.scala diff --git a/scala-gatling/README.md b/scala-gatling/README.md new file mode 100644 index 000000000..00e62d269 --- /dev/null +++ b/scala-gatling/README.md @@ -0,0 +1,6 @@ +### Relevant Articles: +- [Testing With Gatling Using Scala]() + +### Gatling Executions +compile tests: `sbt test:compile` +then run the simulation: `sbt 'Gatling/testOnly com.baeldung.gatling.PeakLoadSimulation'` diff --git a/scala-gatling/src/test/scala/com/baeldung/gatling/ChainRequestsProvider.scala b/scala-gatling/src/test/scala/com/baeldung/gatling/ChainRequestsProvider.scala new file mode 100644 index 000000000..38c6195a7 --- /dev/null +++ b/scala-gatling/src/test/scala/com/baeldung/gatling/ChainRequestsProvider.scala @@ -0,0 +1,31 @@ +package com.baeldung.gatling + +import io.gatling.core.Predef._ +import io.gatling.core.structure.ChainBuilder +import io.gatling.http.Predef._ +import io.gatling.http.request.builder.HttpRequestBuilder + +object ChainRequestsProvider { + + def simpleRequest( + requestName: String, + requestPath: String, + expectedResponseStatus: Int + ): ChainBuilder = { + val request: HttpRequestBuilder = http(requestName) + .get(requestPath) + .check(status.is(expectedResponseStatus)) + .check(bodyString.optional.saveAs("sBodyString")) + + exec(session => session.markAsSucceeded) + .exec(request) + .doIf(_.isFailed) { + exec { session => + println("***Failure on [" + requestPath + "] endpoint:") + print("Gatling Session Data: ") + println(session.attributes.get("sBodyString")) + session + } + } + } +} diff --git a/scala-gatling/src/test/scala/com/baeldung/gatling/PeakLoadSimulation.scala b/scala-gatling/src/test/scala/com/baeldung/gatling/PeakLoadSimulation.scala new file mode 100644 index 000000000..186863d1f --- /dev/null +++ b/scala-gatling/src/test/scala/com/baeldung/gatling/PeakLoadSimulation.scala @@ -0,0 +1,31 @@ +package com.baeldung.gatling + +import io.gatling.core.Predef.{details, _} +import com.baeldung.gatling.ChainRequestsProvider.simpleRequest +import com.baeldung.gatling.ScenariosProvider.getScenario + +class PeakLoadSimulation extends Simulation { + + setUp( + getScenario( + "getExistingEndpoint", + simpleRequest("request_status_endpoint", "/health/status", 200), + 50, + 10, + 60 + ), + getScenario( + "nonExistingEndpoint", + simpleRequest("request_wrong_endpoint", "/health/status1", 200), + 5, + 10, + 60 + ) + ).assertions( + details("request_status_endpoint").successfulRequests.percent.gt(99.99), + details("request_status_endpoint").responseTime.percentile4.lt(20), + details("request_status_endpoint").requestsPerSec.gt(40), + details("request_wrong_endpoint").successfulRequests.percent.lt(1), + details("request_wrong_endpoint").responseTime.percentile4.lt(20) + ) +} diff --git a/scala-gatling/src/test/scala/com/baeldung/gatling/ScenariosProvider.scala b/scala-gatling/src/test/scala/com/baeldung/gatling/ScenariosProvider.scala new file mode 100644 index 000000000..3a5b9259b --- /dev/null +++ b/scala-gatling/src/test/scala/com/baeldung/gatling/ScenariosProvider.scala @@ -0,0 +1,31 @@ +package com.baeldung.gatling + +import io.gatling.core.Predef._ +import io.gatling.core.structure.{ChainBuilder, PopulationBuilder} +import io.gatling.http.Predef.http + +import scala.language.postfixOps + +object ScenariosProvider { + + private val httpProtocol = + http.baseUrl("http://localhost:8080").disableCaching.disableFollowRedirect + + def getScenario( + scenarioName: String, + request: ChainBuilder, + tps: Double, + rampUpSeconds: Int, + durationSeconds: Int + ): PopulationBuilder = { + scenario(scenarioName) + .exec(request) + .inject( + rampUsersPerSec(0).to(tps).during(rampUpSeconds), + constantUsersPerSec(tps) + .during(durationSeconds - rampUpSeconds - rampUpSeconds), + rampUsersPerSec(tps).to(0).during(rampUpSeconds) + ) + .protocols(httpProtocol) + } +}