Install
$ agentstack add skill-gatling-gatling-ai-extensions-gatling-convert-from-loadrunner ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Convert a LoadRunner script to a Gatling simulation
Instructions
Step 1: Find the LoadRunner script, configuration, and parameters files
- Search for LoadRunner script files:
Action.c,vuser_init.c,vuser_end.c: the standard three-file layout- Any
.cor.hfiles in a LoadRunner script directory (look for a.usror.lrsdescriptor file nearby) - A single combined
.cfile containing all sections - If multiple scripts or directories are found, ask the user to specify which one to convert
- Read all relevant
.cand.hfiles before proceeding - Read all relevant
.datfiles as plain text fil es - Search for a
default.cfgfile in the same directory and read it if present - Search for a
.prmfile in the same directory and read it if present
Step 2: Specify output
Either find an existing Gatling project or initialize a new one:
- Try to find an existing project with the /Gatling:gatling-detect-existing-project skill
- If no existing project is found, offer to create a new one with the /Gatling:gatling-bootstrap-project skill
Step 3: Conversion
- Convert the LoadRunner script to a Gatling test written in the specified language
- Write the output to the appropriate source directory of the Gatling project
Preamble
Java SDK
IF a variable needs to be saved inside the function AND the function is used within an Expression Language string:
- Move the code to an exec block that allows saving variables
When parsing dates, use java.time.format.DateTimeFormatter.ofPattern with system default zone and store it outside a function to avoid creation cost overhead.
For regular expression, use java.util.regex.Pattern.compile and store it outside a function to avoid creation cost overhead.
Gatling DSL
Be aware of DSL differences between all the languages Gatling support.
Some methods needs to be followed by .on() in Java, JavaScript and Kotlin but not Scala:
exitBlockOnFail { ... }:exitBlockOnFail().on(...)group("name") { ... }:group("name").on(...)- All loops, etc.
Session handling is different, e.g.:
session.getString("name")in Java, JavaScript and Kotlin,session("name").as[String]in Scala
Script structure
A LoadRunner script has up to three logical sections. Map them as follows:
vuser_init:beforeblock on the simulationAction: one or morescenario+execvuser_end:afterblock on the simulation
If the script only has an Action section (or a single .c file), produce a simulation with just a scenario.
Runtime settings from default.cfg
IF a default.cfg file is present for runtime settings that affects HTTP behavior:
Check the [General] section:
AutomaticTransactions=1and/orAutomaticTransactionsPerFunc=1: LoadRunner can auto-wrap actions or function calls into transactions. In Gatling, scenario and request names serve this purpose directly; nogroup()blocks are needed hereDefaultRunLogic: read the file, checkRunLogicActionOrderin the[RunLogicRunRoot]section actions order, chain them withexecContinueOnError=1: addexitHereIfFailed()between requests, otherwise Gatling continues on error by default; mention this to the userFailTransOnErrorMsg=1: apply the logic oflr_error_messageas Gatling checks if possible, wrap the transaction inside aexitBlockOnFail()block
Check the [ThinkTime] section:
Options=NOTHINK: keep pauses times but add.disablePauses()tosetUpOptions=RECORDED: keep pauses timesOptions=MULTIPLY: keep original pauses times, Gatling does not have a direct equivalent; mention this to the userOptions=RANDOM: keep pauses times, useThinkTimeRandomLowandThinkTimeRandomHigh, add.uniformPauses()tosetUpwith the closest number that matches the original plus or minus values
Check the [WEB] section:
CustomUserAgent: add.userAgentHeader()tohttpProtocolSearchForImages=1: add.inferHtmlResources()tohttpProtocol
HTTP requests
web_url(name, url, ...):http(name).get(url)web_submit_data(name, ...):http(name).post(url).formParam(...)web_submit_form(name, ...):http(name).post(url).formParam(...)web_custom_request(name, method, url, ...):http(name).httpRequest(method, url)web_add_header(name, value):.header(name, value)on the next request only, never onhttpProtocolweb_add_auto_header(name, value):httpProtocol.header(name, value)if called before any request; otherwise add.header(name, value)to every subsequent request manually
web_add_header is one-shot: it applies only to the immediately following request, then is cleared; never hoist it into httpProtocol web_add_auto_header persists from the point of the call onward. If it appears before any request in the script, map it to httpProtocol.header(...); if it appears mid-script, add .header(...) to each request that follows it
For web_submit_data, extract each ITEMDATA name/value pair as a .formParam(name, value).
Response checks and correlation
web_reg_find(text=...):.check(bodyString.contains(...))web_reg_save_param(param, LB=, RB=):.check(regex("LB(.*?)RB").saveAs("param"))web_reg_save_param_ex(...):.check(regex(...).saveAs(...))or.check(xpath(...))web_reg_save_param_json(...): convertQueryStringtojmesPathas.check(jmesPath(...))
Place .check(...) calls on the request that triggers the response being checked. web_reg_* functions are registered before the request they apply to, find the next web_url/web_submit_data and attach the check there.
Parameters and session variables
{ParamName}(LR parameter substitution):#{paramName}(Gatling EL)lr_save_string(value, "param"):.exec(session -> session.set("param", value))lr_param_sprintf("param", fmt, ...):.exec(session -> session.set("param", ...))with string formattinglr_eval_string("{param}"):session.getString("param")or"#{param}"in EL strings
For parameter files (.dat files referenced in the script or .usr descriptor), convert them to Gatling feeders. Copy the data file to the Gatling project's resources directory.
IF a .prm file is present, check it for each [parameter:] entries:
ColumnName="Col ":ColumnName="":Delimiter="": usecsv,tsv, orseparatedValues("", '')SelectNextRow="Random": use.random()SelectNextRow="Same line as ": ensure configuration is the same as ``SelectNextRow="Sequential": use.circular()SelectNextRow="Unique": use.queue()but it has no real Gatling equivalent; mention this to the user
Transactions
In LoadRunner, transactions are the only way to name and track individual requests, so developers routinely wrap every single request in a transaction. In Gatling, HTTP requests are named and tracked individually in reports, making single-request groups redundant.
Apply this rule when mapping lr_start_transaction / lr_end_transaction pairs:
- Single-request transaction (the block contains exactly one HTTP request and no nested transactions): drop the
group()wrapper entirely. Use the transaction name as thehttp("name")request name instead. - Multi-request transaction (the block contains more than one HTTP request, nested transactions, think times, or session logic): map to a
group("name")block as usual.
When FailTransOnErrorMsg=1 applies to a single-request transaction, wrap the request directly in exitBlockOnFail() without a surrounding group().
Logging
lr_output_message,lr_log_message: remove these or convert to a comment, Gatling handles logging at the framework levellr_error_message: keep, wrap inside anexecblock with session and use.markAsFailed()on session if necessary
Rendezvous points
lr_rendezvous("name"): remove, Gatling does not have a direct equivalent; mention this to the user if present
Resource files
Any files referenced in the script (e.g., request body files, upload files, data files) should be copied to the Gatling project's resources directory and referenced via RawFileBody("filename") or a feeder.
Step 4: Verify the code compiles
Use the build-tool skill if available.
Step 5: Post conversion
After the conversion, inform the user of:
- Any LoadRunner features that have no direct Gatling equivalent (rendezvous points, IP spoofing, etc.) and suggest alternatives
- Any hardcoded credentials or environment-specific values found in the script that should be parameterized
- Possible Gatling-idiomatic improvements, such as:
- Extracting the
HttpProtocolconfiguration (base URL, common headers) into a sharedhttpProtocolobject - Replacing repeated
formParamblocks with a map if there are many parameters - Using feeders for any remaining hardcoded user data
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: gatling
- Source: gatling/gatling-ai-extensions
- License: Apache-2.0
- Homepage: https://gatling.io
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.