abstracta / jmeter-java-dsl

Simple JMeter performance tests API
https://abstracta.github.io/jmeter-java-dsl/
Apache License 2.0
477 stars 59 forks source link

Support for Jmeter plugins from Plugin Manager in DSL #176

Closed uddirulz closed 1 year ago

uddirulz commented 1 year ago

Hi,

I am currently exploring this Dsl. Looks fantastic. But was wondering if dsl support the various plugins available in JMETER plugin manager like CustomFunctions? Also does it support Azure plugin or any feature to support Azure?

rabelenda commented 1 year ago

Hello,

I'm glad you like it :).

Regarding plugins, we add built in support for any particular plugins as users request for them and we identify in such requests a general need that would benefit the entire community. We encourage users and in general de community to ask for features and improvements, this way we can properly prioritize work, and make the community be more involved in the development (aside for being able to help with actual code, the community can help us identify improvements or prioritizing work).

In particular for custom functions: how do you use it? What custom functions are the ones you usually use?

As for azure plugin, you mean the Azure Backend Listener? What other kind of Azure support would you like/be interested? We do have some ideas to improve Azure usage experience, but would love to hear community ideas.

In general, some things you can do while we don't implement support for a particular plugin or jmeter feature:

Regards

uddirulz commented 1 year ago

Hi,

Thanks for the detailed information. I was referring to the example provided in the https://abstracta.github.io/jmeter-java-dsl/guide/#custom-or-yet-not-supported-test-elements section. But when I am trying the same in my IDE it throws an error saying CustomSamplerGui cannot be resolved. An error is also present in CustomSampler ret = new CustomSampler();

Where is this CustomSampler coming from?

Thanks & Regards, Uddipan

On Tue, Mar 7, 2023 at 12:44 PM rabelenda @.***> wrote:

Hello,

I'm glad you like it :).

Regarding plugins, we add built in support for any particular plugins as users request for them and we identify in such requests a general need that would benefit the entire community. We encourage users and in general de community to ask for features and improvements, this way we can properly prioritize work, and make the community be more involved in the development (aside for being able to help with actual code, the community can help us identify improvements or prioritizing work).

In particular for custom functions: how do you use it? What custom functions are the ones you usually use?

As for azure plugin, you mean the Azure Backend Listener? What other kind of Azure support would you like/be interested? We do have some ideas to improve Azure usage experience, but would love to hear community ideas.

In general, some things you can do while we don't implement support for a particular plugin or jmeter feature:

Regards

— Reply to this email directly, view it on GitHub https://github.com/abstracta/jmeter-java-dsl/issues/176#issuecomment-1458109286, or unsubscribe https://github.com/notifications/unsubscribe-auth/AW2XHGDO7UEU3L7AJSX45ALW24USXANCNFSM6AAAAAAVRYVYB4 . You are receiving this because you authored the thread.Message ID: @.***>

rabelenda commented 1 year ago

Hello, CustomSampler and CustomSamplerGui are just "placeholders" to be replaced by the actual sampler or sampler gui (and more in general testElement and testElementGui) you want to use. The contribution guide goes in more detail (maybe too much in some cases) on what things to do to implement your own DSL test class.

One way to learn how to extend it is checking existing library source code. Eg: DummySampler is pretty simple and you might initially ignore CodeBuilder inner class. Here are some other simple examples: InfluxdbBackendListener, CsvDataSet, ResponseAssertion, ResponseFileSaver, JsonExtractor.

Note: Implementing a DSL class, should be considered intermediate to high complexity. Using wrapper module is simple to intermediate level. Asking for particular support explaining need is simple (even though is subject to prioritization of work to be done) and may contribute to the entire community.

uddirulz commented 1 year ago

Hi,

Thanks for your response again. I will go through the links. I have another question. Like in the GUI we have a module controller to modularize the Jmeter scripts, how can we do so in dsl? For example - I want to have a Login and Logout step each having its own transaction controller and http samplers, assertions etc, and re-use this for other scripts to make a workflow say Login -> Do Something -> Logout (where Login and Logout comes from the modularized code).

Thanks & Regards, Uddipan

On Tue, Mar 7, 2023 at 8:48 PM rabelenda @.***> wrote:

Hello, CustomSampler and CustomSamplerGui are just "placeholders" to be replaced by the actual sampler or sampler gui (and more in general testElement and testElementGui) you want to use. The contribution guide https://github.com/abstracta/jmeter-java-dsl/blob/master/CONTRIBUTING.md goes in more detail (maybe too much in some cases) on what things to do to implement your own DSL test class.

One way to learn how to extend it is checking existing library source code. Eg: DummySampler https://github.com/abstracta/jmeter-java-dsl/blob/master/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/samplers/DslDummySampler.java is pretty simple and you might initially ignore CodeBuilder inner class. Here are some other simple examples: InfluxdbBackendListener https://github.com/abstracta/jmeter-java-dsl/blob/master/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/InfluxDbBackendListener.java, CsvDataSet https://github.com/abstracta/jmeter-java-dsl/blob/master/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/configs/DslCsvDataSet.java, ResponseAssertion https://github.com/abstracta/jmeter-java-dsl/blob/master/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/assertions/DslResponseAssertion.java, ResponseFileSaver https://github.com/abstracta/jmeter-java-dsl/blob/master/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/ResponseFileSaver.java, JsonExtractor https://github.com/abstracta/jmeter-java-dsl/blob/master/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/postprocessors/DslJsonExtractor.java .

