CSV Parameterization in JMeter
A hundred identical visitors typing the same name, searching for the same word, and buying the same item do not look like a crowd. They look like one person copied a hundred times. A CSV file gives each virtual visitor their own identity and their own errands.
Imagine you are organising a school sports day with five hundred children, and every child is handed a card with exactly the same name on it. The teacher at the finish line calls out the name and five hundred children step forward. Nothing about the day tells you how the school really copes, because the situation could never happen in real life.
A load test with fixed data creates the same silly situation. If every virtual user logs in as “testuser” and searches for “shoes,” the server soon works out that the same questions are being asked again and again. It answers from memory instead of working, it refuses duplicate logins, or it locks the one account that everybody is fighting over. The results look strange, and they teach you very little about real visitors.
The cure is parameterization: replacing fixed values in your test with values that change for each user and each pass. In Apache JMeter, the most popular way to do this is a small element called the CSV Data Set Config, which reads rows from a plain text file. This guide takes you from the first idea to the habits of experienced performance engineers: how the element works, what every setting does, how to size and prepare your data, how to avoid the traps, and how to keep it reliable in large and distributed tests.
1What Is CSV Parameterization?
It means feeding your test with real-looking, varied data that is stored in a simple file instead of being typed into each request.
Two Words Explained
A parameter is a value that can change, such as a user name, a search word, or a product number. To parameterize a test is to replace a fixed value with a named placeholder, so the real value is filled in when the request is sent. A CSV file is a plain text file in which each line is one record and the pieces of each record are separated by a comma. CSV stands for comma-separated values. Spreadsheet programs can open and save such files, which makes them easy to prepare.
How It Looks in Practice
Suppose your file has three columns and four rows:
| username | password | searchWord |
|---|---|---|
| user001 | pass001 | shoes |
| user002 | pass002 | jacket |
| user003 | pass003 | backpack |
| user004 | pass004 | watch |
The first virtual user takes the first row, the second takes the second row, and so on. Each user logs in with their own name and searches for their own word. The login request does not contain a fixed name any more. It contains a placeholder that JMeter replaces with the value from the user’s row.
Think of a theatre that gives each actor a script page. The play is the same, but each actor reads different lines. The CSV file is the stack of script pages, and the CSV Data Set Config is the stagehand who hands one page to each actor as they walk on stage.
2Why Fixed Data Fails Under Load
Identical data does not merely look unrealistic. It actively spoils your measurements.
The Problems of One Identity
- Caching makes the system look faster than it is. When the same search is repeated, the server may keep the answer in fast memory. Your test measures that cheap memory lookup instead of the real work.
- Sessions clash. Many applications refuse or interfere with multiple simultaneous logins of the same account, or silently log the first one out.
- Locks and conflicts. If a hundred users update the same record at once, the database makes them queue up. That queue is not what real traffic looks like.
- Duplicate rejections. A shop may refuse to create the same order twice, or a sign-up form may refuse a repeated email address.
- Hot spots. One account or one item receives all the traffic, so you test one corner of the system and ignore the rest.
What Varied Data Gives You
| Aspect | With Fixed Data | With CSV Data |
|---|---|---|
| Caching behaviour | Unrealistically high cache hits | A realistic mix of hits and misses |
| Login sessions | Conflicts on a single account | One account per user |
| Database load | Hammers a single row | Spreads across many rows |
| Result trustworthiness | Often too optimistic or just odd | Closer to production behaviour |
Parameterization and correlation are two different ideas. Parameterization feeds the test with data that you prepared. Correlation catches data that the server invented during the test, such as a session ticket. Real tests need both.
3Core Concepts You Need First
Eight small ideas explain nearly everything about the CSV Data Set Config.
Virtual User
A thread inside JMeter that behaves like one visitor. Each runs through the test steps, often many times.
Iteration
One complete pass of a virtual user through the steps of the test. A user who loops five times has five iterations.
Variable
A named box that holds a value for one user. Later steps open the box by writing its name inside a dollar sign and curly braces.
Config Element
An element that supplies settings or data to samplers in its scope, without sending any request itself.
Row Pointer
A marker that remembers which line of the file will be handed out next, shared by all users.
End of File
The moment when the pointer has passed the last line. What happens next depends on your settings.
Delimiter
The character that separates the values within a line. A comma is the usual choice.
Sharing Mode
A setting that decides who shares the same file pointer: all users, one group, or each user alone.
The Rule of One Row per Iteration
Remember this sentence: each virtual user takes one new row every time it begins a new iteration. All requests inside the same iteration see the same row. That is why a login and the search that follows can use the same user’s name and word. On the next iteration, the user receives the next unused row.
4Preparing a Good CSV File
The element is easy to configure. The quality of your file decides whether the test is meaningful.
Format Rules
- One record per line. Each line is one set of values for one iteration.
- The same number of columns on every line. A short line leaves variables with stale or empty values.
- A consistent delimiter. Use the same separator everywhere, and make sure the values themselves do not contain that character, unless they are wrapped in quotation marks and quoted data is allowed.
- Plain text only. Save as CSV text, not as a spreadsheet document.
- No stray blank lines. Empty lines, especially at the end, can cause confusing behaviour.
- A known encoding. Save as UTF-8 when the data contains accented letters or other non-English characters.
- Optional header line. The first line may hold the column names, which you can use as variable names.
Choosing the Content
Think about which values change between real visitors and which of them matter for the behaviour of the system. Typical columns are credentials, search words, product or category identifiers, customer numbers, addresses, quantities, and coupon codes. Do not parameterize things that never change, such as the name of the website, because that only adds clutter.
How Many Rows
Count carefully. A test that never repeats a row needs at least as many rows as the number of users multiplied by the number of iterations each will run. A test that is allowed to reuse rows needs fewer, but you must make sure reuse does not cause trouble such as one account logged in twice at once. A later chapter shows the arithmetic.
Open the finished file in a plain text editor, not just a spreadsheet program. A text editor shows you exactly what JMeter will read, including any odd characters, extra spaces, or blank lines that a spreadsheet hides.
5Adding the CSV Data Set Config to a Test Plan
Adding the element takes a few clicks. Choosing its settings takes thought, and the next chapters explain each one.
Prepare and Save the File
Create the data file and save it in a folder you can find easily, preferably next to the test plan.
Right-Click the Thread Group
Choose Add, then Config Element, then CSV Data Set Config.
Name It Clearly
Rename it to say what the data is, such as “Login accounts.”
Point to the File
Enter the file name or path, or use the browse button.
Name the Variables
List the variable names in the same order as the columns, separated by commas.
Set the Behaviour at the End of the File
Decide whether to start over, stop the user, or let the variables become a marker value.
Use the Variables in Your Requests
Replace the fixed values with the variable names written inside a dollar sign and curly braces.
Test With a Few Users
Run three or four users and look at the requests to confirm that each one received a different row.
6Architecture: Where the Data Comes From
The file sits outside JMeter. The config element reads it, and the virtual users draw rows from it.
flowchart TD
F["CSV file on disk: one record per line"] --> C["CSV Data Set Config: reads lines and hands them out"]
C --> T1["Virtual User 1: gets row 1"]
C --> T2["Virtual User 2: gets row 2"]
C --> T3["Virtual User 3: gets row 3"]
T1 --> V1["Variables: username, password, searchWord"]
T2 --> V2["Variables: username, password, searchWord"]
T3 --> V3["Variables: username, password, searchWord"]
V1 --> S["Samplers: Login, Search, Add to basket"]
V2 --> S
V3 --> S
S --> SYS["System under test"]
Reading the Diagram
The file holds the records. The CSV Data Set Config reads lines from it and hands one to each virtual user as that user begins an iteration. Each user stores the values in their own variables. The samplers then send requests with those values filled in, so the system under test sees three different people.
The Main Components
- The file. A passive store of records.
- The config element. The one that opens the file, tracks the position, and hands out rows.
- The virtual users. The ones that ask for rows and keep their own copy as variables.
- The samplers. The elements that read the variables and put the values into requests.
The element reads the file when the test starts and then reads one line at a time. It is efficient for large files, because it does not need to load the whole file into memory at once.
7Internal Working: The Shared Row Pointer
Behind the scenes, there is a single marker moving down the file, and users take turns using it.
sequenceDiagram
participant U1 as Virtual User 1
participant U2 as Virtual User 2
participant C as CSV Data Set Config
participant F as CSV File
U1->>C: Start iteration, ask for next row
C->>F: Read line at pointer position
F-->>C: Line 1
C-->>U1: Values of line 1 become variables
C->>C: Move pointer to line 2
U2->>C: Start iteration, ask for next row
C->>F: Read line at pointer position
F-->>C: Line 2
C-->>U2: Values of line 2 become variables
C->>C: Move pointer to line 3
What the Diagram Shows
When the first user begins an iteration, it asks the element for a row. The element reads the line at the pointer, gives the values to that user, and moves the pointer forward. When the second user asks, it receives the next line. No two users receive the same line, because the pointer moves with each request. The reading is done carefully, so that two users asking at the same instant still receive different lines.
When the Row Is Taken
A user takes a row at the start of each iteration, not at the moment a request uses the variable. So if a journey has ten requests, all ten use the same row. The next row is taken only when the user begins the next pass.
What Is Stored
The values are stored as variables belonging to that user. Another user cannot see them. This is the reason that two users can use the same variable name and still hold different values at the same moment.
Imagine a queue at a ticket office. A clerk hands out numbered tickets in order. Whoever steps up next receives the next number, and nobody receives the same number twice. The row pointer is the ticket counter, and the rows are the numbers.
8Using the Variables in Requests
The data is only useful once your requests actually refer to it.
Writing a Placeholder
To use a stored value, write the variable name inside a dollar sign and curly braces wherever a value is expected. JMeter replaces it with the user’s value just before the request is sent. This works in the path, parameters, headers, body, and most other fields. For example, a login request’s username field would hold the placeholder for the variable called username, instead of a fixed name.
Names Must Match Exactly
Variable names are case sensitive. A variable called searchWord is not the same as searchword. If the placeholder name differs even slightly from the name in the CSV Data Set Config, JMeter does not find a value. It sends the placeholder text itself, and the server rejects it.
Where the Placeholder Can Go
| Location | Example Use |
|---|---|
| Request parameters | Username and password fields of a login form |
| Request path | A product number inside an address |
| Request body | Fields of a data message sent to an interface |
| Headers | A custom header that carries a customer number |
| Assertions | An expected phrase that includes the user’s own name |
| Other elements | Think times, conditions, and controllers that read a value |
If you see the literal placeholder text in a failed request, JMeter could not find a variable of that name. Check the spelling, check that the config element is in scope, and check that the variable names list matches the file’s columns.
9The Settings at a Glance
Before studying each setting in detail, look at the whole panel and learn its shape.
| Setting | Meaning | Usual Choice |
|---|---|---|
| Name and Comments | Label and notes for people | A descriptive name |
| Filename | Where the data file is | A path relative to the plan, so it works on other machines |
| File encoding | How characters are stored in the file | UTF-8 for text with special characters |
| Variable names | Names for the columns, in order, separated by commas | Descriptive names that match the file |
| Ignore first line | Skip a header line | On when the file has a header and names are typed in |
| Delimiter | The separator between values | A comma |
| Allow quoted data | Treat text in quotation marks as one value even if it has delimiters | On only when needed |
| Recycle on EOF | Start again from the top after the last line | Depends on whether reuse is acceptable |
| Stop thread on EOF | End the user when the data runs out | On when running out of data should end the user |
| Sharing mode | Who shares the row pointer | All threads |
EOF is short for end of file. The next chapters explain each setting in turn, using small examples and real-life comparisons.
Setting names and defaults can differ slightly between JMeter versions. Open the panel in your own version and read the labels and tooltips, rather than assuming they match this table exactly.
10The Filename Setting: Paths That Work Everywhere
A test that works on your laptop but cannot find its data file on the load generator is a very common surprise.
Absolute and Relative Paths
An absolute path gives the full location of a file from the top of the disk, such as a drive letter and a chain of folders. It works only on a machine that has the same folders. A relative path gives the location starting from a known folder. In JMeter, a relative path is counted from the folder that holds the test plan file. If the data file sits beside the plan, the filename alone is enough.
| Style | Advantage | Risk |
|---|---|---|
| Absolute path | Unambiguous on one machine | Breaks when the plan moves to another machine or another operating system |
| Relative path | Moves with the plan, easy to share in version control | Breaks if the plan is started from a different working folder than expected, or the data file is forgotten |
| Path from a property | One plan serves many environments; the folder is passed at start-up | Needs discipline to set the property every time |
Distributed Testing and Files
In a distributed test, JMeter does not copy your data file to the worker machines. The controller sends the plan, but each worker opens the data file itself. So the file must exist on every worker, at the path the plan names. If it is missing on one worker, the users on that worker fail to get any data.
A Good Habit
Keep the test plan and its data files together in one folder under version control, and use relative paths. Then anyone who fetches the folder gets everything needed to run the test.
When a data file cannot be opened, JMeter writes a message in its log, and the users may run with unset variables. Always check the log after the first short run, to be sure the file was found.
11Variable Names and the Header Line
The names you give the columns are the names you will use in every request.
Naming the Columns
In the variable names box, list the names in the same order as the columns, separated by commas. If the file has three columns for user name, password, and search word, you might name them username, password, and searchWord. The first value in each line goes into the first variable, the second into the second, and so on.
Using the File’s Own Header
If you leave the variable names box empty, JMeter treats the first line of the file as the list of names. This is convenient, because the names live together with the data. You do not then need to tick anything to skip that line; it is consumed as the header.
Typing Names and Skipping the Header
If the file has a header line but you also type the variable names in the box, the header would be read as a data row. To avoid this, turn on the option to ignore the first line. This option has an effect only when names are typed in.
| Names Box | File Has Header | Ignore First Line | Result |
|---|---|---|---|
| Empty | Yes | Not used | The header supplies the names. Correct. |
| Filled in | Yes | On | The header is skipped. Correct. |
| Filled in | Yes | Off | The header becomes the first data row. Usually a mistake. |
| Filled in | No | Off | All lines are data. Correct. |
| Empty | No | Not used | The first data row is mistaken for names. A mistake. |
Naming Habits
- Use letters, digits, and underscores, with no spaces.
- Choose names that describe the content, such as customerId rather than col2.
- Do not reuse a name already used by another element in the same plan, because one source may overwrite the other.
- Remember that names are case sensitive.
12Delimiters and Quoted Data
The separator decides where one value ends and the next begins. Get it wrong and the columns slide out of line.
The Delimiter
The default separator is a comma. You can choose another character, such as a semicolon, a vertical bar, or a tab. A tab is written in the box using a special marker for the tab character. Pick a character that never appears inside your values.
When Values Contain the Separator
Suppose a column holds addresses, and an address contains a comma, such as “12 Park Road, Springfield.” If the file uses commas as separators, that address looks like two values. The usual remedy is to wrap such a value in quotation marks. The setting Allow quoted data tells JMeter to treat text inside quotation marks as one value, even if it contains the separator.
Using Quoted Data
- Lets values contain commas and similar characters
- Matches the way spreadsheet programs save such files
- Keeps one column per value
Cautions
- Quotation marks inside values need careful handling
- Mismatched quotes can swallow several lines
- Turning it on for a file that does not use quotes is usually harmless but unnecessary
Alternative: Choose a Different Separator
Another way to avoid the problem is to pick a separator that does not appear in your data, such as a vertical bar. Then no quotation marks are needed, and the file is simpler to read and to edit.
After preparing a file with free text, such as addresses or comments, search it for the separator character inside values. A few minutes of checking prevents a long hunt for misaligned columns later.
13File Encoding and Hidden Characters
Some of the strangest data failures come from characters you cannot see.
What Encoding Means
Computers store text as numbers, and an encoding is the table that says which number stands for which character. If the file was saved with one encoding and read with another, letters such as accented vowels turn into strange symbols. The server then receives gibberish and may reject it or return different results.
What to Do
- Save data files as UTF-8, which handles almost every language.
- Set the file encoding box in the panel to match, when your data contains non-English characters.
- For plain English letters and digits, the default is usually fine.
Invisible Troublemakers
| Hidden Problem | Where It Comes From | Visible Effect |
|---|---|---|
| Extra spaces around values | Manual typing or copying from reports | Logins fail because “user001 ” is not “user001” |
| Special marker at the start of the file | Some programs add an invisible marker when saving | The first variable name or value looks right but does not match |
| Different line endings | Files moved between operating systems | Stray characters at the end of the last column |
| Blank lines | Extra returns at the end of the file | Empty values or early end of data |
| Smart quotes | Word processors replace plain quotes | Quoted data is not recognised |
How to Find Them
Run one user and open the request in the results viewer. Compare what was sent with what you meant to send. If a value looks right to the eye but the server refuses it, suspect an invisible character, and recreate the file with a plain text editor.
14When the Data Runs Out: Recycle and Stop Settings
Eventually, the pointer passes the last line. Two settings decide what happens next.
The Two Settings
- Recycle on EOF. When on, the pointer jumps back to the first data line and starts again. When off, the file is considered used up.
- Stop thread on EOF. When on, a user that asks for a row after the data is used up is ended. This setting matters only when recycling is off.
The Combinations
| Recycle | Stop Thread | What Happens at the End | Good For |
|---|---|---|---|
| On | Not used | Rows are reused from the top again and again | Reusable data such as search words |
| Off | On | Each user ends when no unused row remains | Data that may be used only once, such as one-time vouchers |
| Off | Off | Variables receive a special end-of-file marker value and the user carries on | Rare; mostly a mistake, because requests then carry the marker text |
The Marker Value Trap
With recycling off and stopping off, the variables are filled with a special marker, and the user continues. Every request then carries that marker, and the server rejects it. The report shows a sudden wave of failures at the point where the data ran out. If you see requests containing the marker text, you have run out of rows.
A raffle has a limited number of tickets. If tickets may be handed out again, people simply start over from the first ticket. If tickets are one-time only, then when the last ticket is gone, the person at the door is sent home. If neither is arranged, people keep arriving at the counter and receive a note saying “no tickets,” which they then wave at every other desk.
Recycling hides the problem of too little data. A test with a hundred rows and a thousand users will happily reuse rows. If your goal needs unique data, turn recycling off, and size your file properly.
15Sharing Modes: Who Shares the Row Pointer
The sharing mode decides whether users take turns on one pointer or each have their own.
The Choices
| Mode | Who Shares the Pointer | Effect |
|---|---|---|
| All threads | Every virtual user in the whole test | Rows are handed out in turn; no two users get the same row at the same time. This is the usual choice. |
| Current thread group | Only users in the same Thread Group | Each group works through the file separately, so the same row may be used by users in different groups |
| Current thread | No sharing; each user has its own pointer | Every user reads the file from the top, so every user sees the same sequence of rows |
| Identifier-based modes | All elements that share the same identifier text | Lets several elements share one pointer on purpose |
Choosing a Mode
- Unique data per user: use “All threads.”
- Two Thread Groups with their own data files: each file normally has its own config element, and “All threads” keeps each file’s pointer shared by all users of that file.
- Each user must replay the same list of items in order: use “Current thread.”
- Two elements that should step through the same file together: give them the same identifier.
Imagine a pile of exam papers on a table. In “All threads,” students take the top paper in turn, so everyone gets a different one. In “Current thread,” every student has their own photocopy of the whole pile, so everyone reads the same papers in the same order.
Mode names and the exact list differ a little between JMeter versions. Open the drop-down in your version and read the entries, then choose the one that matches your intention.
16Choosing the Right Settings
Three questions decide almost every configuration.
flowchart TD
Q["How should each row be used?"] --> A{"May a row be used more than once?"}
A -->|"Yes, reuse is harmless"| R["Recycle on EOF: on"]
A -->|"No, each row only once"| B{"What should a user do when rows run out?"}
B -->|"End that user"| ST["Recycle off, Stop thread on EOF: on"]
B -->|"Stop the whole test"| SZ["Recycle off, Stop thread on; size the file so it cannot run out unexpectedly"]
R --> C{"Must different users get different rows?"}
ST --> C
C -->|"Yes"| AT["Sharing mode: All threads"]
C -->|"No, each user replays the same list"| CT["Sharing mode: Current thread"]
AT --> D{"Several groups with separate files?"}
D -->|"Yes"| SEP["One config element per file"]
D -->|"No"| OK["One config element is enough"]
Reading the Diagram
First decide whether a row may be used more than once. If it may, switch recycling on. If it must not, switch recycling off and decide what a user should do when no rows remain. Then decide whether different users must receive different rows. If yes, use the sharing mode for all threads. If every user should replay the same list in the same order, use the current thread mode. Finally, if different Thread Groups have different files, give each file its own config element.
Common Configurations
| Data Kind | Recycle | Stop Thread | Sharing |
|---|---|---|---|
| Login accounts (unique per user) | Off, or on if reuse is safe after logout | On if off | All threads |
| Search words | On | Not used | All threads |
| One-time coupon codes | Off | On | All threads |
| A fixed browsing list replayed by each user | On | Not used | Current thread |
17Placement and Scope in the Test Plan
Where you put the element in the tree decides which samplers can see its variables.
The Scope Rule
A config element applies to samplers in its scope: the samplers beneath its parent. If you place it directly under a Thread Group, all samplers in that group can use its variables. If you place it under a single controller, only samplers inside that controller can. If you place it directly under the Test Plan, every Thread Group can use it.
Where to Put It
| Placement | Who Can Use the Variables | Typical Use |
|---|---|---|
| Under the Thread Group | All samplers in that group | The normal choice |
| Under the Test Plan | All groups | When several groups share one file |
| Under a Loop or other controller | Only samplers inside that controller | When a row should advance per inner loop |
| Under one sampler | That sampler only | Rare; a very specific need |
Placement and Row Advancement
The element advances the row at the start of each iteration of its parent. If it sits under the Thread Group, a new row is taken each time a user begins a Thread Group iteration. If it sits under a Loop Controller, a new row is taken for every pass of that inner loop. This lets you take a fresh row for each item in a shopping basket, while keeping one login row per user.
If a variable seems to keep its value when you expected a new row, check where the element sits. A config element under the Thread Group changes rows per Thread Group iteration, not per request.
18Using More Than One CSV File
Real journeys need several kinds of data at once. Several config elements can work side by side.
Why Use Several Files
- Different lifetimes. Accounts may be used once per user, while search words may be reused freely.
- Different shapes. A file of accounts has two columns, and a file of products has five.
- Different owners. Another team may supply the product list while you maintain the account list.
- Easier maintenance. Replacing one list does not require touching the others.
Rules for Several Elements
- Give each element a clear name, such as “Accounts” and “Products.”
- Use different variable names in each element, so one does not overwrite the other.
- Choose the recycle and sharing settings per file, according to how its data may be used.
- Remember that each element advances its own pointer, independently of the others.
An Important Consequence
Because each pointer moves independently, rows from different files are not paired. User three may receive the third account and the seventh product. If you need a particular account to be linked with a particular product, put both in the same file, as columns of one row.
| Need | Design |
|---|---|
| Each user has their own account, and any product may be searched | Two files, two elements |
| Each account has a specific address and order history | One file with all the columns |
| One list used by two Thread Groups in step | One file, one element with matching sharing mode and identifier |
19How Many Rows Do You Need?
Simple arithmetic prevents the most embarrassing data failure of all: running out in the middle of the test.
The Basic Rule
When each row may be used only once, the number of rows needed is the number of rows consumed in total. Each virtual user consumes one row per iteration. So:
Rows needed = number of users × iterations per user.
If you have two hundred users and each runs five iterations, you need one thousand rows. If the test runs for a fixed time instead of a fixed number of iterations, estimate how many iterations each user can complete: the test duration divided by the time one iteration takes, including think time.
An Example
| Quantity | Value |
|---|---|
| Virtual users | 200 |
| Test duration | 30 minutes, which is 1,800 seconds |
| Time for one iteration, including pauses | 45 seconds |
| Iterations per user | 1,800 divided by 45, which is 40 |
| Rows consumed in total | 200 × 40 = 8,000 |
| Safe file size with a 25 percent margin | 10,000 rows |
Why a Margin
If the system under test becomes faster than expected, users finish iterations sooner and consume more rows. If it is slower, they consume fewer. A margin protects against the first case. Real runs also often include extra rows consumed by warm-up runs and by rerun attempts.
When Reuse Is Fine
Data that is only read, such as search words, can be reused safely. A file of a few hundred varied words may serve a test of any length. But remember that very small lists cause repeated requests, which brings back the caching problem. Aim for enough variety that repeated requests are as rare as they would be in real life.
Do the sums before every major run, and again whenever you change users, duration, or think time. A test that was safe last month may run out of rows today.
20Login Data: One Account per User
Credentials are the first thing most tests parameterize, and the one most likely to cause trouble.
Why Unique Accounts Matter
Many applications limit simultaneous sessions for one account, log earlier sessions out, or lock an account after repeated activity. If all users share one account, the test measures a very unusual situation. Using a separate account for each virtual user matches what happens in production, where many people are logged in at once, each with their own identity.
Preparing the Accounts
- Create them in advance. The accounts must exist in the test system before the test starts, with passwords that work.
- Create enough of them. Use the arithmetic from the previous chapter, with a margin.
- Give them realistic state. An account with no history behaves differently from an account with a year of orders. Where behaviour depends on history, prepare data to match.
- Use test-only accounts. Never use real customers’ accounts or passwords.
- Reset between runs. If a run changes an account, such as emptying its credit balance, restore it before the next run.
The Logout Question
If each virtual user logs in on every iteration and the application allows only one session per account, a user who loops must log out before the next iteration, or use a different account. Otherwise the second login may fail or kick out the first one. Decide whether your journey includes a logout step and whether recycling is safe for the accounts.
An account locked by repeated wrong passwords stays locked in the next run. A first run with a mistyped password column can spoil an entire account list. Verify a handful of accounts by hand before a large test.
If every guest at a hotel were handed the same room key, the first guest would be thrown out by the second. A realistic test hands each guest their own room key.
21Search Words, Products, and Realistic Variety
Choosing the values is as important as choosing the file format. The distribution of requests should resemble real traffic.
Real Traffic Is Uneven
In real life, a few items are very popular and most are rarely viewed. A news site has a handful of headline stories and thousands of old articles. A shop has bestsellers and slow movers. If your test picks every item with equal probability, it is more even than reality. If it always picks the same few, it is more skewed than reality.
Making the Mix Realistic
- Use real data patterns. If you have access to anonymised logs or analytics, build the list from them, so popular items appear more often.
- Repeat popular values. A simple way to weight a list is to include popular values several times in the file.
- Include rare values too. Slow-moving items test the less common paths, such as cache misses and cold database pages.
- Include failure cases deliberately. A few searches with no results, or a few mistyped words, are normal in real life.
- Keep the list long enough. A tiny list leads to repeated requests and unrealistic caching.
The Caching Effect
| List Design | Likely Effect on Results |
|---|---|
| Five search words, recycled | Almost every request is served from cache, so results look too fast |
| Every search word is unique and never repeated | Almost no cache hits, so results may look too slow |
| A weighted list with realistic repeats | A cache hit rate close to what production sees |
Ask the people who run the system what its real cache hit rate is. Then design the data so your test’s rate is in the same area, instead of far above or below it.
22Data for Forms, Orders, and Messages
When a test creates data, the values you feed it often must be unique, valid, and well shaped.
Typical Cases
| Case | Data Needed | Watch For |
|---|---|---|
| Registration forms | Unique emails or user names | Duplicates cause rejections after the first run |
| Order creation | Product identifiers, quantities, addresses | Products out of stock, invalid combinations |
| Payment steps | Test payment details supplied by the payment provider for testing | Never use real card details |
| Data messages sent to interfaces | Fields for each message | Dates in the right format, numbers in the right range |
| File uploads | File names or paths | Files must exist on every load generator |
Uniqueness Across Runs
If the first run registers the user “newuser001,” the second run cannot register it again. You have two choices: clean the test system between runs, or generate fresh values each time. For fresh values, you can build the file with a number or date stamp inside each value, or use built-in functions that produce unique values at run time.
Validity
Data that the application rejects as invalid wastes the test, because the system spends its time producing error messages rather than doing normal work. Check the rules for each field, such as length, characters allowed, and ranges, and prepare the file to follow them. Include a small share of invalid data only if you want to test error handling on purpose.
Never put real personal data or real payment details into test files. Use fake names, addresses, and the special test payment details that payment providers publish for testing.
23Data That Is Used Up or Changed by the Test
Some data is consumed by use. A test that forgets this works once and fails on the second run.
Kinds of Data That Change
- One-time codes. Vouchers and invitation codes that work only once.
- Stock levels. Items that sell out, so later orders fail.
- Balances. Accounts that run out of credit.
- Records that move through stages. An order that was paid cannot be paid again.
- Unique fields. Names and emails that cannot be created twice.
Strategies
Reset the Environment
Restore a known data snapshot before each run, so every run starts from the same state.
Generate Fresh Data for Each Run
Create a new file with new codes and names before every run, using a small script.
Make the Test Undo Its Changes
Include steps that cancel an order or delete a record at the end of a journey, where the business allows it.
Use Generous Stock and Balances
Prepare test products and accounts with so much stock and credit that they cannot run out during the test.
Record What You Used
Keep a copy of the exact data file used in each important run, stored with the results. When something looks odd later, you can see precisely which rows were used.
24Combining CSV Data With Values Caught From Responses
Real journeys mix two kinds of data: what you prepared, and what the server invents along the way.
Two Sources, One Request
A login request may need your prepared user name and password from the CSV file, and also a hidden security code that the server placed in the login page. The first comes from the CSV Data Set Config. The second must be caught from the earlier response by an extractor, which is a kind of Post-Processor. The final request uses both kinds of variables, written the same way inside a dollar sign and curly braces.
| Value | Source | Tool |
|---|---|---|
| User name and password | Prepared by you | CSV Data Set Config |
| Hidden security code | Created by the server for this visit | An extractor on the login page |
| Session ticket after login | Created by the server on login | An extractor on the login answer |
| Search word | Prepared by you | CSV Data Set Config |
| Product identifier from search results | Created by the server from the search | An extractor with a random match |
Name Clashes
Both tools write into the same pool of variables. If an extractor and a CSV column use the same name, the later writer replaces the earlier value. Use clearly different names, such as a prefix for CSV variables, so you always know where a value came from.
Using CSV Values in Checks
You can also use CSV variables inside assertions. For example, after login the page should greet the user by name, and the expected phrase can be built from the user name variable. Each user then checks for their own name, which proves that the right account was really logged in.
When a request fails, ask first: “Was this value prepared by me or invented by the server?” The answer tells you whether to look at the CSV file or at an extractor.
25Other Ways to Feed Data Into JMeter
The CSV Data Set Config is the most common choice, but not the only one. Knowing the alternatives helps you pick wisely.
| Method | How It Works | Best For | Limits |
|---|---|---|---|
| CSV Data Set Config | Reads rows from a text file, one per iteration | Lists of accounts, words, and records | Needs file preparation and distribution |
| User Defined Variables | Fixed variables typed into the plan | Settings that are the same for all users | Does not vary per user |
| Counter | Produces an increasing number | Unique sequence numbers | Numbers only |
| Random variable element | Produces random numbers in a range | Random quantities or choices | Not tied to real records |
| Built-in functions | Generate values at the moment of use, such as random strings, times, and unique identifiers | Unique emails, time stamps | Not for fixed, valid records |
| Older file functions | Read lines from a file inside a placeholder | Quick one-off needs and old plans | Less flexible and less recommended than the config element |
| Database queries | Fetch rows from a database before or during the test | Data that already lives in a database | Adds load and complexity to the test machine |
| Plugin-based random data readers | Read a file in random order | Random picking from a list | Needs an extra plugin installed |
Choosing Between Them
- For prepared, valid records, use the CSV Data Set Config.
- For values that only need to be unique, use a counter or a function and avoid a file altogether.
- For random picking from a list, use a plugin that reads randomly, or shuffle the file once before the test.
- For data that already lives in a system you can query, consider exporting it to a file first. A file is simple, fast, and independent of other systems during the test.
The CSV Data Set Config reads rows in file order. If you need random order, shuffle the rows when you build the file, instead of asking JMeter to pick randomly.
26Generating Test Data Files
For a few users, you can type the file by hand. For thousands, you need a method.
Ways to Build a File
- A spreadsheet program. Fill a column with a series, and combine columns with formulas. Save the result as plain CSV text.
- A small script. A short program written in any language can produce thousands of lines with patterned values such as numbered accounts.
- A database export. If the accounts or products already exist, export the needed columns directly.
- Test data tools. Some tools generate realistic fake names, addresses, and numbers.
- Production-like copies, anonymised. Data derived from real patterns, with personal details removed or changed.
Keeping Data and System in Step
A file of accounts is useful only if the system really has those accounts. The best method is to create the accounts and the file together from the same source, such as one script that registers the accounts in the test system and writes the matching file. Then the two cannot drift apart.
Checks Before Using a File
| Check | Why |
|---|---|
| Count the lines | Make sure there are enough rows |
| Count the columns on every line | A short line leaves variables empty or stale |
| Look for duplicates | Duplicate accounts defeat uniqueness |
| Look for stray spaces and blank lines | They cause hidden failures |
| Try a few rows by hand | Confirms the data is valid in the real system |
27Large Files and Performance
The element is efficient, but very large files and very busy tests deserve a little care.
Reading Cost
The element reads the file line by line, so even large files do not fill the machine’s memory. The cost per row is small. For most tests, the CSV Data Set Config is not a performance concern at all.
Where Care Is Needed
- Extremely large files. Files with millions of lines take disk space and time to move between machines. Split them if you can.
- Many elements. Dozens of elements, each reading separate files, add some overhead.
- Slow storage. A data file on a slow network drive can delay users. Keep files on the local disk of the load generator.
- Very wide rows. Rows with hundreds of columns create hundreds of variables for each user.
- Large values. Columns that hold big bodies of text enlarge the memory used by each user.
Practical Advice
Keep Rows Lean
Include only the columns the test uses.
Keep Files Local
Copy files to the local disk of each load generator before the test.
Split by Worker
In distributed tests, give each worker its own slice of the data.
Compress for Transfer
Transfer large files in compressed form, and unpack them before the run.
If you suspect the data reading is slow, compare a run with a small file against a run with the full file. If the numbers are the same, the file is not the cause.
28Keeping Data Files Under Control
A data file is part of your test. Treat it with the same care as the plan.
Versioning
Store the test plan and small data files together in version control, so changes are tracked and anyone can recover an earlier version. For very large files, store the script or recipe that creates them, and keep the generated file outside version control, with a clear note about how to rebuild it.
Naming and Documentation
- Give files descriptive names, such as accounts for the checkout test, not just data1.
- Add a short note beside each file: its purpose, its columns, how it was generated, and its limits, such as a count of rows.
- Record the date and the system version it was built for.
Staleness
Data goes stale. Accounts get deleted, products are withdrawn, and rules for valid values change. A file that worked last quarter may produce a wave of failures today. Check data files whenever the system changes, and run a one-user smoke test before every important run.
Ownership
Decide who owns each file. When nobody owns it, nobody updates it, and the test slowly rots. A named owner and a refresh schedule keep data healthy.
Never commit real credentials to a shared repository. Test accounts should be harmless if the file is ever seen by someone it was not meant for.
29Small Pitfalls With Big Effects
A short collection of everyday problems that waste hours.
| Pitfall | What You Notice | Cure |
|---|---|---|
| Blank line at the end of the file | An empty row, or users stopping early | Remove trailing blank lines |
| Empty value in the middle of a row | A request is sent with a blank field | Fill every column, or design requests that tolerate blanks |
| Fewer columns than variable names | The extra variables keep an earlier row’s value or are unset | Make every line the same length |
| Comma inside a value without quoting | Columns shift to the right | Use quoted data or another delimiter |
| Spreadsheet changed a value | Leading zeros dropped, long numbers turned into scientific notation, dates reformatted | Format the columns as text before saving |
| Header treated as data | First user logs in as a name like “username” | Use the ignore-first-line option, or leave the names box empty |
| Wrong file opened | Plan runs with an old list | Check the path and the log |
| Tab character confusion | Everything lands in one column | Set the delimiter to the tab marker |
The Spreadsheet Trap
Spreadsheet programs try to be helpful. They may remove leading zeros from numbers such as a postal code, turn a long account number into a number with an exponent, or change a date into another format. The text in the cell looks right on screen, but the saved file holds something different. Always check the saved file in a plain text editor.
An error caused by the data file often looks like a server problem. When a request fails for some users but not others, compare the failing rows with the successful ones before blaming the server.
30CSV Data With Loops and Controllers
Loops decide how often rows are taken. Understanding this prevents unexpected shortages and repeats.
Loops at the Thread Group
If a Thread Group has two hundred users and each runs five loops, the CSV element, placed under the group, hands out one row per loop, so a thousand rows are consumed. If the loop count is set to run forever, with the test stopped by a duration, the number of rows consumed depends on how fast the system answers, which is why you must estimate with care.
Loop Controllers Inside a Journey
A Loop Controller repeats a set of steps inside one iteration, for example adding five items to a basket. If the CSV element sits under the Thread Group, all five passes of the inner loop use the same row. If the element sits under the Loop Controller, each inner pass takes a fresh row, giving five different products.
| Goal | Where to Place the Element | Effect |
|---|---|---|
| One account for the whole journey | Under the Thread Group | One row per outer iteration |
| A different product for each pass of an inner loop | Under the Loop Controller | One row per inner pass |
| Both of the above | Two elements: one at each level, with different files and variable names | Accounts per outer iteration and products per inner pass |
Other Controllers
An If Controller that skips a part of the journey also skips any CSV element inside it, so no row is consumed for that pass. A Once Only Controller runs its contents just on the first iteration of each user, which suits a login that happens once. A Transaction Controller groups steps for measuring and does not change how rows advance.
After setting up loops, run one user for three iterations and watch the requests. You should see the row change exactly where you expect it to change, and nowhere else.
31Ramp-Up, Duration, and the Pace of Row Use
The speed at which a test consumes data depends on how it is shaped in time.
Ramp-Up
Ramp-up is the period during which users are started gradually. During ramp-up, row consumption starts slowly and grows as more users join. Total rows consumed over the full test still follow the arithmetic of users and iterations, but a long ramp-up means early users run more iterations than late ones.
Fixed Duration Tests
When a test runs for a set time, users repeat their loops until the time is up. Faster responses mean more iterations, and more iterations mean more rows. A system that performs better than expected could therefore consume rows faster than planned and run the file dry. Keep a margin.
Think Time
Pauses between steps slow each user down and reduce row consumption. If you shorten pauses to push more load, remember that you also use data faster. Recalculate the rows needed after any change to pauses.
Effects on Throughput and Data
| Change | Effect on Row Consumption |
|---|---|
| More users | Faster consumption, in proportion |
| Longer test | More rows needed, in proportion |
| Shorter think time | Faster consumption |
| Slower system | Slower consumption, because each iteration takes longer |
| Journey with more requests per iteration | Slower consumption, but rows are used per iteration, not per request |
A test that was fine at a small scale can fail suddenly when scaled up, because the file now runs out halfway through. Always scale the data with the load.
32CSV Data in Distributed Testing
When several machines generate load, data needs special care. Each machine reads its own copy of the file.
The Core Problem
In a distributed test, every worker machine runs the plan with its own virtual users, and every worker has its own row pointer. If all workers read the same file from the top, then worker one’s first user and worker two’s first user both take row one. Two users share one account at the same time, which is just the clash you wanted to avoid.
The Solution: Split the Data
Divide the Rows
Split the master list into slices, one for each worker, with no overlapping rows.
Give Each Slice the Same File Name
Place each slice on its worker at the path named in the plan, so the same plan works everywhere.
Check the Sizes
Make sure each slice holds enough rows for the users and iterations of that worker.
Test the Setup
Run a short test and confirm that no two workers use the same row at the same time.
Other Points
- Users multiply. Fifty users in the plan on four workers means two hundred users, which need two hundred rows per iteration.
- The same plan, different data. The plan is identical, and only the data slices differ.
- The file must exist. A missing file on one worker leaves its users without data.
- Keep a map. Record which slice went to which worker, so you can trace a failure to the right row.
Where overlap is harmless, such as reusable search words, every worker can read the same full file. Splitting matters only for data that must be unique across all users.
33Monitoring, Logging, and Tracing Failures to a Data Row
When one user fails and another succeeds, the first question is: which row did each one use?
Why Tracing Matters
Many failures depend on the data. An account with a wrong password, a product that is out of stock, a record in a strange state. If your results do not show which row a user used, you cannot connect a failure to its data, and you will spend hours guessing.
Ways to Trace
- Put an identifier in the request. Where the application allows it, include the user name or a row number in a harmless field, such as a custom header or a label.
- Include the key value in sample labels or messages. Failure messages that mention the account name make reports easier to read.
- Save request details for failures only. Configure result files to save the request data when a sample fails, so you can see which values were sent.
- Use the debugging listener on small runs. The View Results Tree shows each request, including the values used.
- Log row numbers sparingly. A small log line when something unusual happens is helpful. A line per request fills the disk.
Watching for Data Problems in Results
| Pattern in the Results | Likely Data Cause |
|---|---|
| Failures start at a specific time and affect everyone afterwards | The file ran out, or rows after a certain point are bad |
| Failures affect only some users, always the same ones | Particular rows are invalid, such as wrong passwords |
| Requests contain placeholder text or an end-of-file marker | A variable was not found, or the data ran out |
| Failures on one worker only | That worker’s slice is missing, stale, or overlapping |
| Very fast response times with many identical requests | Recycling of a short list is causing cache hits |
A delivery company that finds many parcels returned will want to know which addresses they were for. If the records only say “some parcels failed,” nothing can be fixed. Tracing a failure to its data row is like keeping the address on every parcel.
34Security and Privacy
Data files often hold credentials and personal details. Handle them with care, even in a test environment.
What Can Go Wrong
- Real personal data in files. Copying production customer records into test files exposes people’s privacy and may break the law.
- Passwords stored in plain text. Data files are plain text and anyone with access can read every password.
- Files in shared repositories. A file committed to a shared repository may be copied or seen by many people.
- Result files that repeat the data. Saved request details copy usernames and passwords into result files and dashboards.
- Leftover files. Old data files forgotten on shared machines.
Good Habits
- Use synthetic test data. Invent names, addresses, and numbers.
- If production-like data is needed, anonymise it thoroughly before it reaches the test environment.
- Use test-only accounts with limited permissions and short-lived passwords.
- Keep data files in access-controlled storage, not in public or widely shared folders.
- Do not save passwords in result files. Review which fields are saved.
- Delete data files and results when the project no longer needs them.
- Use the payment provider’s published test card details, and never real cards.
- Test only systems you own or have written permission to test.
The passwords in a test file may be reused by people elsewhere out of habit. Make test passwords unique to the test system, never copies of any real person’s password.
35Advantages, Disadvantages, and Trade-Offs
The CSV approach is simple and popular, and it has limits you should know.
Advantages
- Simple to understand and to set up
- Data is separate from the plan, so each can change independently
- Spreadsheet programs and scripts can create the files
- Reads line by line, so large files are fine
- Each user receives different data
- Flexible settings for end of file and sharing
- Works in distributed tests with split files
Disadvantages
- The data must be prepared and kept in step with the system
- Rows are handed out in file order, not randomly
- Files must be copied to every worker in distributed tests
- Running out of data can cause confusing failures
- Plain text files hold credentials in the open
- Spreadsheet programs can silently alter values
Key Trade-Offs
| Choice | One Side | The Other Side |
|---|---|---|
| Recycling on or off | On: never runs out, but repeats rows | Off: unique data, but needs enough rows |
| One file or several | One: rows are paired exactly | Several: easy to maintain separately but not paired |
| Realistic data or simple data | Realistic: results closer to production, more work to build | Simple: quick, but may mislead |
| CSV file or generated values | File: valid known records | Generated: no preparation, but not tied to real records |
A sensible middle path is to use a CSV file for records that must exist in the system, such as accounts, and functions for values that only need to be unique, such as time stamps.
36Design Patterns and Anti-Patterns
Experienced testers keep returning to a handful of good habits and a handful of repeated mistakes.
Good Patterns
Data Beside the Plan
Keep data files next to the plan and use relative paths.
Sized With a Margin
Calculate rows needed and add a safety margin.
Generated, Not Hand-Typed
Build files with a script that also creates the matching accounts in the system.
One File per Purpose
Separate files for accounts, products, and search words, each with fitting settings.
Smoke Test First
Run one user for a few iterations before every big run, to confirm the data works.
Trace to the Row
Make failures show which data was used.
Anti-Patterns
What Happens
All users log in as one test account.
Why It Hurts
Sessions clash, locks form, and results do not look like real traffic.
Better Approach
Prepare one account per virtual user, with a margin.
What Happens
A file of ten rows serves a thousand users with recycling on.
Why It Hurts
Rows repeat constantly, caches are very hot, and the test hides the true cost of real requests.
Better Approach
Size the data to the real variety, and turn recycling off where uniqueness matters.
What Happens
The plan names a path that exists only on the author’s laptop.
Why It Hurts
The plan fails on any other machine, including the load generators.
Better Approach
Use relative paths or a property that carries the folder.
What Happens
All workers read the same full list of unique accounts.
Why It Hurts
Different workers use the same account at the same time.
Better Approach
Give each worker its own non-overlapping slice.
What Happens
A copy of production records is used as test data.
Why It Hurts
It exposes real people’s information and creates legal and trust problems.
Better Approach
Use synthetic or properly anonymised data.
37Best Practices and Common Mistakes
A short list that separates calm, reliable data-driven tests from endless surprises.
Best Practices
- Plan your data first. Decide which values vary, how many rows you need, and how they will be created.
- Use unique accounts per user and keep a margin of spare accounts.
- Choose realistic variety, including popular and rare values.
- Check every file for column counts, blank lines, stray spaces, and encoding.
- Set end-of-file behaviour on purpose, not by default.
- Use relative paths and keep data beside the plan.
- Split data for distributed runs where uniqueness matters.
- Run a one-user smoke test before every important run.
- Keep data synthetic and files protected.
- Document each file and name an owner.
Common Mistakes
| Mistake | Consequence | Fix |
|---|---|---|
| Variable name spelled differently in the request | The placeholder text is sent | Copy the exact name from the config element |
| Header line read as data | First user uses column titles as a login | Ignore the first line, or leave names empty |
| File missing on a worker | Users on that worker have no data | Distribute files and check the log |
| Too few rows | Data runs out mid-test | Do the arithmetic with a margin |
| Recycling on for single-use data | Repeated use of a used-up code | Turn recycling off and stop users at the end |
| Config element in the wrong place | Rows change too often or too rarely | Place it at the level whose iteration should advance the row |
| Changed values from a spreadsheet | Leading zeros lost, odd formats | Save as text and check in a plain editor |
| Passwords saved in result files | Credentials leak | Restrict the saved fields |
38Real-World Examples
These are teaching illustrations of common situations. They are not descriptions of any particular company’s setup.
An Online Shop Before a Sale
A shop prepares five thousand test accounts and a weighted product list, in which bestsellers appear more often. Each virtual shopper logs in with their own account and searches for products from the list. Because the mix of popular and rare items matches real behaviour, the cache hit rate in the test resembles production, and the results can be trusted.
A Staff Portal With Single Sessions
An internal portal allows only one session per account. The team creates as many accounts as the highest planned user count, turns recycling off, and stops users at the end of the data. No account is used twice at the same moment, so no sessions are knocked out.
A Voucher Campaign
A marketing campaign gives out one-time vouchers. The test uses a file of thousands of voucher codes, with recycling off, so every user redeems a different code. A script generates a fresh set of codes before each run, because codes cannot be reused.
A Registration Interface
An interface that creates new members needs unique email addresses. Instead of a file, the team uses a built-in function that produces a unique identifier at the moment of use. A CSV file still supplies the realistic names and cities, which do not need to be unique.
A Multi-Region Distributed Test
Four load generators in different regions each receive a separate slice of an account list of forty thousand rows, ten thousand each. Every region uses its own slice, and no account is shared between regions, so traffic patterns look like real visitors from different areas.
39Step-by-Step: Parameterizing a Recorded Journey
A repeatable recipe that works for almost any recorded journey.
Find the Fixed Values That Should Vary
Review the recorded requests and list the values that real visitors would change: accounts, search words, products, quantities.
Decide Reuse Rules
For each list, decide whether rows may be reused and whether users must have different rows.
Build the Files
Create the files with a script or spreadsheet. Check columns, blank lines, and encoding.
Make Sure the System Has the Data
Create the accounts and products in the test environment so the file matches reality.
Add the Config Elements
Add one CSV Data Set Config per file, with clear names, relative paths, and the right end-of-file and sharing settings.
Replace Fixed Values With Placeholders
In each request, write the variable names in place of the recorded values.
Add Assertions That Use the Data
Check that each user’s own name appears after login, proving that the right account was used.
Smoke Test With a Few Users
Run three users for a few iterations and confirm that each request carries the expected values.
Do the Row Arithmetic
Calculate the rows needed for the real run, with a margin, and extend the files if necessary.
Distribute and Run
For distributed tests, split and copy the files first. Then scale up the load gradually.
40A Worked Example: Sizing and Settings for a Shop Test
Let us plan the data for a small shop test, using invented numbers to teach the method.
The Scenario
A shop wants to test its busiest hour. The plan has three hundred virtual users. Each user logs in, searches for a product, views it, and adds it to the basket. One iteration takes about sixty seconds including pauses. The test will run for forty minutes.
Step 1: Work Out Iterations and Rows
| Quantity | Calculation | Result |
|---|---|---|
| Duration in seconds | 40 × 60 | 2,400 |
| Iterations per user | 2,400 ÷ 60 | 40 |
| Total iterations | 300 × 40 | 12,000 |
| Account rows needed if each iteration needs a fresh login row | 12,000 plus a 25 percent margin | 15,000 |
| Account rows needed if each user keeps one account all test long | 300 plus a 25 percent margin | 375 |
The second line shows a very different need. A test where each user logs in once and then loops through searches needs only a few hundred accounts. A test where every iteration is a fresh login by a new account needs fifteen thousand. The journey design decides the data need.
Step 2: Choose the Files and Settings
| File | Columns | Rows | Recycle | Stop Thread | Sharing |
|---|---|---|---|---|---|
| Accounts | username, password | 375 | Off | On | All threads |
| Search words | searchWord | 2,000, popular words repeated | On | Not used | All threads |
Step 3: Place the Elements
The accounts element goes under a Once Only Controller that holds the login, so each user takes one account row at the start. The search words element goes under the Thread Group, so each iteration takes a new search word. Login and search use different variable names, so they never overwrite each other.
Step 4: Check the Result
A smoke test with three users for three iterations shows three different accounts on login and a new search word on each iteration. The log shows no file errors. The team then runs the full test with a gradual ramp-up, confident that data will not run out.
The same scenario needs 375 rows or 15,000 rows depending on one design decision: log in once per user, or log in every iteration. Always decide how a journey uses data before you build the files.
41Troubleshooting Data Problems
When data does not behave, a fixed path of questions finds the cause fast.
flowchart TD
S["A request carries a wrong or missing value"] --> A{"Does the request show the placeholder text itself?"}
A -->|"Yes"| N["Check variable name spelling and case, the names list, and element scope"]
A -->|"No"| B{"Does it show an end-of-file marker?"}
B -->|"Yes"| E["Data ran out: add rows, turn on recycling, or stop users at the end"]
B -->|"No"| C{"Is the value empty or shifted to the wrong column?"}
C -->|"Yes"| D["Check delimiter, quoted data, blank lines, and column counts"]
C -->|"No"| F{"Is the value the same for all users?"}
F -->|"Yes"| G["Check sharing mode, element placement, and whether the variable is overwritten elsewhere"]
F -->|"No"| H["Check the row itself: is it valid in the system, and is it duplicated?"]
Reading the Diagram
Start with what the failing request actually carried. If you see the placeholder text, the variable was not found. If you see the end-of-file marker, the rows ran out. If the value is empty or in the wrong column, the file’s structure is wrong. If every user has the same value, the sharing mode or the placement of the element is the problem. If everything looks fine but the system rejects the value, the row itself is invalid.
Common Symptoms and Causes
| Symptom | Likely Cause | What To Do |
|---|---|---|
| File not found message in the log | Wrong path, or the file is missing on this machine | Use a relative path and check every machine |
| First user logs in with column titles | Header read as data | Ignore the first line, or leave names empty |
| Everyone uses the same row | Sharing mode is per thread, or the file has one line | Use all threads and check the line count |
| Failures after some time | Data ran out | Recalculate the rows needed |
| Some users fail, always the same accounts | Bad passwords or locked accounts | Verify those rows by hand |
| Odd symbols in requests | Encoding mismatch | Save as UTF-8 and set the file encoding |
| Columns shifted | Delimiter inside values | Quote values or change the delimiter |
| Different results between workers | Different data slices or versions | Compare the files on each worker |
42Terms People Often Confuse
Several pairs of ideas look alike and behave differently. Knowing the difference saves hours.
Parameterization vs Correlation
Parameterization feeds the test with data you prepared. Correlation catches values the server invents during the test.
Iteration vs Request
An iteration is one pass through the whole journey. A request is a single step within it. Rows advance per iteration, not per request.
Variable vs Property
A variable belongs to one virtual user. A property is global, shared by everyone, and set at start-up.
Recycle vs Stop Thread
Recycle restarts the file from the top. Stop thread ends a user when data is exhausted and applies only when recycling is off.
All Threads vs Current Thread
All threads share one pointer, so users get different rows. Current thread gives every user a pointer of their own, so each reads the same sequence.
Header Names vs Typed Names
Names can come from the file’s first line or from the names box. Typing names means the header must be skipped.
CSV File vs Generated Values
A file holds prepared real records. A function creates values at the moment of use, without any record behind them.
Thread Group Loop vs Loop Controller
The first repeats the whole journey. The second repeats only part of it, and can advance the rows of an element beneath it.
When two terms sound alike, test both on a tiny example with a three-line file and three users. A few minutes of experimenting beats an hour of guessing.
43A Case Study: The Test That Ran Out of Accounts
This is a composed story built to teach. It is an illustration, not an account of a real team.
The Situation
A team tested a members’ website with five hundred virtual users and a file of five hundred accounts. In the first week, the test ran well. The team then lengthened the test from ten minutes to an hour, to look for slow leaks. Each user now logged in on every iteration, and users ran about forty iterations each.
The Surprise
Twelve minutes into the new test, the error rate shot up from nearly zero to more than ninety percent, and it stayed there. The server’s graphs looked healthy. The team feared a sudden failure in the application and stopped the test.
The Investigation
Read a Failed Request
They opened the saved failure details. The login requests carried the end-of-file marker text instead of an account name.
Check the Settings
Recycling was off and stopping was off, which fills the variables with the marker when the data is used up and lets users continue.
Do the Arithmetic
Five hundred users each taking one row per iteration used all five hundred rows in the first iteration of each user. With forty iterations per user, they would have needed twenty thousand rows.
Redesign the Journey
They moved the login under a controller that runs once per user, so each user logs in once and then loops through the other steps. Five hundred accounts now were enough.
Set Safer Behaviour
They also turned stopping on at the end of the data, so a shortage ends users clearly instead of flooding the server with invalid logins.
The Lesson
The application had not failed. The data had run out, and the test sent nonsense to a healthy server. Two habits would have prevented the confusion: calculating the rows needed before the run, and setting end-of-file behaviour deliberately.
44CSV Data in Automated Pipelines
When tests run on their own after each change, data must be ready and correct without a person watching.
Why Pipelines Raise the Stakes
In a pipeline, nobody checks the first minutes of a run. If the data file is missing, stale, or too small, the test may fail in a confusing way, or worse, pass without exercising anything important. Data preparation must be part of the pipeline itself.
Practices for Pipelines
- Prepare data as a pipeline step. A step before the test creates or refreshes accounts and writes the data file.
- Pass paths as properties. The folder with data files is given at start-up, so the same plan works on any build machine.
- Check the data before the run. A short step counts the rows and columns and fails the build if there are not enough.
- Fail loudly when data runs out. Turn stopping on, and add checks that flag requests carrying the end-of-file marker.
- Reset the environment. Restore data to a known state, so a rerun starts from the same place.
- Keep the files with the results. Store the exact data used with the saved results, for later investigation.
- Run a quick smoke test first. One user for a few iterations will reveal most data problems in seconds.
A bakery that opens at dawn must prepare its dough the night before. If nobody checks that the flour is in the kitchen, the first customers arrive at an empty counter. Preparing and checking data in the pipeline is the night-before preparation.
45Quick Reference
A one-page reminder for the next time you are in a hurry.
| Setting | Meaning | Remember |
|---|---|---|
| Filename | Where the file is | Prefer relative paths; the file must exist on every worker |
| File encoding | How characters are read | UTF-8 for special characters |
| Variable names | Column names, in order | Case sensitive; must match requests |
| Ignore first line | Skip the header | Needed only when names are typed in |
| Delimiter | Separator between values | Default is a comma |
| Allow quoted data | Values in quotes may hold separators | Turn on only if needed |
| Recycle on EOF | Restart after the last line | Hides a shortage of data |
| Stop thread on EOF | End the user when data runs out | Works only when recycling is off |
| Sharing mode | Who shares the pointer | All threads gives each user a different row |
46Glossary of Terms
Plain-language meanings of the words used in this guide.
| Term | Meaning |
|---|---|
| Parameterization | Replacing fixed values in a test with values that change for each user or pass. |
| CSV | Comma-separated values: a plain text file with one record per line. |
| CSV Data Set Config | The JMeter element that reads a CSV file and hands out rows. |
| Config element | An element that supplies settings or data to samplers in its scope. |
| Virtual user | A thread that behaves like one visitor. |
| Iteration | One pass of a virtual user through the steps of the test. |
| Variable | A named container for a value belonging to one virtual user. |
| Property | A global setting shared across the whole JMeter run. |
| Placeholder | A variable name written in a request, replaced by its value when sent. |
| Row pointer | The marker that shows which line will be handed out next. |
| EOF | End of file: the point after the last line. |
| Recycle | Starting again from the first line after the last. |
| Delimiter | The character that separates values within a line. |
| Quoted data | Values wrapped in quotation marks, so they may contain delimiters. |
| Encoding | The table that maps characters to stored numbers. |
| Sharing mode | The setting that decides who shares a row pointer. |
| Scope | The set of samplers an element applies to, decided by its place in the tree. |
| Correlation | Catching a dynamic value from one response and using it in a later request. |
| Ramp-up | The period in which users are started gradually. |
| Think time | The pause that imitates a person reading or deciding. |
| Load generator | The machine that runs JMeter and creates the load. |
| Worker | A machine in a distributed test that runs the plan under a controller. |
| Cache | Fast memory where a system keeps answers it may need again. |
| Synthetic data | Invented data that does not describe real people. |
47A Checklist Before Every Important Run
Pilots read a checklist before every flight, however experienced they are. A short list protects a test run in the same way.
Before You Press Start
- The values that should vary have been identified and replaced by placeholders.
- Row arithmetic is done for users, iterations, and think time, with a margin.
- Every file was checked for column counts, blank lines, spaces, duplicates, and encoding.
- The data exists in the system. A few rows were tried by hand.
- End-of-file behaviour was chosen on purpose, not left by default.
- Sharing mode and element placement match the intention.
- Paths are relative or come from a property, and files exist on every worker.
- Data is split per worker where uniqueness matters.
- A one-user smoke test passed, and the log shows no file errors.
- Data is synthetic and files are protected. The target is permitted for testing.
After the Run
- Search the results for the end-of-file marker and for placeholder text.
- Look for failures that cluster around particular accounts or rows.
- Save the exact data files together with the results.
- Reset or refresh the data for the next run, and note what changed.
Paste this checklist into your team’s notes and tick it for each important run. A habit that takes two minutes can save a day of chasing failures caused by one missing file.
48Frequently Asked Questions
At the start of each iteration of the element’s parent. All requests in that iteration use the same row. The next iteration takes the next row.
The sharing mode may be set to current thread, so every user reads the file from the top. Also check that the file has more than one line and that no other element overwrites the variable.
It depends on two settings. With recycling on, the file restarts. With recycling off and stopping on, the user ends. With both off, variables receive an end-of-file marker and the user continues, which usually causes failures.
Only if the file has a header and you type the variable names in the box. If you leave the names box empty, the header is used as the names automatically.
No. Each worker opens the file itself, so the file must exist on every worker at the path named in the plan.
The standard element reads rows in order. For random order, shuffle the file when you build it, or use a plugin that reads randomly.
For single-use data, users multiplied by iterations per user, plus a margin. For reusable data, enough variety to avoid unrealistic repetition.
JMeter could not find a variable of that name. Check spelling and case, the names list in the element, and whether the element is in scope of the request.
Yes. Use one element per file with different variable names. Each element advances its own pointer, so rows from different files are not paired.
The file encoding probably does not match. Save the file as UTF-8 and set the file encoding in the element accordingly.
Only for test-only accounts with harmless, test-specific passwords, kept in protected storage. Never use real people’s passwords or real customer data.
Include an identifier such as the user name in a harmless field or in failure messages, and save request details for failures. Then the failing data is visible in the results.
49Summary and Key Takeaways
CSV parameterization gives each virtual user their own identity and errands, so a load test looks like a real crowd instead of one person copied many times.
- The CSV Data Set Config reads a text file line by line and hands one new row to each user at the start of each iteration, storing the values in variables.
- Use variables in requests by writing their names exactly, with the same spelling and case as in the element, and check that the element is in scope.
- Plan the data first: decide what varies, calculate rows needed as users times iterations plus a margin, and build files carefully.
- Choose end-of-file behaviour on purpose. Recycling hides shortages, and doing neither recycling nor stopping floods the system with marker values.
- Use sharing mode all threads for different rows per user, and split files per worker in distributed tests where data must be unique.
- Combine CSV data with extractors for values the server invents, and use realistic variety to avoid unrealistic caching.
- Keep data synthetic and protected, use relative paths, smoke test with one user before every big run, and make failures traceable to their data row.