Skip to content

Commit

Permalink
Add jsr223PreProcessor to allow generating dynamic info per request
Browse files Browse the repository at this point in the history
  • Loading branch information
rabelenda committed Feb 5, 2024
1 parent d4334a9 commit 4d58379
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Abstracta.JmeterDsl.Core.PreProcessors
{
using static JmeterDsl;

public class DslJsr223PreProcessorTest
{
[Test]
public void ShouldUseDefinedLabelWhenPreProcessorSettingLabelInTestPlan()
{
var stats = TestPlan(
ThreadGroup(1, 1,
DummySampler("ok")
.Children(
Jsr223PreProcessor("sampler.name = 'test'")
)
)).Run();
Assert.That(stats.Labels["test"].SamplesCount, Is.EqualTo(1));
}
}
}
23 changes: 23 additions & 0 deletions Abstracta.JmeterDsl/Core/PreProcessors/DslJsr223PreProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Abstracta.JmeterDsl.Core.TestElements;

namespace Abstracta.JmeterDsl.Core.PreProcessors
{
/// <summary>
/// Allows running custom logic before executing a sampler.
/// <br/>
/// This is a very powerful and flexible component that allows you to modify variables, sampler,
/// context, etc., before running a sampler (for example to generate dynamic requests
/// programmatically).
/// <br/>
/// By default, provided script will be interpreted as groovy script, which is the default setting
/// for JMeter. If you need, you can use any of JMeter provided scripting languages (beanshell,
/// javascript, jexl, etc.) by setting the <see cref="DslJsr223TestElement{T}.Language(string)"/> property.
/// </summary>
public class DslJsr223PreProcessor : DslJsr223TestElement<DslJsr223PreProcessor>, IMultiLevelTestElement
{
public DslJsr223PreProcessor(string name, string script)
: base(name, script)
{
}
}
}
24 changes: 24 additions & 0 deletions Abstracta.JmeterDsl/Core/TestElements/DslJsr223TestElement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace Abstracta.JmeterDsl.Core.TestElements
{
/// <summary>
/// Abstracts common logic used by JSR223 test elements.
/// </summary>
public abstract class DslJsr223TestElement<T> : BaseTestElement
where T : DslJsr223TestElement<T>
{
protected readonly string _script;
protected string _language;

public DslJsr223TestElement(string name, string script)
: base(name)
{
_script = script;
}

public T Language(string language)
{
_language = language;
return (T)this;
}
}
}
25 changes: 25 additions & 0 deletions Abstracta.JmeterDsl/JmeterDsl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Abstracta.JmeterDsl.Core.Controllers;
using Abstracta.JmeterDsl.Core.Listeners;
using Abstracta.JmeterDsl.Core.PostProcessors;
using Abstracta.JmeterDsl.Core.PreProcessors;
using Abstracta.JmeterDsl.Core.Samplers;
using Abstracta.JmeterDsl.Core.ThreadGroups;
using Abstracta.JmeterDsl.Http;
Expand Down Expand Up @@ -246,6 +247,30 @@ public static DslDummySampler DummySampler(string responseBody)
public static DslDummySampler DummySampler(string name, string responseBody)
=> new DslDummySampler(name, responseBody);

/// <summary>
/// Builds a JSR223 Pre Processor which allows including custom logic to modify requests.
/// <br/>
/// This preprocessor is very powerful, and lets you alter request parameters, jmeter context and
/// implement any kind of custom logic that you may think.
/// </summary>
/// <param name="script">contains the script to be executed by the preprocessor. By default, this will be
/// a groovy script, but you can change it by setting the language property in the
/// returned post processor.</param>
/// <returns>the JSR223 Pre Processor instance</returns>
/// <seealso cref="DslJsr223PreProcessor"/>
public static DslJsr223PreProcessor Jsr223PreProcessor(string script) =>
Jsr223PreProcessor(null, script);

/// <summary>
/// Same as <see cref="Jsr223PreProcessor(string)"/> but allowing to set a name on the preprocessor.
/// <br/>
/// The name is used as logger name which allows configuring log level, appender, etc., for the
/// preprocessor.
/// </summary>
/// <seealso cref="Jsr223PreProcessor(string)"/>
public static DslJsr223PreProcessor Jsr223PreProcessor(string name, string script) =>
new DslJsr223PreProcessor(name, script);

/// <summary>
/// Builds a Regex Extractor which allows using regular expressions to extract different parts of a
/// sample result (request or response).
Expand Down
1 change: 1 addition & 0 deletions docs/guide/request-generation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@

<!-- @include: loops/index.md -->
<!-- @include: csv-dataset.md -->
<!-- @include: jsr223-pre-processor.md -->
36 changes: 36 additions & 0 deletions docs/guide/request-generation/jsr223-pre-processor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
### Provide request parameters programmatically per request

So far we have seen a how to generate requests with information extracted from CSV, but this is not enough for some scenarios. When you need more flexibility and power you can use `jsr223preProcessor` to specify your own logic to build each request.

Here is an example:

```cs
using System;
using System.Net.Http.Headers;
using System.Net.Mime;
using static Abstracta.JmeterDsl.JmeterDsl;

public class PerformanceTest
{
[Test]
public void LoadTest()
{
var stats = TestPlan(
ThreadGroup(5, 10,
HttpSampler("http://my.service")
.Post("${REQUEST_BODY}", new MediaTypeHeaderValue(MediaTypeNames.Text.Plain))
.Children(Jsr223PreProcessor("vars.put('REQUEST_BODY', '{\"time\": \"' + Instant.now() + '\"}')"))
)
).Run();
Assert.That(stats.Overall.SampleTimePercentile99, Is.LessThan(TimeSpan.FromSeconds(5)));
}
}
```

::: tip
For the time being only JSR223 scripts can be used. By default `Groovy` is used, but you can change to others by using the provided `Language()` method.

We plan in the future to look for alternatives as to be able to use .Net code as pre processor. If you are interested in this you can let us know in [this issue](https://github.com/abstracta/jmeter-dotnet-dsl/issues/3) posting your use case.
:::

Check [DslJsr223PreProcessor](/Abstracta.JmeterDsl/Core/PreProcessors/DslJsr223PreProcessor.cs) for more details and additional options.

0 comments on commit 4d58379

Please sign in to comment.