Note: Implementing a DSL class, should be considered intermediate to high complexity. Using wrapper module is simple to intermediate level. Asking for particular support explaining need is simple (even though is subject to prioritization of work to be done) and may contribute to the entire community.

— Reply to this email directly, view it on GitHub https://github.com/abstracta/jmeter-java-dsl/issues/176#issuecomment-1458853212, or unsubscribe https://github.com/notifications/unsubscribe-auth/AW2XHGCEBXMKY4APF6QKEKDW26NH7ANCNFSM6AAAAAAVRYVYB4 . You are receiving this because you authored the thread.Message ID: @.***>

rabelenda commented 1 year ago

Hello,

You can take advantage of java modularization capabilities (methods and/or classes). For example, suppose I have this:

@Test
  public void testListProducts() throws Exception {
    String baseUrl = "http://myservice.test";
    TestPlanStats stats = testPlan(
        threadGroup(1, 1,
            httpAuth()
                .basicAuth(baseUrl, "user", "pass")
            transaction("Home",
                httpSampler(baseUrl)
            ),
            transaction("Login",
                httpSampler(baseUrl + "/login")
                    .method(HTTPConstants.POST)
            ),
            transaction("List products",
              httpSampler(baseUrl + "/products")
            ),
            transaction("Logout",
                httpSampler(baseUrl + "/logout")
                    .method(HTTPConstants.POST)
            )
        )
    ).run();
    assertThat(stats.overall().errorsCount()).isEqualTo(0);

And want to create another test plan using same login and logout logic, you can come up with something like this:

private String baseUrl = "http://myservice.test";

  private DslAuthManager auth() {
    return httpAuth()
        .basicAuth(baseUrl, "user", "pass");
  }

  private DslTransactionController home() {
    return transaction("Home",
        httpSampler(baseUrl)
    );
  }

  private DslTransactionController login() {
    return transaction("Login",
        httpSampler(baseUrl + "/login")
            .method(HTTPConstants.POST)
    );
  }

  private DslTransactionController logout() {
    return transaction("Logout",
        httpSampler(baseUrl + "/logout")
            .method(HTTPConstants.POST)
    );
  }

  @Test
  public void testListProducts() throws Exception {
    TestPlanStats stats = testPlan(
        threadGroup(1, 1,
            auth(),
            home(),
            login(),
            transaction("List products",
                httpSampler(baseUrl + "/products")
            ),
            logout()
        )
    ).run();
    assertThat(stats.overall().errorsCount()).isEqualTo(0);
  }

  @Test
  public void testListLocations()
      throws Exception {
    TestPlanStats stats = testPlan(
        threadGroup(1, 1,
            auth(),
            home(),
            login(),
            transaction("List locations",
                httpSampler(baseUrl + "/locations")
            ),
            logout()
        )
    ).run();
    assertThat(stats.overall().errorsCount()).isEqualTo(0);
  }

Or something like this:

private String baseUrl = "http://myservice.test";

  private void testWith(ThreadGroupChild... children) throws IOException {
    List<ThreadGroupChild> threadGroupChildren = new ArrayList<>();
    threadGroupChildren.addAll(Arrays.asList(httpAuth()
            .basicAuth(baseUrl, "user", "pass"),
        transaction("Home",
            httpSampler(baseUrl)
        ),
        transaction("Login",
            httpSampler(baseUrl + "/login")
                .method(HTTPConstants.POST)
        )));
    threadGroupChildren.addAll(Arrays.asList(children));
    threadGroupChildren.add(transaction("Logout",
        httpSampler(baseUrl + "/logout")
            .method(HTTPConstants.POST)
    ));
    TestPlanStats stats = testPlan(
        threadGroup(1, 1,
            threadGroupChildren.toArray(new ThreadGroupChild[0])
        )
    ).run();
    assertThat(stats.overall().errorsCount()).isEqualTo(0);
  }

  @Test
  public void testListProducts() throws Exception {
    testWith(transaction("List products",
        httpSampler(baseUrl + "/products")
    ));
  }

  @Test
  public void testListLocations() throws Exception {
    testWith(transaction("List locations",
        httpSampler(baseUrl + "/locations")
    ));
  }

Or any other potential usage. You can extract logic to separate classes to be used in separate test clases. You can also generate jars to be reused by different projects as dependencies.

You can even parameterize reusable parts of the test, for example:

private DslHttpSampler httpRequest(String path) {
    return httpSampler("http://myservice.test" + path);
  }

  @Test
  public void testListProducts() throws Exception {
    TestPlanStats stats = testPlan(
        threadGroup(1, 1,
            httpAuth()
                .basicAuth("http://myservice.test", "user", "pass"),
            transaction("Home",
                httpRequest("")
            ),
            transaction("Login",
                httpRequest("/login")
                    .method(HTTPConstants.POST)
            ),
            transaction("List products",
                httpRequest("/products")
            ),
            transaction("Logout",
                httpRequest("/logout")
                    .method(HTTPConstants.POST)
            )
        )
    ).run();
    assertThat(stats.overall().errorsCount()).isEqualTo(0);
  }

I hope this helps.

rabelenda commented 1 year ago

We have just released a new version which includes AzureEngine that should greatly simplify integration with Azure.

If you have other ideas to simplify Azure usage, please let us know!

rabelenda commented 1 year ago

I'm closing this issue for the time being. We can re open, or open a new one if any related topic needs further discussion or attention.