{"id":175,"date":"2024-10-23T07:00:46","date_gmt":"2024-10-23T07:00:46","guid":{"rendered":"https:\/\/yassinemoumen.com\/?p=175"},"modified":"2024-10-23T07:00:47","modified_gmt":"2024-10-23T07:00:47","slug":"app-stress-test-showdown-putting-your-app-to-the-test-with-k6","status":"publish","type":"post","link":"https:\/\/yassinemoumen.com\/?p=175","title":{"rendered":"App Stress Test Showdown: Putting Your App to the Test with k6"},"content":{"rendered":"\n<p>Would you like to see your brand-new app which is malfunctioning with the users, failing to serve them, and representing a stale cookie after being demolished with a hammer? Clearly, a scenario that is way too intense, don&#8217;t you agree? Nevertheless, we are able to avoid this situation by using testing tools like <strong>k6 <\/strong>which is a freeware tool for simulation of a group of virtual users, you can ruin your app in the lab to investigate the weakest spots and start to fix them before your users actually get to them.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why Stress Test Your App?<\/h2>\n\n\n\n<p>Imagine your app is like a race car. You wouldn\u2019t throw it onto the track before putting it through rigorous test laps, would you? <strong>Load testing<\/strong> is the equivalent of those test laps for your app\u2014helping you simulate real user activity to observe how your app performs under stress. The goal? Find vulnerabilities before launch to avoid embarrassing outages and to ensure your users get a smooth experience.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">k6: The Load Testing Champion<\/h2>\n\n\n\n<p><strong>k6<\/strong> is the champion tool for load testing your app. It&#8217;s free, intuitive, and allows you to write easy scripts to simulate user behavior. Imagine a swarm of pretend users browsing, clicking, and interacting with your app simultaneously. k6 helps you orchestrate that and then reports on how well (or poorly) your app performed, allowing you to zero in on any weak points.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Scripting Your User Swarm: Getting Started with k6<\/h2>\n\n\n\n<p>Let\u2019s jump into coding! Here&#8217;s an example of a basic <strong>k6 script<\/strong> that simulates users visiting your app\u2019s homepage:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import http from 'k6\/http';\nimport { sleep } from 'k6';\n\nexport default function () {\n  http.get('https:\/\/your-app.com');\n  sleep(1);\n}<\/code><\/pre>\n\n\n\n<p>This script simply instructs each virtual user to visit your homepage. But the real power of k6 lies in its flexibility\u2014you can build much more sophisticated scenarios:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Login Rush:<\/strong> Create a script that logs each virtual user in, sending credentials to your login page.<\/li>\n\n\n\n<li><strong>Shopping Frenzy:<\/strong> Simulate users adding items to their shopping carts, replicating the traffic spikes during a flash sale.<\/li>\n\n\n\n<li><strong>API Overload:<\/strong> Test your backend\u2019s capabilities by bombarding your app\u2019s APIs with requests, seeing how long it takes to respond.<\/li>\n<\/ul>\n\n\n\n<p>With your script ready, it&#8217;s time to unleash the horde of virtual users. <strong>k6<\/strong> makes this easy. You can run the tests locally on your own machine for smaller-scale tests, or use cloud infrastructure for larger, more demanding tests. Running a local test is as simple as typing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>k6 run your-script.js<\/code><\/pre>\n\n\n\n<p>For cloud-based testing, k6 integrates seamlessly with k6 Cloud, letting you scale up your tests to simulate thousands of users from around the world.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">In Real-World<\/h2>\n\n\n\n<p>What we typically seek from k6 is to cover multiple scenarios, such as user logins, browsing, and interacting with an API endpoint, and to simulate realistic user behavior with <strong>ramped load testing<\/strong>, gradually increasing the number of virtual users over time. Here is an example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import http from 'k6\/http';\nimport { sleep, check, group } from 'k6';\nimport { Trend, Counter, Rate } from 'k6\/metrics';\n\n\/\/ Custom metrics for better reporting\nconst loginDuration = new Trend('login_duration');\nconst errors = new Counter('errors');\nconst successRate = new Rate('successful_requests');\n\n\/\/ Test configuration\nexport const options = {\n  stages: &#91;\n    { duration: '30s', target: 10 }, \/\/ Ramp up to 10 users\n    { duration: '1m', target: 50 },  \/\/ Hold at 50 users\n    { duration: '30s', target: 0 },  \/\/ Ramp down to 0 users\n  ],\n  thresholds: {\n    http_req_duration: &#91;'p(95)&lt;500'], \/\/ 95% of requests must complete in &lt;500ms\n    successful_requests: &#91;'rate>0.95'], \/\/ At least 95% of requests must be successful\n  },\n};\n\nconst BASE_URL = 'https:\/\/your-app.com'; \/\/ Replace with your app's URL\n\n\/\/ User credentials for login simulation\nconst USERNAME = 'testuser';\nconst PASSWORD = 'password123';\n\nexport default function () {\n  \/\/ Group user behavior into logical sections for clarity\n  group('User Journey: Homepage', function () {\n    const res = http.get(`${BASE_URL}\/`);\n    check(res, {\n      'Homepage loaded successfully': (r) => r.status === 200,\n      'Homepage load time &lt; 300ms': (r) => r.timings.duration &lt; 300,\n    }) || errors.add(1);\n    sleep(1); \/\/ Simulate think time\n  });\n\n  group('User Journey: Login', function () {\n    const payload = JSON.stringify({\n      username: USERNAME,\n      password: PASSWORD,\n    });\n    const headers = { 'Content-Type': 'application\/json' };\n\n    const res = http.post(`${BASE_URL}\/login`, payload, { headers });\n    check(res, {\n      'Login successful': (r) => r.status === 200,\n      'Response contains auth token': (r) => r.json('token') !== '',\n    }) || errors.add(1);\n\n    loginDuration.add(res.timings.duration);\n    sleep(1);\n  });\n\n  group('User Journey: Browse Products', function () {\n    const res = http.get(`${BASE_URL}\/products`);\n    check(res, {\n      'Products loaded': (r) => r.status === 200,\n      'Products load time &lt; 400ms': (r) => r.timings.duration &lt; 400,\n    }) || errors.add(1);\n    sleep(1);\n  });\n\n  group('User Journey: Add Item to Cart', function () {\n    const productId = 1; \/\/ Assume product ID 1 exists for testing\n    const res = http.post(`${BASE_URL}\/cart`, JSON.stringify({ product_id: productId }), {\n      headers: { 'Content-Type': 'application\/json' },\n    });\n    check(res, {\n      'Item added to cart': (r) => r.status === 201,\n    }) || errors.add(1);\n    sleep(1);\n  });\n\n  group('API Performance Test: Check Order Status', function () {\n    const res = http.get(`${BASE_URL}\/orders\/123\/status`);\n    check(res, {\n      'Order status fetched': (r) => r.status === 200,\n    }) || errors.add(1);\n    sleep(1);\n  });\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Breakdown<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Staging Users Gradually:<\/strong>\n<ul class=\"wp-block-list\">\n<li>The <strong><code>options<\/code><\/strong> block defines a <strong>staged load test<\/strong>.\n<ul class=\"wp-block-list\">\n<li>10 users in the first 30 seconds.<\/li>\n\n\n\n<li>Hold steady at 50 users for 1 minute.<\/li>\n\n\n\n<li>Ramp down to 0 users over the last 30 seconds.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Thresholds:<\/strong>\n<ul class=\"wp-block-list\">\n<li>The script ensures that 95% of requests complete in under 500ms.<\/li>\n\n\n\n<li>At least 95% of requests must be successful (no errors or timeouts).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>User Simulation:<\/strong>\n<ul class=\"wp-block-list\">\n<li><strong>Homepage Load<\/strong>: A GET request to the homepage.<\/li>\n\n\n\n<li><strong>Login Simulation<\/strong>: Users log in with predefined credentials, checking if an authentication token is received.<\/li>\n\n\n\n<li><strong>Browsing Products<\/strong>: Fetching product listings.<\/li>\n\n\n\n<li><strong>Adding to Cart<\/strong>: Simulating adding a product to the cart.<\/li>\n\n\n\n<li><strong>API Check<\/strong>: Checking the status of an order.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Custom Metrics:<\/strong>\n<ul class=\"wp-block-list\">\n<li><strong><code>Trend<\/code><\/strong> metric for tracking login duration.<\/li>\n\n\n\n<li><strong><code>Counter<\/code><\/strong> to track the total number of errors.<\/li>\n\n\n\n<li><strong><code>Rate<\/code><\/strong> to measure the proportion of successful requests.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Error Handling and Sleep:<\/strong>\n<ul class=\"wp-block-list\">\n<li><strong><code>check()<\/code><\/strong> validates the response of each request. If a check fails, the error counter increments.<\/li>\n\n\n\n<li><strong><code>sleep()<\/code><\/strong> simulates user think time between actions.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Running the Test<\/h3>\n\n\n\n<p>Save the script as <code>test-script.js<\/code> and run it with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>k6 run test-script.js<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Analyzing the Aftermath: What Did We Learn?<\/h2>\n\n\n\n<p>Once the test is over, k6 gives you a comprehensive report &#8211; the performance of your app described by this scorecard. The report lists statistics like response time, error rate, and system resources use. These metrics are essential for pinpointing the problems. Was there a sudden increase in page load times under high load? Did the app run into a problem at a point when the number of users exceeded a certain level? Use these observations to address the issues your application is having.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"971\" height=\"1024\" src=\"https:\/\/yassinemoumen.com\/wp-content\/uploads\/2024\/10\/k6-971x1024.png\" alt=\"\" class=\"wp-image-179\" srcset=\"https:\/\/yassinemoumen.com\/wp-content\/uploads\/2024\/10\/k6-971x1024.png 971w, https:\/\/yassinemoumen.com\/wp-content\/uploads\/2024\/10\/k6-284x300.png 284w, https:\/\/yassinemoumen.com\/wp-content\/uploads\/2024\/10\/k6-768x810.png 768w, https:\/\/yassinemoumen.com\/wp-content\/uploads\/2024\/10\/k6-1456x1536.png 1456w, https:\/\/yassinemoumen.com\/wp-content\/uploads\/2024\/10\/k6-1942x2048.png 1942w, https:\/\/yassinemoumen.com\/wp-content\/uploads\/2024\/10\/k6-1200x1266.png 1200w, https:\/\/yassinemoumen.com\/wp-content\/uploads\/2024\/10\/k6-600x633.png 600w, https:\/\/yassinemoumen.com\/wp-content\/uploads\/2024\/10\/k6.png 2048w\" sizes=\"auto, (max-width: 971px) 100vw, 971px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Pro Tips for Using k6 Effectively<\/h2>\n\n\n\n<p><strong>Start Small, Scale Big:<\/strong> Begin with small-scale tests and gradually increase the number of users until you reach expected peak levels. This allows you to identify and fix issues incrementally.<\/p>\n\n\n\n<p><strong>Simulate Realistic User Behavior:<\/strong> Load patterns should mimic real-world scenarios. If users usually log in, browse, and make purchases, simulate this flow. Avoid creating unrealistic behavior patterns that don&#8217;t match typical user journeys.<\/p>\n\n\n\n<p><strong>Automate Performance Testing:<\/strong> Integrate k6 scripts into your CI\/CD pipeline to ensure that every update is validated against performance standards. This prevents regressions from sneaking into production.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>k6 is not only a load testing tool but is a true defender of your app that will check how your app can handle the increased load. When you are able to experience such performance-related issues ahead of time, you can be more confident of a trouble-free product launch and that the end users will be satisfied.<\/p>\n\n\n\n<p>So, grab your k6 scripting skills, rally your virtual user army, and fortify your app to withstand the toughest challenges. With k6, your app will be ready to shine, even when faced with the most intense pressure!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Further Reading<\/h2>\n\n\n\n<p><a href=\"https:\/\/grafana.com\/docs\/k6\/latest\/\">https:\/\/grafana.com\/docs\/k6\/latest\/<\/a><br><a href=\"https:\/\/github.com\/grafana\/k6\">https:\/\/github.com\/grafana\/k6<\/a><br><a href=\"https:\/\/www.youtube.com\/c\/k6test\">https:\/\/www.youtube.com\/c\/k6test<\/a><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Would you like to see your brand-new app which is malfunctioning with the users, failing to serve them, and representing a stale cookie after being demolished with a hammer? Clearly, a scenario that is way too intense, don&#8217;t you agree? Nevertheless, we are able to avoid this situation by using testing tools like k6 which [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[5,6,7],"tags":[],"class_list":["post-175","post","type-post","status-publish","format-standard","hentry","category-computer-performance","category-devops","category-programming","missing-thumbnail"],"_links":{"self":[{"href":"https:\/\/yassinemoumen.com\/index.php?rest_route=\/wp\/v2\/posts\/175","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/yassinemoumen.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/yassinemoumen.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/yassinemoumen.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/yassinemoumen.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=175"}],"version-history":[{"count":8,"href":"https:\/\/yassinemoumen.com\/index.php?rest_route=\/wp\/v2\/posts\/175\/revisions"}],"predecessor-version":[{"id":184,"href":"https:\/\/yassinemoumen.com\/index.php?rest_route=\/wp\/v2\/posts\/175\/revisions\/184"}],"wp:attachment":[{"href":"https:\/\/yassinemoumen.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=175"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yassinemoumen.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=175"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yassinemoumen.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=175"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}