Custom DSL by extending Gatling: How to Scala?

南楼画角 提交于 2019-12-23 03:36:22

问题


We're using Gatling to load test our application (and it works great). We're attempting to DRY up some of the code by making composable extensions on the Gatling classes (like ScenarioBuilder / ChainBuilder / etc. found in io.gatling.core.structure).

Here is an example of one of our scenarios:

val scn = scenario("Whatever")
  .exec(Authentication.FeederLogin(userCsvFile, password))
  .exec(User.ExtractId(User.SignIn()))
  .exec(FindPeople(50, "personIds"))

  // SPA load
  .exec(User.FetchLandingPageFor("${userId}"))

  .during(durationSeconds.seconds) {
    pace(3.seconds, 8.seconds)
      .exec(Person.Search("${personIds.random()}"))
      .pause(3.seconds, 10.seconds)

      // start the upload
      .exec(Upload.create())
  }

What we'd like to do is start to make some of that composable so we can re-use them in other scenarios. Something like this:

val scn = scenario("Whatever")
  .login()

  .during(durationSeconds.seconds) {
    pace(3.seconds, 8.seconds)
      .uploadFor("${personIds.random()}")
  }

// ...

object WhateverScenarios {
  implicit class ScenarioBuilderWithWhatevers(b: ScenarioBuilder) {

    def login() : ScenarioBuilder = {
      b.exec(Authentication.FeederLogin(userCsvFile, password))
      .exec(User.ExtractId(User.SignIn()))
      .exec(FindPeople(50, "personIds"))
    }

    def uploadFor(whom : String) : ScenarioBuilder {
      b.exec(Person.Search("${personIds.random()}"))
      .pause(3.seconds, 10.seconds)

      // start the upload
      .exec(Upload.create())
    }
  }
}

Full disclosure; I'm not super familiar with Scala. This works, but the problem is in the uploadFor in that at that point it's working with a ChainBuilder vs. a ScenarioBuilder.

I thought

Oh, simple! Just use generics!

Except I cannot get it to work :( It looks like most of these extend StructureBuilder[T] but I cannot seem to get a generic definition defined where I can use my WhateverScenarios in any context of a StructureBuilder[T].

Thanks in advance for any information that can be provided.


回答1:


So I was able to get past my issue, but I'm not entirely sure why I had to do this. What fixed my issue is the following:

object WhateverScenarios {
  implicit class StructureBuilderWithWhatevers[B <: io.gatling.core.structure.StructureBuilder[B]](b: B) {

    def login() : B = {
      b.exec(Authentication.FeederLogin(userCsvFile, password))
      .exec(User.ExtractId(User.SignIn()))
      .exec(FindPeople(50, "personIds"))
    }

    def uploadFor(whom : String) : ScenarioBuilder {
      b.exec(Person.Search("${personIds.random()}"))
      .pause(3.seconds, 10.seconds)

      // start the upload
      .exec(Upload.create())
    }
  }
}

The thing that was throwing me for a loop, was originally I tried to define it like this:

object WhateverScenarios {
  implicit class StructureBuilderWithWhatevers[B <: StructureBuilder[B]](b: B) {
  // ...
}

But when I did that, it didn't recognize login or uploadFor as being part of either ScenarioBuilder or ChainBuilder. Not sure why, but I had the specify the fully qualified package name for it to work ¯\_(ツ)_/¯

Edit

Turns out that the fully qualified package name was some weird artifact that I had on my machine. Doing a ./gradlew clean fixed the issue and I no longer have to use the fully qualified path name.



来源:https://stackoverflow.com/questions/50475447/custom-dsl-by-extending-gatling-how-to-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!