performancegatlingscala-gatling

Gatling - Dynamic Scenario, InjectionProfile, Assertion creation based on Configuration


I am attempting to write a simulation that can read from a config file for a set of apis that each have a set of properties.

That all seems to work no issue. But when I try to use the properties / CommonScenario request to build a set of Assertions it does not work as expected.

  // get active scenarios from the config
  val activeApiScenarios: List[String] = Utils.getStringListProperty("my.active_scenarios")


  // build all active scenarios from config
  var activeScenarios: Set[CommonScenario] = Set[CommonScenario]()
  activeApiScenarios.foreach { scenario =>
    activeScenarios += CommonScenarioBuilder()
      .withRequestName(Utils.getProperty("my." + scenario + ".request_name"))
      .withRegion(Utils.getProperty("my." + scenario + ".region"))
      .withConstQps(Utils.getDoubleProperty("my." + scenario + ".const_qps"))
      .withStartQps(Utils.getDoubleListProperty("my." + scenario + ".toth_qps").head)
      .withPeakQps(Utils.getDoubleListProperty("my." + scenario + ".toth_qps")(1))
      .withEndQps(Utils.getDoubleListProperty("my." + scenario + ".toth_qps")(2))
      .withFeeder(Utils.getProperty("my." + scenario + ".feeder"))
      .withAssertionP99(Utils.getDoubleProperty("my." + scenario + ".p99_lte_assertion"))
      .build
  }

  // build population builder set by adding inject profile values to scenarios
  var injectScenarios: Set[PopulationBuilder] = Set[PopulationBuilder]()
  var assertions : Set[Assertion] = Set[Assertion]()

  activeScenarios.foreach { scenario =>
    // create injection profiles from CommonScenarios
    injectScenarios += scenario.getCommonScenarioBuilder
      .inject(nothingFor(5 seconds),
        rampUsersPerSec(scenario.startQps).to(scenario.rampUpQps).during(rampOne seconds),
        rampUsersPerSec(scenario.rampUpQps).to(scenario.peakQps).during(rampTwo seconds),
        rampUsersPerSec(scenario.peakQps).to(scenario.rampDownQps) during (rampTwo seconds),
        rampUsersPerSec(scenario.rampDownQps).to(scenario.endQps).during(rampOne     seconds)).protocols(httpProtocol)

    // create scenario assertions this does not work for some reason
    assertions += Assertion(Details(List(scenario.requestName)), TimeTarget(ResponseTime, Percentiles(4)), Lte(scenario.assertionP99))
  }

  setUp(injectScenarios.toList)
    .assertions(assertions)

Note scenario.requestName is straight from the build scenario

    .feed(feederBuilder)
    .exec(commonRequest)

I would expect the Assertions get built from their scenarios into an iterable and pass into setUp().

What I get:

When I print out everything the scenarios, injects all look good but then I print my "assertions" and get 4 assertions for the same scenario name with 4 different Lte() values. This is generalized but I configured 12 apis all with different names and Lte() values, etc.

Details(List(Request Name)) - TimeTarget(ResponseTime,Percentiles(4.0)) - Lte(500.0) Details(List(Request Name)) - TimeTarget(ResponseTime,Percentiles(4.0)) - Lte(1500.0) Details(List(Request Name)) - TimeTarget(ResponseTime,Percentiles(4.0)) - Lte(1000.0) Details(List(Request Name)) - TimeTarget(ResponseTime,Percentiles(4.0)) - Lte(2000.0)

After the simulation the assertions all run like normal:

Request Name: 4th percentile of response time is less than or equal to 500.0 : false Request Name: 4th percentile of response time is less than or equal to 1500.0 : false Request Name: 4th percentile of response time is less than or equal to 1000.0 : false Request Name: 4th percentile of response time is less than or equal to 2000.0 : false

Not sure what I am doing wrong when building my assertions. Is this even a valid approach? I wanted to ask for help before I abandon this for a different approach.


Solution

  • Disclaimer: Gatling creator here.

    It should work.

    Then, there are several things I'm super not found of.

    assertions += Assertion(Details(List(scenario.requestName)), TimeTarget(ResponseTime, Percentiles(4)), Lte(scenario.assertionP99))
    

    You shouldn't be using the internal AST here. You should use the DSL like you've done for the injection profile.

    var assertions : Set[Assertion] = SetAssertion

    activeScenarios.foreach { scenario =>

    You should use map on activeScenarios (similar to Java's Stream API), not use a mutable accumulator.

    val activeScenarios = activeApiScenarios.map(???)
    val injectScenarios = activeScenarios.map(???)
    val assertions = activeScenarios.map(???)
    

    Also, as you seem to not be familiar with Scala, you should maybe switch to Java (supported for more than 1 year).