<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Scale Testing - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Scale Testing - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 05 May 2026 16:59:26 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/scale-testing/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build Your First Dynamic Performance Test in Apache JMeter ]]>
                </title>
                <description>
                    <![CDATA[ As a QA engineer, I have always found performance testing to be one of the most exciting and underrated parts of software testing. Yes, functional testing is important, but it’s of little use if users have to wait for 5 seconds for each page to load.... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-your-first-dynamic-performance-test-in-apache-jmeter/</link>
                <guid isPermaLink="false">6900f3ca65a053299e38eab3</guid>
                
                    <category>
                        <![CDATA[ Scale Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Performance Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ jmeter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mah Noor ]]>
                </dc:creator>
                <pubDate>Tue, 28 Oct 2025 16:48:10 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761335397152/cb105a44-4c18-4998-9ffb-d520df0e6510.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As a QA engineer, I have always found performance testing to be one of the most exciting and underrated parts of software testing. Yes, functional testing is important, but it’s of little use if users have to wait for 5 seconds for each page to load.</p>
<p>For me personally, there is a deep satisfaction that comes with seeing your product come alive under load to find out how it’ll actually work in production when thousands of users will be using it.</p>
<p>Performance testing is about discovering how your system performs under real-world pressure in terms of load, concurrency, and throughput. One of the key aspects of performance testing is ensuring that the APIs can endure the expected load. You can do this using tools like Apache JMeter and K6.</p>
<p>In this tutorial, we’ll explore how you can build your first end-to-end performance test in Apache JMeter. You will be learning to create a test suite that is dynamic (the test can be run with any test data) and that’s one-click executable (the test execution can be done through the GUI as well as the CLI).</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-introduction-to-apache-jmeter">Introduction to Apache JMeter</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-create-a-new-test-plan">Step 1: Create a New Test Plan</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-configure-the-thread-group">Step 2: Configure the Thread Group</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-add-http-request-defaults">Step 3: Add HTTP Request Defaults</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-add-a-csv-data-set-config-dynamic-input">Step 4: Add a CSV Data Set Config (Dynamic Input)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-add-the-http-request-sampler">Step 5: Add the HTTP Request Sampler</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-6-add-a-json-extractor">Step 6: Add a JSON Extractor</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-7-add-an-assertion">Step 7: Add an Assertion</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-8-add-listeners">Step 8: Add Listeners</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-9-run-your-test">Step 9: Run Your Test</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-10-chain-another-request-optional">Step 10: Chain Another Request (Optional)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-11-analyze-the-results">Step 11: Analyze the Results</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pro-tips">Pro Tips</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-folder-structure">Example Folder Structure:</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you start, make sure you have:</p>
<ul>
<li><p><a target="_blank" href="https://jmeter.apache.org/download_jmeter.cgi"><strong>Apache JMeter (5.5 or above)</strong></a> installed.</p>
</li>
<li><p><a target="_blank" href="https://www.java.com/en/download/manual.jsp"><strong>Java 8 or later</strong></a> configured on your system.</p>
</li>
</ul>
<p>You can check if JMeter is installed by running the command below:</p>
<pre><code class="lang-plaintext">jmeter -v
</code></pre>
<p><strong>Note:</strong> This tutorial will use the <a target="_blank" href="https://jsonplaceholder.typicode.com/">JSONPlaceholder</a> public API. You’ll learn how you can get a post_id and use it in a chain request to get user details.</p>
<p>Let’s get started.</p>
<h2 id="heading-introduction-to-apache-jmeter">Introduction to Apache JMeter</h2>
<p>Apache JMeter is an open-source API load and stress testing tool. It’s a powerful testing tool that supports a wide range of protocols, including HTTP, HTTPS, FTP, JDBC, SOAP, and REST.</p>
<p>JMeter helps you answer critical questions about your APIs, like:</p>
<ul>
<li><p>How does my API perform under heavy load?</p>
</li>
<li><p>What’s the maximum number of users it can handle before it starts failing?</p>
</li>
<li><p>Which requests or endpoints are slowing things down?</p>
</li>
</ul>
<p>Let’s go through the step-by-step process of building a dynamic load testing suite with JMeter.</p>
<h3 id="heading-step-1-create-a-new-test-plan">Step 1: Create a New Test Plan</h3>
<p>Once JMeter opens, you’ll see an empty Test Plan. Think of this as your main workspace, which holds everything: Test configuration, users, requests, assertions, and results.</p>
<p>Right-click on <strong>Test Plan → Add → Threads (Users) → Thread Group</strong> to add a thread group. A thread group is essentially a test suite containing our test cases.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761045558747/ad3a2fe3-de59-420f-ba9d-1a36323e1d9e.png" alt="Add Thread Group" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-2-configure-the-thread-group">Step 2: Configure the Thread Group</h3>
<p>To configure the thread group, fill out the following input fields:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Setting</td><td>Value</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>Number of Threads (Users)</td><td>5</td><td>This represents the number of concurrent users. In this case, it will be ‘5’</td></tr>
<tr>
<td>Ramp-up Period (seconds)</td><td>10</td><td>This means the time it takes the threads to reach the maximum value.</td></tr>
<tr>
<td>Loop Count</td><td>2</td><td>This specifies the number of times you want your thread group executed.</td></tr>
</tbody>
</table>
</div><p>You’ve now created a small, controlled load test of 10 total requests (5 users × 2 loops).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049951497/8221336c-5f10-4161-81fa-d0ad27c7164f.png" alt="Thread Group" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-3-add-http-request-defaults">Step 3: Add HTTP Request Defaults</h3>
<p>When you’re creating a suite of 100s of APIs, you don’t need to add your request details to all the API samplers in JMeter. JMeter lets you set it once globally by using a config element called HTTP Request Defaults. To add this element, follow the steps below:</p>
<ol>
<li><p>Right-click on <strong>Thread Group → Add → Config Element → HTTP Request Defaults.</strong></p>
</li>
<li><p>Enter the following:</p>
<ul>
<li><p><strong>Protocol:</strong> <code>https</code></p>
</li>
<li><p><strong>Server Name or IP:</strong> <a target="_blank" href="http://jsonplaceholder.typicode.com"><code>jsonplaceholder.typicode.com</code></a></p>
</li>
</ul>
</li>
</ol>
<p>This means all requests in this test will automatically use this base URL.</p>
<h3 id="heading-step-4-add-a-csv-data-set-config-dynamic-input">Step 4: Add a CSV Data Set Config (Dynamic Input)</h3>
<p>In real projects, APIs rarely use static inputs. Take as an example a login API that you want to run for 100 concurrent users. In a real-world scenario, every login request will have a different username and password.</p>
<p>To replicate this on JMeter, you need to run your test for 100 different login credentials. This means that your test should be <strong>test data-driven</strong>. We can build a data-driven test in JMeter using a <strong>CSV file</strong>:</p>
<ol>
<li><p>Create a file named <code>data.csv</code> with the following content:</p>
<pre><code class="lang-plaintext"> post_id
 1
 2
 3
 4
 5
</code></pre>
</li>
<li><p>Save it in your JMeter project folder.</p>
</li>
<li><p>In JMeter, right-click on <strong>Thread Group → Add → Config Element → CSV Data Set Config.</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761048312824/4558aae4-23c8-446d-89d0-237aca29619d.png" alt="Add CSV Data Set Config" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
</li>
<li><p>Fill in the following fields:</p>
<ul>
<li><p><strong>Filename:</strong> <code>data.csv</code></p>
</li>
<li><p><strong>Variable Names:</strong> <code>post_id</code></p>
</li>
<li><p><strong>Recycle on EOF:</strong> <code>True</code></p>
</li>
<li><p><strong>Stop thread on EOF:</strong> <code>False</code></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761048167041/eae27f5c-6e23-4c7d-8890-b3eb5943bb66.png" alt="CSV Data Set Config" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
</li>
</ul>
</li>
</ol>
<p>Now each user will pick a new <code>post_id</code> for every iteration from the CSV file.</p>
<h3 id="heading-step-5-add-the-http-request-sampler">Step 5: Add the HTTP Request Sampler</h3>
<p>Now let’s add the actual API call we'll test under load. To do this, follow the steps below:</p>
<ol>
<li><p>Right-click on <strong>Thread Group → Add → Sampler → HTTP Request.</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761051865320/92bf89d0-616c-4d07-9531-3985265e07d7.png" alt="Add an HTTP Request" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
</li>
<li><p>Rename it to <strong>Get Post Data.</strong></p>
</li>
<li><p>Set the following fields:</p>
<ul>
<li><p><strong>Method:</strong> GET</p>
</li>
<li><p><strong>Path:</strong> <code>/posts/${post_id}</code></p>
</li>
</ul>
</li>
</ol>
<p>Here <code>${post_id}</code> dynamically takes its value from your CSV file. The Protocol and Server IP fields will automatically get data from the ‘HTTP Request default’ config element that we added in Step #3.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049282841/a420139c-4622-4d7a-ac7d-4308bb9a1dbc.png" alt="Add a GET Request" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-6-add-a-json-extractor">Step 6: Add a JSON Extractor</h3>
<p>When the API returns a response, we can extract a value (like <code>userId</code>) from it and use it later. This is used to implement an end-to-end flow where data is gotten (with GET) from an API and sent to the next POST/DELETE API.</p>
<p>For our API, below is the example response:</p>
<pre><code class="lang-plaintext">{
  "userId": 1,
  "id": 3,
  "title": "fugiat veniam minus",
  "body": "This is an example post body"
}
</code></pre>
<p>To extract <code>userId</code>:</p>
<ol>
<li><p>Right-click on <strong>Get Post Data → Add → Post Processors → JSON Extractor.</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761051791176/b7888a78-efbb-48d3-8aba-fcd21edfd8f2.png" alt="Add JSON Extractor" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
</li>
<li><p>Set the variables below in the JSON Extractor:</p>
<ul>
<li><p><strong>Name:</strong> Extract User ID</p>
</li>
<li><p><strong>Variable Name:</strong> <code>user_id</code></p>
</li>
<li><p><strong>JSON Path Expression:</strong> <code>$.userId</code></p>
</li>
</ul>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049324410/8a163733-8925-4557-9ace-124b08167f8e.png" alt="JSON Extractor" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Now you can use <code>${user_id}</code> in the next request, making your test fully dynamic.</p>
<h3 id="heading-step-7-add-an-assertion">Step 7: Add an Assertion</h3>
<p>Assertions help you verify that your API responds correctly even under load. You can assert on the API response code, response time, or even the response payload. To add an assertion, follow the steps below:</p>
<ol>
<li><p>Right-click <strong>Get Post Data → Add → Assertions → Response Assertion.</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049384591/a0293eef-74a0-4d55-b0c4-232d5c5eaa0c.png" alt="Add Response Assertion" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
</li>
<li><p>Configure as:</p>
<ul>
<li><p><strong>Response Field to Test:</strong> <em>Response Code –</em> This will add an assertion for the response code.</p>
</li>
<li><p><strong>Pattern Matching Rules:</strong> <em>Contains</em></p>
</li>
<li><p><strong>Pattern to Test:</strong> 200</p>
</li>
</ul>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050184412/5a52f600-74f6-48c7-a975-7e39df47afdb.png" alt="Add Response Assertion" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>This ensures JMeter only counts the request as successful if the word <code>fugiat</code> appears in the response.</p>
<h3 id="heading-step-8-add-listeners">Step 8: Add Listeners</h3>
<p>We’ll add listeners to display our test results in different forms, such as visually or in a summary. Let’s add two essential ones:</p>
<ol>
<li><p><strong>View Results Tree</strong>: to view and debug individual requests.</p>
</li>
<li><p><strong>Summary Report</strong>: to view performance metrics like response time, error rate, and throughput.</p>
</li>
</ol>
<p>Add them via <strong>Thread Group → Add → Listener → [Choose Listener]</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761049568483/0daa916c-503d-4f91-ad17-1d2bd29a9f72.png" alt="Add Listener in JMeter" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-9-run-your-test">Step 9: Run Your Test</h3>
<p>Hit the green <strong>Start</strong> button at the top. JMeter will start sending requests to your API using the dynamic post IDs from your CSV file.</p>
<p>As the test runs:</p>
<ul>
<li><p>Green checkmarks in <strong>View Results Tree</strong> mean successful responses.</p>
</li>
<li><p>Assertion failures will appear in red.</p>
</li>
<li><p><strong>Summary Report</strong> will aggregate key metrics.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050151356/d8c72408-cf91-4c9d-8663-0a65b6943f5b.png" alt="JMeter View Results Tree" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050211424/532dd999-b870-4cf8-ad1e-1a692119b0e0.png" alt="JMeter Summary Report" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-10-chain-another-request-optional">Step 10: Chain Another Request (Optional)</h3>
<p>Let’s take it one step further: we’ll use the extracted <code>user_id</code> from the first response to get user details from the <a target="_blank" href="https://jsonplaceholder.typicode.com/users">GET users call</a>. To do this, follow the steps below:</p>
<ol>
<li><p>Right-click <strong>Thread Group → Add → Sampler → HTTP Request.</strong></p>
</li>
<li><p>Rename to <strong>Get User Details.</strong></p>
</li>
<li><p>Set:</p>
<ul>
<li><p><strong>Method:</strong> GET</p>
</li>
<li><p><strong>Path:</strong> <code>/users/${user_id}</code></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050384264/dcc1c333-4e06-4dd9-8dca-9af823fedabd.png" alt="GET Users API" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
</li>
</ul>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761050365937/736b9954-6d01-45a6-8c16-f6d2ceb60e10.png" alt="Test Execution in JMeter" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-11-analyze-the-results">Step 11: Analyze the Results</h3>
<p>Once the test completes, open the <strong>Summary Report</strong>. You’ll see:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Metric</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Sample Count</strong></td><td>Number of total requests sent</td></tr>
<tr>
<td><strong>Average</strong></td><td>Mean response time per request</td></tr>
<tr>
<td><strong>Min/Max</strong></td><td>Fastest and slowest response times</td></tr>
<tr>
<td><strong>Error %</strong></td><td>Percentage of failed requests</td></tr>
<tr>
<td><strong>Throughput</strong></td><td>Requests handled per second</td></tr>
</tbody>
</table>
</div><p>If your error percentage is 0% and throughput is stable, your system handled the load well.</p>
<h3 id="heading-pro-tips">Pro Tips</h3>
<ul>
<li><p><strong>Parameterize everything.</strong> Use multiple CSVs for realistic test flows (users, IDs, tokens).</p>
</li>
<li><p><strong>Add timers</strong> (like <em>Constant Timer</em>) to simulate think time between user actions.</p>
</li>
<li><p><strong>Use Assertions wisely.</strong> Don’t add extra assertions; focus on key validations such as response time and API status code.</p>
</li>
<li><p><strong>Generate HTML reports using the command below:</strong></p>
<pre><code class="lang-plaintext">  jmeter -n -t test-plan.jmx -l results.jtl -e -o report
</code></pre>
</li>
</ul>
<h3 id="heading-example-folder-structure">Example Folder Structure:</h3>
<p>Follow the folder structure below for an organized test suite.</p>
<pre><code class="lang-plaintext">performance-test/
├── data.csv
├── test-plan.jmx
└── results/
    ├── summary.csv
    └── report.html
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Performance testing is an essential element of a production readiness checklist for any product. It helps you ensure that your product can handle the expected user load and scale gracefully.</p>
<p>This guide is your first step towards writing end-to-end performance test cases and bridging the gap between being a functional test engineer and a full-stack QA Engineer who understands both quality and scalability.</p>
<p>I hope you found this tutorial helpful. If you want to stay connected or learn more about performance testing, follow me on <a target="_blank" href="https://www.linkedin.com/in/mah-noorqa/">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
