In JMeter, you used CSV Data Set Config to parameterize test data. In Gatling, the equivalent is called a Feeder. Feeders supply data to virtual users -- usernames, passwords, search terms, product IDs. Each time a virtual user calls feed(), it gets the next record. Without feeders, all your virtual users would send identical requests, which is unrealistic and often hits caching layers instead of actually stressing the system.
The most common feeder. Create a CSV file in src/test/resources/, and Gatling reads it automatically. Each column becomes a session variable.
email,password,name
john@test.com,pass123,John Doe
jane@test.com,pass456,Jane Smith
bob@test.com,pass789,Bob Wilson
alice@test.com,pass012,Alice Brown// CSV feeder -- reads from src/test/resources/data/users.csv
FeederBuilder<String> userFeeder = csv("data/users.csv")
.random(); // Pick random rows
ScenarioBuilder loginScenario = scenario("Login Flow")
.feed(userFeeder) // Each user gets a random row
.exec(
http("Login")
.post("/api/login")
.body(StringBody(
"{\"email\":\"#{email}\",\"password\":\"#{password}\"}"
))
.asJson()
.check(
status().is(200),
jsonPath("$.token").saveAs("authToken")
)
)
.pause(1)
.exec(
http("Get Profile")
.get("/api/profile")
.header("Authorization", "Bearer #{authToken}")
.check(jsonPath("$.name").is("#{name}")) // Verify correct user
);| Strategy | Behavior | Use When |
|---|---|---|
| queue() | Each record used once, in order. Error when exhausted. | Unique data needed (one-time registrations) |
| random() | Random record each time. Records reused. | General parameterization (most common) |
| shuffle() | Random order, each record used once. Error when exhausted. | Unique data in random order |
| circular() | Loops back to start when exhausted. | Limited data, many users (round-robin) |
[
{ "productId": 1, "productName": "Laptop", "price": 999 },
{ "productId": 2, "productName": "Phone", "price": 699 },
{ "productId": 3, "productName": "Tablet", "price": 499 },
{ "productId": 4, "productName": "Monitor", "price": 349 }
]// JSON feeder
FeederBuilder<Object> productFeeder = jsonFile("data/products.json")
.circular();
ScenarioBuilder browseScenario = scenario("Browse Products")
.feed(productFeeder)
.exec(
http("View Product: #{productName}")
.get("/api/products/#{productId}")
.check(
status().is(200),
jsonPath("$.price").ofInt().is("#{price}")
)
);Sometimes you need data that is generated on the fly -- random strings, UUIDs, timestamps. Custom feeders let you generate data programmatically.
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Supplier;
import java.util.stream.Stream;
// Custom feeder using a lambda
Iterator<Map<String, Object>> searchFeeder =
Stream.generate((Supplier<Map<String, Object>>) () -> {
Map<String, Object> map = new HashMap<>();
String[] terms = {"laptop", "phone", "tablet", "headphones", "camera"};
map.put("searchTerm", terms[ThreadLocalRandom.current().nextInt(terms.length)]);
map.put("minPrice", ThreadLocalRandom.current().nextInt(100, 500));
map.put("maxPrice", ThreadLocalRandom.current().nextInt(500, 2000));
return map;
}).iterator();
ScenarioBuilder searchScenario = scenario("Search Products")
.feed(searchFeeder)
.exec(
http("Search: #{searchTerm}")
.get("/api/products/search")
.queryParam("q", "#{searchTerm}")
.queryParam("minPrice", "#{minPrice}")
.queryParam("maxPrice", "#{maxPrice}")
.check(status().is(200))
);FeederBuilder<String> userFeeder = csv("data/users.csv").random();
FeederBuilder<Object> productFeeder = jsonFile("data/products.json").circular();
ScenarioBuilder purchaseFlow = scenario("Purchase Flow")
.feed(userFeeder) // Get user credentials
.exec(
http("Login").post("/api/login")
.body(StringBody("{\"email\":\"#{email}\",\"password\":\"#{password\"}"))
.asJson()
.check(jsonPath("$.token").saveAs("authToken"))
)
.pause(2)
.feed(productFeeder) // Get a product to buy
.exec(
http("Add to Cart").post("/api/cart")
.header("Authorization", "Bearer #{authToken}")
.body(StringBody("{\"productId\":#{productId},\"qty\":1}"))
.asJson()
.check(status().is(200))
);With queue() and shuffle() strategies, Gatling throws an error when the feeder runs out of data. If you have 100 records and 200 virtual users, the last 100 users will fail. Use random() or circular() when you have more users than data records. For unique data requirements (like user registration), make sure your CSV has enough rows.
Q: How do you handle test data parameterization in Gatling? Compare it with JMeter's approach.
A: Gatling uses Feeders for data parameterization, which serve the same purpose as JMeter's CSV Data Set Config. You create a CSV or JSON file with test data and load it using csv() or jsonFile(). Each column becomes a session variable referenced with #{variableName} syntax -- similar to JMeter's ${variableName}. Gatling offers four strategies: queue (sequential, one-time use), random (random with reuse), circular (round-robin), and shuffle (random, one-time use). For dynamic data, I create custom feeders using Java iterators that generate random values on the fly. The main advantage over JMeter is that feeders are code -- you can compose them, filter them, transform them with standard programming techniques instead of being limited to GUI configuration options.
Key Point: Feeders supply test data from CSV, JSON, or custom code. Use random() for most cases, circular() for limited data, and queue() when each record must be used exactly once.
Key Point: Feeders parameterize test data -- CSV for static data, custom iterators for dynamic data, four strategies for different needs