NCS-59 Create Load tests
This commit is contained in:
+4
-1
@@ -19,7 +19,10 @@ tasks.withType(io.gatling.gradle.GatlingRunTask) {
|
|||||||
jvmArgs = [
|
jvmArgs = [
|
||||||
'--add-opens=java.base/java.lang=ALL-UNNAMED',
|
'--add-opens=java.base/java.lang=ALL-UNNAMED',
|
||||||
"-Dtarget.baseUrl=${findProperty('baseUrl') ?: 'http://localhost:8080'}",
|
"-Dtarget.baseUrl=${findProperty('baseUrl') ?: 'http://localhost:8080'}",
|
||||||
"-Dgatling.authToken=${findProperty('authToken') ?: System.getenv('GATLING_AUTH_TOKEN') ?: ''}"
|
"-Dgatling.authToken=${findProperty('authToken') ?: System.getenv('GATLING_AUTH_TOKEN') ?: ''}",
|
||||||
|
"-Dhealthz.path=${findProperty('healthzPath') ?: '/health'}",
|
||||||
|
"-DmaxUsers=${findProperty('maxUsers') ?: '10'}",
|
||||||
|
"-DrampDuration=${findProperty('rampDuration') ?: '60'}"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import io.gatling.core.Predef._
|
import io.gatling.core.Predef._
|
||||||
|
import io.gatling.core.structure.ScenarioBuilder
|
||||||
import io.gatling.http.Predef._
|
import io.gatling.http.Predef._
|
||||||
import io.gatling.http.protocol.HttpProtocolBuilder
|
import io.gatling.http.protocol.HttpProtocolBuilder
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for all simulations.
|
|
||||||
*
|
|
||||||
* Reads runtime configuration from JVM system properties set by Gradle:
|
|
||||||
* -Dtarget.baseUrl=... (via -PbaseUrl=... on the Gradle command line)
|
|
||||||
* -Dgatling.authToken=... (via -PauthToken=... or env GATLING_AUTH_TOKEN)
|
|
||||||
*/
|
|
||||||
abstract class BaseSimulation extends Simulation {
|
abstract class BaseSimulation extends Simulation {
|
||||||
|
|
||||||
protected val baseUrl: String =
|
protected val baseUrl: String =
|
||||||
@@ -23,4 +17,21 @@ abstract class BaseSimulation extends Simulation {
|
|||||||
.baseUrl(baseUrl)
|
.baseUrl(baseUrl)
|
||||||
.header("Authorization", s"Bearer $authToken")
|
.header("Authorization", s"Bearer $authToken")
|
||||||
.header("Accept", "application/json")
|
.header("Accept", "application/json")
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
|
||||||
|
protected def scenarioFromEndpoint(endpoint: base.Endpoint): ScenarioBuilder = {
|
||||||
|
val base = endpoint.method.toUpperCase match {
|
||||||
|
case "GET" => http(endpoint.name).get(endpoint.path)
|
||||||
|
case "POST" => http(endpoint.name).post(endpoint.path)
|
||||||
|
case "PUT" => http(endpoint.name).put(endpoint.path)
|
||||||
|
case "DELETE" => http(endpoint.name).delete(endpoint.path)
|
||||||
|
case "PATCH" => http(endpoint.name).patch(endpoint.path)
|
||||||
|
}
|
||||||
|
val withBody = endpoint.body.fold(base)(b => base.body(StringBody(b)))
|
||||||
|
scenario(endpoint.name).exec(
|
||||||
|
withBody
|
||||||
|
.check(status.is(endpoint.expectedStatus))
|
||||||
|
.check(responseTimeInMillis.lte(endpoint.maxResponseTimeMs))
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package base
|
||||||
|
|
||||||
|
case class Endpoint(
|
||||||
|
name: String,
|
||||||
|
method: String,
|
||||||
|
path: String,
|
||||||
|
body: Option[String] = None,
|
||||||
|
expectedStatus: Int = 200,
|
||||||
|
maxResponseTimeMs: Int = 5000
|
||||||
|
)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package endpoints
|
||||||
|
|
||||||
|
import base.Endpoint
|
||||||
|
|
||||||
|
object BoardEndpoints {
|
||||||
|
|
||||||
|
val createGame: Endpoint = Endpoint(
|
||||||
|
name = "Create Game",
|
||||||
|
method = "POST",
|
||||||
|
path = "/api/board/game/",
|
||||||
|
expectedStatus = 201
|
||||||
|
)
|
||||||
|
|
||||||
|
val all: List[Endpoint] = List(createGame)
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package simulations
|
||||||
|
|
||||||
|
import base.BaseSimulation
|
||||||
|
import endpoints.BoardEndpoints
|
||||||
|
import io.gatling.core.Predef._
|
||||||
|
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
|
class LoadTestSimulation extends BaseSimulation {
|
||||||
|
|
||||||
|
private val maxUsers = sys.props.getOrElse("maxUsers", "10").toInt
|
||||||
|
private val rampDuration = sys.props.getOrElse("rampDuration", "60").toInt
|
||||||
|
|
||||||
|
setUp(
|
||||||
|
BoardEndpoints.all.map { endpoint =>
|
||||||
|
scenarioFromEndpoint(endpoint)
|
||||||
|
.inject(rampUsers(maxUsers).during(rampDuration.seconds))
|
||||||
|
}: _*
|
||||||
|
).protocols(httpProtocol)
|
||||||
|
}
|
||||||
@@ -1,35 +1,13 @@
|
|||||||
package simulations
|
package simulations
|
||||||
|
|
||||||
import base.BaseSimulation
|
import base.BaseSimulation
|
||||||
|
import endpoints.BoardEndpoints
|
||||||
import io.gatling.core.Predef._
|
import io.gatling.core.Predef._
|
||||||
import io.gatling.http.Predef._
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Smoke test: verifies the cluster is reachable and the bearer token is accepted.
|
|
||||||
*
|
|
||||||
* Runs a single virtual user that hits GET /healthz and asserts:
|
|
||||||
* - HTTP 200
|
|
||||||
* - Response time under 2 000 ms
|
|
||||||
*
|
|
||||||
* Use this as a reference when writing new simulations.
|
|
||||||
*
|
|
||||||
* Run:
|
|
||||||
* ./gradlew gatlingRun -PbaseUrl=http://<cluster-service> -PauthToken=<token>
|
|
||||||
*/
|
|
||||||
class SmokeTestSimulation extends BaseSimulation {
|
class SmokeTestSimulation extends BaseSimulation {
|
||||||
|
|
||||||
private val healthzPath: String =
|
|
||||||
sys.props.getOrElse("healthz.path", "/healthz")
|
|
||||||
|
|
||||||
private val scn = scenario("Smoke Test")
|
|
||||||
.exec(
|
|
||||||
http(s"GET $healthzPath")
|
|
||||||
.get(healthzPath)
|
|
||||||
.check(status.is(200))
|
|
||||||
.check(responseTimeInMillis.lte(2000))
|
|
||||||
)
|
|
||||||
|
|
||||||
setUp(
|
setUp(
|
||||||
scn.inject(atOnceUsers(1))
|
scenarioFromEndpoint(BoardEndpoints.createGame)
|
||||||
|
.inject(atOnceUsers(1))
|
||||||
).protocols(httpProtocol)
|
).protocols(httpProtocol)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user