LoadRunner Script Migration
Migrate from LoadRunner to Gatling with an AI-powered agentic workflow
Migrate existing LoadRunner C scripts into Gatling Java simulations directly from VS Code. The AI agent automatically parses, analyzes, transforms, and generates Gatling code through a multi-step workflow with full visibility into each stage.
When to use the migration tool
- Migrating from LoadRunner: Migrate your entire LoadRunner test suite to Gatling
- Consolidating tools: Unify performance testing across teams
- Cost optimization: Reduce licensing costs while maintaining test coverage
- Enhanced CI/CD: Integrate with Gatling Cloud or on-premises deployments
How it works
The migration uses an AI agent workflow that processes your LoadRunner scripts through multiple steps:
- Parse: The agent reads and parses the LoadRunner C script, identifying requests, headers, parameters, and correlation directives
- Analyze: Script structure is analyzed to determine request flows, shared headers, query parameters, and data extraction patterns
- Transform: LoadRunner functions are mapped to their Gatling Java equivalents, with intelligent grouping of global headers into the HTTP protocol configuration
- Generate: A complete Gatling Java simulation is generated with proper structure and conventions
A progress UI displays each step as the agent works, giving you full visibility into the migration process.
Migration workflow
Single script migration
1. Right-click the LoadRunner script
In the VS Code Explorer, right-click any .c file and select “Migrate LoadRunner Script to Gatling”.
2. Provide the base URL
Enter the base URL for your target application (e.g., https://api.example.com). The agent uses this to generate accurate request paths in the output simulation.
3. Follow the agent’s progress
The progress UI shows each step of the migration in real time. The agent automatically handles:
- Parsing headers (
web_add_header,web_add_auto_header) and query parameters - Identifying correlation directives and generating extraction code
- Grouping global headers into the HTTP protocol configuration
- Generating per-request headers and query parameters where needed
If a transient error occurs, the agent automatically retries before reporting a failure.
4. Review the generated code
The agent produces a diff-based output so you can review exactly what was generated. Inspect the output for:
- Correct endpoint URLs and base URL
- Proper request parameters and payloads
- Accurate think times
- Appropriate checks and assertions
- Correct correlation code
5. Validate in your project
Copy the generated Java simulation file to your Gatling project and test it locally before deploying.
Batch migration
Migrate multiple LoadRunner scripts at once:
- Open the Command Palette (
Ctrl+Shift+P/Cmd+Shift+P) - Run “Migrate LoadRunner Scripts to Gatling”
- Provide the base URL
- The agent processes all
.cfiles in your workspace
What gets migrated
Automatically mapped
| LoadRunner | Gatling Java | Notes |
|---|---|---|
web_url() |
http(...).get() |
Migrated to GET request |
web_submit_form() |
http(...).post() |
Form data preserved as body |
web_submit_data() |
http(...).post() |
Request body migrated to form-encoded or JSON |
web_custom_request() |
http(...).method() |
Preserves custom method and headers |
web_add_header() |
.header() |
Per-request headers applied to the appropriate request |
web_add_auto_header() |
httpProtocol.header() |
Global headers added to the HTTP protocol configuration |
lr_think_time() |
pause() |
Think times become pause durations |
lr_start_transaction() / lr_end_transaction() |
Named groups | Transaction boundaries preserved as groups |
| Comments | // comments |
Context preserved in output |
Correlation and data extraction
| LoadRunner | Gatling Java | Notes |
|---|---|---|
web_reg_save_param() |
check(regex()).saveAs() |
Extracts values using left/right boundary regex |
web_reg_save_param() (JSON responses) |
check(jmesPath()).saveAs() |
Automatically inferred for JSON response bodies |
web_reg_find() |
check(bodyString().is()) |
Migrates to body validation check |
Form parameters with {PARAM} |
"#{PARAM}" in Gatling EL |
Parameter references migrated to Gatling expression language |
Requires manual review
| LoadRunner | Reason | Action |
|---|---|---|
lr_load_dll() |
External C libraries | Not migrated - implement in Java |
lr_save_string() |
String manipulation | Not migrated - use feeders or session vars |
lr_eval_string() |
String evaluation | Not migrated - use Gatling EL instead |
web_submit_form() with Ordinal |
Implicit form detection | TODO comment added - specify form fields manually |
| Complex C logic | Custom functions/conditionals | Review and reimplement in Java |
Migration examples
Example 1: Simple web flow
LoadRunner C script:
Action()
{
lr_think_time(5);
web_url("Home",
"URL=https://api.example.com/",
"Resource=0",
"RecContentType=text/html",
LAST);
lr_think_time(3);
web_submit_form("Login",
"Snapshot=t1.inf",
"Action=Login",
ITEMDATA,
"Name=email", "Value=user@example.com",
"Name=password", "Value=testpass123",
LAST);
lr_think_time(2);
web_url("Dashboard",
"URL=https://api.example.com/dashboard",
LAST);
return 0;
}
Migrated to Gatling Java:
import io.gatling.javaapi.core.*;
import io.gatling.javaapi.http.*;
import static io.gatling.javaapi.core.CoreDsl.*;
import static io.gatling.javaapi.http.HttpDsl.*;
public class MigratedSimulation extends Simulation {
HttpProtocolBuilder httpProtocol = http
.baseUrl("https://api.example.com")
.acceptHeader("text/html,application/json")
.acceptEncodingHeader("gzip, deflate")
.userAgentHeader("Mozilla/5.0");
ScenarioBuilder userFlow = scenario("User Flow")
.pause(5)
.exec(http("Home")
.get("/"))
.pause(3)
.exec(http("Login")
.post("/Login")
.formParam("email", "user@example.com")
.formParam("password", "testpass123")
.check(status().is(200)))
.pause(2)
.exec(http("Dashboard")
.get("/dashboard"));
{
setUp(userFlow.injectOpen(constantUsersPerSec(1).during(60)))
.protocols(httpProtocol);
}
}
Example 2: Request with data extraction
LoadRunner C script:
web_reg_save_param("ProductID",
"LB=product_id=",
"RB=&",
"Ord=1",
LAST);
web_url("Search",
"URL=https://store.example.com/search?q=laptop",
LAST);
web_url("View Product",
"URL=https://store.example.com/product/{ProductID}",
LAST);
Migrated to Gatling Java:
scenario("Product Search")
.exec(http("Search")
.get("/search?q=laptop")
.check(regex("product_id=(.*?)&").saveAs("ProductID")))
.exec(http("View Product")
.get("/product/#{ProductID}"))
Example 3: Global and per-request headers
LoadRunner C script:
web_add_auto_header("Accept", "application/json");
web_add_auto_header("X-Api-Version", "2");
web_add_header("X-Request-Id", "abc123");
web_url("Get Items",
"URL=https://api.example.com/items",
LAST);
Migrated to Gatling Java:
HttpProtocolBuilder httpProtocol = http
.baseUrl("https://api.example.com")
.header("Accept", "application/json")
.header("X-Api-Version", "2");
ScenarioBuilder scn = scenario("Items Flow")
.exec(http("Get Items")
.get("/items")
.header("X-Request-Id", "abc123"));
Post-migration review checklist
After migration, review the generated simulation:
Endpoints and URLs
- Base URL is correct
- All endpoints are properly mapped
- Query parameters are preserved
- Path variables are correct
Authentication
- Auth headers are present
- API keys or tokens are properly placed
- Session handling is correct
- Credentials are parameterized (not hardcoded)
Request data
- Form data is converted to proper format (JSON, form-encoded)
- Request payloads are accurate
- Custom headers are preserved
- Content-Type headers are correct
Think times and pauses
- Think times converted to appropriate pause durations
- Realistic pauses between requests (not too short/long)
- Transaction boundaries are clear
Validations and checks
- Assertions match original LoadRunner validations
- Data extraction (saveAs) works correctly
- Error handling is appropriate
Load injection
- Manually configure based on your test goals
- Default is single user—adjust for your load pattern
- Consider ramp-up/ramp-down strategies
Common post-migration adjustments
Add realistic load injection
The migration generates single-user simulations. Add your load pattern:
setUp(
userFlow.injectOpen(
rampUsers(100).during(60),
constantUsersPerSec(50).during(300)
)
).protocols(httpProtocol);
Update hardcoded values
Replace hardcoded credentials and data with feeders:
// Before
.post("/login")
.body(StringBody("{\"email\":\"user@example.com\",\"password\":\"pass123\"}"))
// After
.post("/login")
.body(StringBody("{\"email\":\"#{email}\",\"password\":\"#{password}\"}"))
Improve data extraction
The migration may use simple regex. For complex JSON responses, refine extractions:
// Before (migrated from LoadRunner)
.check(regex("token=([\\w]+)").saveAs("token"))
// After (more reliable)
.check(jmesPath("auth.token").saveAs("token"))
Adjust think times
Review and adjust pauses to match expected user behavior:
// Before (exact conversion)
.pause(5)
// After (realistic variation)
.pause(3, 7) // Random pause between 3-7 seconds
Add transaction grouping
Group related requests for better reporting:
.exec(http("Login").post("/login"))
.pause(2)
.exec(http("Get Profile").get("/profile"))
.exec(http("Get Settings").get("/settings"))
Limitations and workarounds
External C libraries
LoadRunner scripts sometimes call external C DLLs. These don’t migrate automatically.
Solution: Implement equivalent logic in Java.
Complex string operations
LoadRunner’s C language allows arbitrary string manipulation.
Solution: Implement custom Java functions or use exec() blocks.
Advanced correlation
Complex LoadRunner correlation rules may not migrate directly.
Solution: Review and manually adjust jmesPath() or regex() checks.
Custom LoadRunner functions
Your LoadRunner scripts may use custom functions.
Solution: Map these to equivalent Gatling patterns or reimplement them in Java.
Validation and testing
After migration:
- Test locally: Run the generated simulation in your dev environment
- Verify assertions: Confirm all checks pass against your target system
- Compare metrics: Run both LoadRunner and Gatling versions to compare results
- Review performance: Ensure the migrated simulation generates similar load profiles