You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jmeter.apache.org by Vladimir Sitnikov <si...@gmail.com> on 2023/06/06 20:20:31 UTC

Re: JMeter DSL discussion

I've been improving tests, and I realized there's a small change that
brings a decent way to build test plans.

I've updated PR https://github.com/apache/jmeter/pull/678
The PR includes samples for both Kotlin and Java
(see OpenModelThreadGroupConfigElementTest
and OpenModelThreadGroupConfigElementJavaTest).

I think we can merge it and make incremental improvements later.
The good part is that DSL is usable for all the components with no
modifications.

I might miss certain cases, however, it looks nice, at least for testing
JMeter itself.

WDYT?

Here's Java code:

HashTree tree = testTree(b -> {
    b.add(TestPlan.class, tp -> {
        b.add(OpenModelThreadGroup.class, tg -> {
            tg.setName("Thread Group");
            // 5 samples within 100ms
            // Then 2 sec pause to let all the threads to finish,
especially the ones that start at 99ms
            tg.setScheduleString("rate(50 / sec) random_arrivals(100 ms)
pause(2 s)");
            b.add(listener);
            b.add(CounterConfig.class, c -> {
                c.setVarName("counter");
                c.setIncrement(1);
            });
            b.add(DebugSampler.class, dbg -> {
                dbg.setName("${counter}");
                dbg.setDisplayJMeterProperties(false);
                dbg.setDisplayJMeterVariables(false);
                dbg.setDisplaySystemProperties(false);
            });
        });
    });
});

Here's Kotlin code:

val tree = testTree {
    TestPlan::class {
        OpenModelThreadGroup::class {
            name = "Thread Group"
            // 5 samples within 100ms
            // Then 2 sec pause to let all the threads to finish,
especially the ones that start at 99ms
            scheduleString = "rate(50 / sec) random_arrivals(100 ms)
pause(2 s)"
            listener()
            CounterConfig::class {
                varName = "counter"
                increment = 1
            }
            DebugSampler::class {
                name = "\${counter}"
                isDisplayJMeterProperties = false
                isDisplayJMeterVariables = false
                isDisplaySystemProperties = false
            }
        }
    }
}

Vladimir

Re: JMeter DSL discussion

Posted by Vladimir Sitnikov <si...@gmail.com>.
I've added a "copy code" context action (implementation, tests,
documentation), so it copies the code that users can paste into their
projects.
In other words, it enables configuring an element (or a subtree) in UI
and automatically generating code.

The generator uses element schemas to create a better-looking code,
and it resorts to setProperty(..., ...)
when the element lacks schema.

I do not think we need to add schemas for all the elements, and we
should be good to go.

It would be great if somebody could help review and test the change.
In theory, the change should be backward compatible.

Vladimir

Re: JMeter DSL discussion

Posted by Milamber <mi...@apache.org>.
Hi,

Seems a good approach for DSL features, Java/Kotlin as language seems 
good too.

Probably need:

* add a new page on manual to describe and explain how to create DSL 
plan (with your samples below)
* and (perhaps) indicate that is a 'beta' features, and will be improve 
in next version of JMeter.

Milamber

On 06/06/2023 21:20, Vladimir Sitnikov wrote:
> I've been improving tests, and I realized there's a small change that
> brings a decent way to build test plans.
>
> I've updated PR https://github.com/apache/jmeter/pull/678
> The PR includes samples for both Kotlin and Java
> (see OpenModelThreadGroupConfigElementTest
> and OpenModelThreadGroupConfigElementJavaTest).
>
> I think we can merge it and make incremental improvements later.
> The good part is that DSL is usable for all the components with no
> modifications.
>
> I might miss certain cases, however, it looks nice, at least for testing
> JMeter itself.
>
> WDYT?
>
> Here's Java code:
>
> HashTree tree = testTree(b -> {
>      b.add(TestPlan.class, tp -> {
>          b.add(OpenModelThreadGroup.class, tg -> {
>              tg.setName("Thread Group");
>              // 5 samples within 100ms
>              // Then 2 sec pause to let all the threads to finish,
> especially the ones that start at 99ms
>              tg.setScheduleString("rate(50 / sec) random_arrivals(100 ms)
> pause(2 s)");
>              b.add(listener);
>              b.add(CounterConfig.class, c -> {
>                  c.setVarName("counter");
>                  c.setIncrement(1);
>              });
>              b.add(DebugSampler.class, dbg -> {
>                  dbg.setName("${counter}");
>                  dbg.setDisplayJMeterProperties(false);
>                  dbg.setDisplayJMeterVariables(false);
>                  dbg.setDisplaySystemProperties(false);
>              });
>          });
>      });
> });
>
> Here's Kotlin code:
>
> val tree = testTree {
>      TestPlan::class {
>          OpenModelThreadGroup::class {
>              name = "Thread Group"
>              // 5 samples within 100ms
>              // Then 2 sec pause to let all the threads to finish,
> especially the ones that start at 99ms
>              scheduleString = "rate(50 / sec) random_arrivals(100 ms)
> pause(2 s)"
>              listener()
>              CounterConfig::class {
>                  varName = "counter"
>                  increment = 1
>              }
>              DebugSampler::class {
>                  name = "\${counter}"
>                  isDisplayJMeterProperties = false
>                  isDisplayJMeterVariables = false
>                  isDisplaySystemProperties = false
>              }
>          }
>      }
> }
>
> Vladimir
>