<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Jmeter on Nicole van der Hoeven</title><link>https://nicolevanderhoeven.com/tags/jmeter/</link><description>Recent content in Jmeter on Nicole van der Hoeven</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>Nicole van der Hoeven</copyright><lastBuildDate>Mon, 17 Jan 2022 16:30:07 +0100</lastBuildDate><atom:link href="https://nicolevanderhoeven.com/tags/jmeter/index.xml" rel="self" type="application/rss+xml"/><item><title>Testing tool cheat sheet for load testers who don't just care about numbers</title><link>https://nicolevanderhoeven.com/blog/20220117-testing-tool-cheat-sheet-for-load-testers-who-dont-just-care-about-numbers/</link><pubDate>Mon, 17 Jan 2022 16:30:07 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20220117-testing-tool-cheat-sheet-for-load-testers-who-dont-just-care-about-numbers/</guid><description>&lt;p&gt;It&amp;rsquo;s not enough to decide &lt;em&gt;how much&lt;/em&gt; load you want to generate. You also have to know &lt;em&gt;how&lt;/em&gt; you&amp;rsquo;re generating it.&lt;/p&gt;
&lt;p&gt;Your approach affects what part of your application is tested, the results returned, and the budget you&amp;rsquo;ll need to run your test.&lt;/p&gt;
&lt;p&gt;Here are three main categories of load testing tools:&lt;/p&gt;
&lt;h2 id="protocol-based-load-testing-tools"&gt;Protocol-based load testing tools:&lt;/h2&gt;
&lt;p&gt;These tools simulate the underlying messages sent back and forth between an application and a client.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Choose a protocol-based tool if&lt;/em&gt;: you want to generate massive load, you want to load test before components are integrated, you want to test APIs, or you are budget-conscious.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Best in class tools&lt;/em&gt;: Gatling, JMeter, k6, Locust, Neoload&lt;/p&gt;
&lt;h2 id="browser-based-load-testing-tools"&gt;Browser-based load testing tools:&lt;/h2&gt;
&lt;p&gt;These tools automate real user interactions with an interface.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Choose a browser-based tool if:&lt;/em&gt; you want to measure end-to-end performance, you want to reuse your browser automation scripts, you want front-end performance metrics, or you have a higher budget.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Best in class tools:&lt;/em&gt; Cypress, Flood Element, k6, Playwright, Puppeteer&lt;/p&gt;
&lt;h2 id="hybrid-load-testing-tools"&gt;Hybrid load testing tools:&lt;/h2&gt;
&lt;p&gt;This approach is a mixture of the previous two. You can do this in a few ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use a protocol tool to generate the majority of the load, and a browser tool for a handful of virtual users &lt;em&gt;(best functionality, highest effort/cost)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Use a browser-based tool for all load &lt;em&gt;(expensive, simplest)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Find a tool that can do both &lt;em&gt;(ideal solution, few options)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="whatever-you-choose-compare-like-with-like"&gt;Whatever you choose, compare like with like.&lt;/h2&gt;
&lt;p&gt;Happy testing!&lt;/p&gt;</description></item><item><title>Realistic load testing</title><link>https://nicolevanderhoeven.com/blog/20210807-clubhouse-realistic-load-tests/</link><pubDate>Sat, 07 Aug 2021 22:15:13 +0200</pubDate><guid>https://nicolevanderhoeven.com/blog/20210807-clubhouse-realistic-load-tests/</guid><description>&lt;p&gt;This is a conversation I recorded from Clubhouse in the Performance Engineers group created by NaveenKumar Namachivayam today, August 7th, 2021. I started by introducing myself and then let everyone know that I would be recording the conversation. Enjoy!&lt;/p&gt;
&lt;iframe src="https://open.spotify.com/embed/episode/5MJaz2PAhYfy5FShrIaXUK" width="100%" height="232" frameBorder="0" allowtransparency="true" allow="encrypted-media"&gt;&lt;/iframe&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/-hBVZqNJ4_A?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;</description></item><item><title>Comparing k6 and JMeter for load testing</title><link>https://nicolevanderhoeven.com/blog/20210129-k6-vs-jmeter/</link><pubDate>Fri, 29 Jan 2021 23:01:18 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20210129-k6-vs-jmeter/</guid><description>
&lt;link rel="canonical" href="https://k6.io/blog/k6-vs-jmeter"&gt;
&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://k6.io/blog/k6-vs-jmeter"&gt;k6.io&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/noZppBruOSY?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h1 id="introduction"&gt;Introduction&lt;/h1&gt;
&lt;p&gt;When I &lt;a href="https://www.youtube.com/watch?v=zcYeboT5FYE&amp;amp;list=PLJdv3RhAQXNHsC8OOV3ZjwZvC9tRoAYF2"&gt;joined the k6 team in late November&lt;/a&gt;, the foremost question on my mind was &amp;ldquo;How does this compare to JMeter?&amp;rdquo; You see, I come from a performance testing consulting background, and in the last few years, JMeter has been far and away my tool of choice.&lt;/p&gt;
&lt;p&gt;So what am I doing on the k6 site, talking about how much I love JMeter? Well, firstly, it turns out that the k6 team is pretty open and transparent, especially about potential improvements in k6. Secondly, I want to share my reasons for wanting to explore k6 as a load testing tool&amp;ndash; the same reasons that ultimately convinced me to join the team that builds it.&lt;/p&gt;
&lt;h2 id="what-is-jmeter"&gt;What is JMeter?&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://jmeter.apache.org/"&gt;JMeter&lt;/a&gt; is an open source load testing tool built entirely in Java by the &lt;a href="https://www.apache.org/"&gt;Apache Foundation&lt;/a&gt;. It was first released in 1998, and it made waves because of its audacity in taking on more popular but proprietary load testing tools. JMeter took what other companies were charging a lot of money for and published it online for everyone to use&amp;ndash; for free. Although scripts can also be extended using code, majority of the scripting in JMeter is done using the UI. At the time of this writing, the latest version of JMeter is 5.4.&lt;/p&gt;
&lt;h2 id="what-is-k6"&gt;What is k6?&lt;/h2&gt;
&lt;p&gt;k6 is an &lt;a href="https://github.com/loadimpact/k6"&gt;open source&lt;/a&gt; load testing tool released by &lt;a href="https://loadimpact.com"&gt;LoadImpact&lt;/a&gt; in 2017. LoadImpact had previously consisted of the SaaS platform (now &lt;a href="https://k6.io/cloud"&gt;k6 Cloud&lt;/a&gt;) and professional services. k6 is written in Go, but scripts are written in Javascript. Taking the opposite tack to JMeter, k6&amp;rsquo;s main selling point is its code-based scripting and heavy prioritization of the developer experience. The latest version of k6 is 0.30.&lt;/p&gt;
&lt;h2 id="which-is-better"&gt;Which is better?&lt;/h2&gt;
&lt;p&gt;This article isn&amp;rsquo;t about which tool is &lt;em&gt;better&lt;/em&gt;, because as much as we might prefer a clear-cut answer, there&amp;rsquo;s no &amp;ldquo;best tool&amp;rdquo;. Everything depends on the situation your team is in: what, how, why, and when you&amp;rsquo;re testing.&lt;/p&gt;
&lt;p&gt;The question that I want to answer here is: &lt;em&gt;What situations does each tool excel in?&lt;/em&gt;&lt;/p&gt;
&lt;h1 id="when-does-jmeter-excel"&gt;When does JMeter excel?&lt;/h1&gt;
&lt;h2 id="when-you-want-to-get-started-quickly"&gt;When you want to get started quickly&lt;/h2&gt;
&lt;h3 id="jmeter-has-a-gui"&gt;JMeter has a GUI&lt;/h3&gt;
&lt;p&gt;Many testing teams make decisions on load testing tools based on this fact alone. Sometimes, if you&amp;rsquo;re in a situation where people haven&amp;rsquo;t done load testing before and need to learn a new tool, a GUI-driven tool like JMeter is simply the most frictionless option. A tool with a GUI will be less daunting for many testers that are used to the mostly no-code UIs of the likes of Postman or SOAPUI.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/01-jmetergui.png" alt="JMeter’s starting screen: a fresh new test plan" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve always thought of JMeter as user-friendly, but a developer friend recently pointed out that the Test Plan screen that greets you when you first start JMeter doesn&amp;rsquo;t provide any indication of how to create an HTTP sampler. None of the icons add elements to the test plan. It takes a bit of exploring to realize that right clicking on the test plan, or going to Edit &amp;gt; Add, will show the &amp;ldquo;Add&amp;rdquo; menu that you need. He has a point there: UI is subjective to a certain degree. However, I&amp;rsquo;d argue that it&amp;rsquo;s definitely easier for non-developers to explore a UI than a bit of code.&lt;/p&gt;
&lt;p&gt;k6 doesn&amp;rsquo;t have a GUI packaged within the tool, but the &lt;a href="https://k6.io/docs/test-authoring/test-builder"&gt;k6 Test Builder&lt;/a&gt; is available for free. It&amp;rsquo;s a way to create tests with a GUI interface, and despite its inclusion in k6 cloud, it doesn&amp;rsquo;t require any subscription to use. However, it isn&amp;rsquo;t as fully-featured as JMeter.&lt;/p&gt;
&lt;h3 id="jmeter-supports-many-protocols-and-features-out-of-the-box"&gt;JMeter supports many protocols and features out of the box&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s &lt;a href="https://jmeter.apache.org/index.html"&gt;the official list&lt;/a&gt; of the protocols that JMeter supports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Web - HTTP, HTTPS (Java, NodeJS, PHP, ASP.NET, …)&lt;/li&gt;
&lt;li&gt;SOAP / REST Webservices&lt;/li&gt;
&lt;li&gt;FTP&lt;/li&gt;
&lt;li&gt;Database via JDBC&lt;/li&gt;
&lt;li&gt;LDAP&lt;/li&gt;
&lt;li&gt;Message-oriented middleware (MOM) via JMS&lt;/li&gt;
&lt;li&gt;Mail - SMTP(S), POP3(S) and IMAP(S)&lt;/li&gt;
&lt;li&gt;Native commands or shell scripts&lt;/li&gt;
&lt;li&gt;TCP&lt;/li&gt;
&lt;li&gt;Java Objects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In contrast, k6 supports the following protocols:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Web - HTTP/1.1, &lt;a href="https://k6.io/docs/using-k6/protocols/http-2"&gt;HTTP/2&lt;/a&gt; (Java, NodeJS, PHP, ASP.NET, …)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://k6.io/docs/using-k6/protocols/websockets"&gt;WebSockets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://k6.io/docs/using-k6/protocols/grpc"&gt;gRPC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;SOAP / REST Webservices&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The protocols above are those that are natively supported. However, both tools allow the development of third-party plugins, adding support for more protocols. The number of &lt;a href="https://github.com/topics/xk6"&gt;k6 community extensions&lt;/a&gt;, through &lt;a href="https://k6.io/blog/extending-k6-with-xk6"&gt;xk6&lt;/a&gt;, is growing, but &lt;a href="https://jmeter-plugins.org/"&gt;JMeter plugins&lt;/a&gt; still outnumber them. In many cases, the protocols your application uses may make the decision for you of which tool to use.&lt;/p&gt;
&lt;p&gt;JMeter also has most of the features you&amp;rsquo;ll need for a basic load test, and you don&amp;rsquo;t have to code any of it up yourself. Its parent-child element structure means that you can modify a specific element, like an HTTP request, or modify all HTTP requests, with equal ease. Adding think time to all requests is as easy as adding a Uniform Random Timer to your thread group, and all requests within that group will inherit it.
With code-based load testing tools, it can be a bit more difficult to find out what&amp;rsquo;s possible without a UI. Some of the gap, however, can be bridged by an IDE with good autocompletion.&lt;/p&gt;
&lt;h2 id="when-you-want-a-mature-community-with-tons-of-documentation"&gt;When you want a mature community with tons of documentation&lt;/h2&gt;
&lt;p&gt;JMeter&amp;rsquo;s old, and sometimes that&amp;rsquo;s a good thing. It&amp;rsquo;s been around since 1998, so at this point, it&amp;rsquo;s had 22 years to improve and to build a following. JMeter has a presence on nearly every community networking site, and no matter how specific your use case for JMeter is, the chances are that it&amp;rsquo;s been done before. Searching &amp;ldquo;how to load test X with JMeter&amp;rdquo; is bound to yield thousands of hits and some videos showing you exactly how to do it.&lt;/p&gt;
&lt;p&gt;JMeter&amp;rsquo;s &lt;a href="https://jmeter.apache.org/usermanual/component_reference.html"&gt;Component Reference&lt;/a&gt; is proof of JMeter&amp;rsquo;s extensive and thorough documentation. Every element, function, and property is discussed in more detail than most people could ever want, and that&amp;rsquo;s just the &amp;ldquo;official&amp;rdquo; documentation that&amp;rsquo;s on the Apache site. There are thousands of JMeter books, tutorials, and courses by its passionate users.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/apache/jmeter"&gt;JMeter GitHub repository&lt;/a&gt; has 17,290 commits as of December 2020 - evidence of a community of developers that have committed some time and experience to JMeter over the last two decades.&lt;/p&gt;
&lt;p&gt;In comparison, the k6 community is growing, but still small. There is an official and &lt;a href="https://community.k6.io/"&gt;central community forum&lt;/a&gt; that allows users to share their experiences with k6, which is something missing from the JMeter community. The &lt;a href="https://github.com/loadimpact/k6"&gt;k6 repository&lt;/a&gt; does have more stars, but significantly fewer commits at 3,795. Much of the disparity, of course, is because k6 is very new - the open-source tool k6 was only released in 2017.&lt;/p&gt;
&lt;h2 id="when-you-need-a-cost-effective-way-to-do-distributed-load-testing"&gt;When you need a cost-effective way to do distributed load testing&lt;/h2&gt;
&lt;p&gt;One of JMeter&amp;rsquo;s absolute best features is that it gives you a framework for running distributed load tests with it. This is pretty special for a free and open-source tool.&lt;/p&gt;
&lt;p&gt;Distributed testing means ramping up the amount of load you&amp;rsquo;re generating with your load tests, usually by increasing the number of virtual users and running multiple instances of your script on other load generators. JMeter accomplishes this by designating a controller node and letting you set up worker nodes. Each worker node needs to have a copy of &lt;code&gt;jmeter-server&lt;/code&gt;, a utility included with every JMeter installation (in &lt;code&gt;jmeter/bin&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/02-jmeterdistributed.svg" alt="JMeter comes with a native distributed testing mode" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Source: &lt;a href="https://jmeter.apache.org/usermanual/jmeter_distributed_testing_step_by_step.html"&gt;Apache JMeter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;These worker nodes then run copies of your test plan and exert load against your application server. You can use on-premise or cloud machines as your worker nodes. A distributed execution like this takes a bit to set up, but it does work surprisingly well.&lt;/p&gt;
&lt;p&gt;k6 doesn&amp;rsquo;t have a &lt;em&gt;native&lt;/em&gt; distributed load testing mode. You &lt;em&gt;can&lt;/em&gt; containerize it yourself and deploy it via Kubernetes, for instance, but it does require a more involved setup. The team is also working on the &lt;a href="https://github.com/k6io/operator"&gt;k6 Operator&lt;/a&gt;, which makes setup significantly easier, but it is experimental and comes with drawbacks such as not supporting threshold synchronization between instances. For now, the easiest way to scale up on k6 is by using the paid service k6 Cloud, which reduces setup time and complexity significantly.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s important to note that JMeter can be quite resource-hungry, and thus is more likely to require multiple load generators to generate load than k6. Depending on the resources of the load generator, JMeter can run about a thousand virtual users on average, and scaling up your test beyond that point will require a distributed execution setup. A single instance of k6, on the other hand, can run tens of thousands of virtual users given the same resources. More on that later.&lt;/p&gt;
&lt;h2 id="when-you-want-canned-reports-built-into-your-load-testing-tool"&gt;When you want canned reports built into your load testing tool&lt;/h2&gt;
&lt;p&gt;JMeter&amp;rsquo;s many listeners allow you to decide exactly what format you want to view results in. Debugging? Use the View Results Tree. Wanting metrics for your load test? Use the Summary or Aggregate Report.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/03-jmeterlistener.png" alt="Adding listeners like View Results Tree in JMeter lets you visualize results in different ways" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;In addition, JMeter can generate HTML reports based on your load tests. They&amp;rsquo;re currently quite limited, but functional, and they have several default graphs to help you analyze your load test. They are not interactive, but they are pretty easy to generate and a good starting point for putting together a report template for your tests.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/04-jmeterhtmlreport.png" alt="JMeter’s built-in HTML dashboard is limited but functional" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;k6 does not have built-in reporting. Its modular nature lends itself better to integrating with &lt;a href="https://k6.io/docs/results-visualization"&gt;many other data analytics tools&lt;/a&gt;, including Grafana, Datadog, New Relic, Amazon CloudWatch, and k6 Cloud&amp;ndash; all of which are better analysis tools and can provide more insights than what JMeter&amp;rsquo;s reports can provide, but they do require you to set up another tool to analyze your tests. If you&amp;rsquo;re running low on time and can make do with its reports, JMeter does really well at providing that extra value out of the box.&lt;/p&gt;
&lt;h1 id="when-does-k6-excel"&gt;When does k6 excel?&lt;/h1&gt;
&lt;h2 id="when-you-want-to-get-started-quickly-1"&gt;When you want to get started quickly&lt;/h2&gt;
&lt;p&gt;Yup, I put this one in both the JMeter and k6 sections. JMeter and k6 can each be easy to get started with, but for very different reasons.&lt;/p&gt;
&lt;h3 id="installation"&gt;Installation&lt;/h3&gt;
&lt;p&gt;k6 installs extremely quickly - on my first installation of it on macOS, it took &lt;a href="https://www.youtube.com/watch?v=y5tteMKZUqk&amp;amp;t=99"&gt;7 seconds&lt;/a&gt; via &lt;code&gt;brew install k6&lt;/code&gt;. It doesn&amp;rsquo;t require nodeJS or any other dependencies, either.&lt;/p&gt;
&lt;p&gt;JMeter itself is fairly easy to install, but before you install JMeter, you need to install Java. Especially if you&amp;rsquo;re using Windows, it&amp;rsquo;s a bit of a rite of passage for a new JMeter user to run into issues adding the environment variables needed for Java to function.&lt;/p&gt;
&lt;p&gt;It can also be confusing to determine which version of Java is the right one. There&amp;rsquo;s JDK, JRE, and recently Oracle has added to the confusion by announcing that some versions of Java (but not all) are going to require a license.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/05-javalicense.png" alt="Oracle’s changing Java licensing can cause confusion for JMeter users" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Source: &lt;a href="https://java.com/en/download/"&gt;Oracle Java&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;While JMeter is still free via OpenJDK, I&amp;rsquo;ve spoken to a few testers who mistakenly thought they&amp;rsquo;d have to pay for JMeter. It&amp;rsquo;s a little disconcerting to see Oracle flexing its muscles here, especially if you&amp;rsquo;ve built a whole performance testing suite on Java through JMeter.&lt;/p&gt;
&lt;h3 id="plugins"&gt;Plugins&lt;/h3&gt;
&lt;p&gt;k6 &lt;a href="https://k6.io/blog/extending-k6-with-xk6"&gt;supports plugins&lt;/a&gt;, but they&amp;rsquo;re not necessary. For most use cases, k6&amp;rsquo;s built-in functionality should be more than sufficient. This is in sharp contrast to JMeter, where everything is a plugin &amp;hellip; even the &lt;a href="https://jmeter-plugins.org/wiki/PluginsManager/"&gt;Plugin Manager&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Most JMeter users would argue that there is a standard set of plugins that you should download before you even begin to use it. A new JMeter user might not necessarily know where to find these and may have a less-than-satisfying experience out of the box.&lt;/p&gt;
&lt;p&gt;Here are a few things you &lt;em&gt;won&amp;rsquo;t&lt;/em&gt; have if you stick to a vanilla, no-plugin JMeter installation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Thread groups: No custom load profile, stages, rendezvous&lt;/li&gt;
&lt;li&gt;Controllers: No parallel controller to execute requests in parallel&lt;/li&gt;
&lt;li&gt;Samplers: No HTTP/2 support&lt;/li&gt;
&lt;li&gt;Test Data: No randomization of lines within a CSV file (sequential only)&lt;/li&gt;
&lt;li&gt;Timers: No throughput shaping timer for setting throughput in stages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These functions are all available within k6 from the get-go.&lt;/p&gt;
&lt;h3 id="scripting"&gt;Scripting&lt;/h3&gt;
&lt;p&gt;k6 scripts are written in javascript, making them simple to write and run. All you need is one installer (on Microsoft Windows) or a single command on your terminal and any text editor. For JMeter, you&amp;rsquo;ll need to install a few things locally before you can get started: Java, JMeter itself, and the standard set of plugins you&amp;rsquo;ll need. This can be confusing for new users. Who hasn&amp;rsquo;t struggled with environment variables at some point when learning to use JMeter, especially on Windows?&lt;/p&gt;
&lt;p&gt;It also takes time to learn any new UI, whereas javascript is near-ubiquitous and it&amp;rsquo;s a good language to learn when you&amp;rsquo;re load testing web sites anyway.&lt;/p&gt;
&lt;h2 id="when-you-want-to-maximize-performance-and-efficiency"&gt;When you want to maximize performance and efficiency&lt;/h2&gt;
&lt;h3 id="test-your-test-tools"&gt;Test your test tools!&lt;/h3&gt;
&lt;p&gt;Why does all this matter?&lt;/p&gt;
&lt;p&gt;When we&amp;rsquo;re talking about simulating many virtual users, slow performance = high cost. There is a cost to the number of load generators you use, whether it&amp;rsquo;s the cost to acquire and maintain them (on-prem) or the cost of a cloud service.&lt;/p&gt;
&lt;p&gt;It makes sense to consider the performance limitations of your load testing tool before you use it to improve your own application&amp;rsquo;s performance.&lt;/p&gt;
&lt;h3 id="k6-builds-on-gos-stellar-performance"&gt;k6 builds on Go&amp;rsquo;s stellar performance&lt;/h3&gt;
&lt;p&gt;k6 is written in Go, and Go is built with performance in mind. &amp;ldquo;Go is a compiled language and does not need to be interpreted, unlike Java or Python. There is no added layer of complexity.&amp;rdquo; It also has no external dependencies, which is a good thing. Fewer moving parts for a performance tester means fewer potential sources of a bottleneck.&lt;/p&gt;
&lt;p&gt;The simplest and most common way for a load testing tool to run a virtual user is to assign one virtual user to one kernel or OS thread. However, the 1 Thread: 1 Virtual User paradigm has a serious flaw: when a virtual user is waiting for a response or executing a programmed &lt;code&gt;sleep()&lt;/code&gt;, the thread is also blocked, and cannot process other work.&lt;/p&gt;
&lt;p&gt;In k6, each virtual user is run on a goroutine, not a thread. What difference does that make? Well, goroutines can be controlled by something called the Go Scheduler, which acts like a traffic cop. It reuses idle threads and intelligently assigns work, by allowing &amp;ldquo;work stealing&amp;rdquo; and work hand-offs between threads. Does this sound familiar? This is the same principle that load balancers are built on: An external monitor that oversees the flow of work improves general performance. Go itself is intrinsically load-balanced in a way that many programming languages aren&amp;rsquo;t, which makes it the perfect foundation for a load testing tool.&lt;/p&gt;
&lt;p&gt;Being able to leverage Go&amp;rsquo;s innate performance optimizations also translates into significantly less memory utilization. One thread running k6 doesn&amp;rsquo;t go above 100 kb, whereas a JVM thread like JMeter uses, for instance, &lt;a href="https://www.baeldung.com/jvm-configure-stack-sizes"&gt;uses the default of 1MB&lt;/a&gt;. That&amp;rsquo;s 1000% more than k6! Of course, Java allows a user to tweak an app&amp;rsquo;s memory utilization, so the difference is usually not quite as stark, but it&amp;rsquo;s still interesting to note that Go has a much lower starting point.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;hellip; creating [a] new thread in Java is not memory efficient. As every thread consumes approx 1MB of the memory heap size and eventually if you start spinning thousands of threads, they will put tremendous pressure on the heap and will cause shut down due to out of memory. Also, if you want to communicate between two or more threads, it’s very difficult. - &lt;a href="https://medium.com/@kevalpatel2106/why-should-you-learn-go-f607681fad65"&gt;Keval Patel&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="performance-benefits-in-practice"&gt;Performance benefits in practice&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Fewer load generators needed&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;k6&amp;rsquo;s comparatively better performance means it needs fewer load generators to execute a given amount of load. Rafaela Azevedo made a comparison of the memory used by k6 and JMeter, and &lt;a href="https://azevedorafaela.com/2020/07/06/load-tests-jmeter-vs-k6/"&gt;here are her results&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;JMeter took up 760 MB of memory.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/06-jmeterbenchmark.png" alt="In an independent test by Rafaela Azevedo, JMeter took up 760 MB of memory" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Source: &lt;a href="https://azevedorafaela.com/2020/07/06/load-tests-jmeter-vs-k6/"&gt;Rafaela Azevedo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Meanwhile, k6 took up 256 MB of memory.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/07-k6benchmark.png" alt="In an independent test by Rafaela Azevedo, k6 took up 256 MB of memory compared to JMeter’s 760 MB for the same test" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Source: &lt;a href="https://azevedorafaela.com/2020/07/06/load-tests-jmeter-vs-k6/"&gt;Rafaela Azevedo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Rafaela&amp;rsquo;s findings are further affirmed by our own benchmarks.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/08-internalbenchmarks.png" alt="A comparison of maximum throughput and memory for the most popular open-source load testing tools" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Source: Ragnar Lönn, in our &lt;a href="https://k6.io/blog/comparing-best-open-source-load-testing-tools"&gt;Load Testing Tool Comparison&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;k6&amp;rsquo;s lower memory footprint is the reason it can run more virtual users and generate more load than average. Whether you&amp;rsquo;re using load generators that are on-premise or in a cloud, you&amp;rsquo;ll pay less for provisioning costs when using k6. This cost saving makes k6 a great tool for budget-conscious teams.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The common misconception of many load testers is that distributed execution (ability to launch a load test on multiple machines) is required to generate large load. This is not the case with k6. - &lt;a href="https://azevedorafaela.com/2020/07/06/load-tests-jmeter-vs-k6/"&gt;Rafaela Azevedo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;k6 is different from many other load testing tools in the way it handles hardware resources. A single k6 process will efficiently use all CPU cores on a load generator machine. A single instance of k6 is often enough to generate load of 30.000-40.000 simultaneous users (VUs). This amount of VUs can generate upwards of 300,000 requests per second (RPS).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unless you need more than 100,000-300,000 requests per second (6-12M requests per minute), a single instance of k6 will likely be sufficient for your needs. - &lt;a href="https://k6.io/docs/testing-guides/running-large-tests"&gt;k6 documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;No out of memory errors&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;k6 is also good for when you&amp;rsquo;re short on time. Using JMeter means getting familiar with how to performance tune Java and how to fix the &lt;a href="https://www.eginnovations.com/blog/top-10-java-performance-problems/"&gt;most common Java performance problems&lt;/a&gt;, because there are several. The one that I&amp;rsquo;ve personally run into the most while using JMeter is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ERROR - jmeter.threads.JMeterThread: Test failed! java.lang.OutOfMemoryError:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Java heap space.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You&amp;rsquo;re not really a JMeter load tester until you&amp;rsquo;ve seen this error. :)&lt;/p&gt;
&lt;p&gt;The cause for this error is usually that there was an insufficient amount of Heap memory allocated to JMeter. Yup&amp;ndash; in addition to monitoring your load generator&amp;rsquo;s memory usage, you&amp;rsquo;ll also need to monitor the JVM&amp;rsquo;s memory usage. You can set the amount of heap memory allocated to JMeter by modifying the JMeter binary itself and changing this line:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; This is the base heap size &lt;span style="color:#f92672"&gt;--&lt;/span&gt; you may increase or decrease it &lt;span style="color:#66d9ef"&gt;to&lt;/span&gt; fit your
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; system&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;s memory availability:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;${HEAP:=&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;Xms1g &lt;span style="color:#f92672"&gt;-&lt;/span&gt;Xmx1g &lt;span style="color:#f92672"&gt;-&lt;/span&gt;XX:MaxMetaspaceSize&lt;span style="color:#f92672"&gt;=&lt;/span&gt;256m&lt;span style="color:#e6db74"&gt;&amp;#34;}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Even JMeter official documentation suggests that you increase the Java Heap size beyond 1GB before you even run your first load test.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Increase the Java Heap size. By default JMeter runs with a heap of 1 GB, this might not be enough for your test and depends on your test plan and number of threads you want to run - &lt;a href="https://jmeter.apache.org/usermanual/get-started.html"&gt;Apache JMeter&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;No GUI means no resource overhead during load tests&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GUIs typically add significantly more overhead to an application, which is one of the reasons why k6 doesn&amp;rsquo;t have one.&lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re running a load test, the best practice is to run it from the command line anyway&amp;ndash; because otherwise, it interferes with your results. Code-based load testing tools are performant from the beginning.&lt;/p&gt;
&lt;p&gt;JMeter is peppered with warnings about the GUI&amp;rsquo;s effect on performance. Here&amp;rsquo;s one from the &amp;ldquo;JMeter documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Don&amp;rsquo;t run load test using GUI mode ! - &lt;a href="https://jmeter.apache.org/usermanual/get-started.html"&gt;Apache JMeter&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And here&amp;rsquo;s a message that occurs upon startup of JMeter:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/09-jmeterguimodewarning.png" alt="JMeter’s startup screen warns users not to use the GUI mode for load testing" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Not having a GUI means there&amp;rsquo;s one less gotcha. Any load testing scripts you create in k6 are ready for prime-time execution whenever you&amp;rsquo;re ready.&lt;/p&gt;
&lt;h2 id="when-you-want-to-do-goal-oriented-testing"&gt;When you want to do goal-oriented testing&lt;/h2&gt;
&lt;p&gt;The most important question a load tester can ask when starting a new load testing project is &amp;ldquo;Why&amp;rdquo;?
Test plans should be made to directly address a team&amp;rsquo;s reasons for wanting to do load testing, and that should be reflected in the non-functional requirements. Non-functional requirements, in turn, should then give some guidance as to the bounds of acceptable performance. A common example for these bounds, or thresholds, is an average response time of less than 3 seconds for all transactions during the test.
k6 does this natively with &lt;a href="https://k6.io/docs/using-k6/thresholds"&gt;global thresholds&lt;/a&gt; worked into the script, and you can also create your own metric to use in a threshold:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;k6/http&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Rate&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;k6/metrics&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;myFailRate&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Rate&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;failed requests&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;options&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;thresholds&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;failed requests&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;rate&amp;lt;0.1&amp;#39;&lt;/span&gt;], &lt;span style="color:#75715e"&gt;// threshold on a custom metric
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;http_req_duration&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;p(95)&amp;lt;500&amp;#39;&lt;/span&gt;], &lt;span style="color:#75715e"&gt;// threshold on a standard metric
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;res&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;https://test-api.k6.io/public/crocodiles/1/&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;myFailRate&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;status&lt;/span&gt; &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Source: &lt;a href="https://k6.io/docs/using-k6/thresholds"&gt;k6 documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;JMeter doesn&amp;rsquo;t natively support thresholds at the test-level. There are a few ways that I&amp;rsquo;ve been able to work around this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Duration Assertion&lt;/strong&gt;: You can add a Duration Assertion to any sampler in JMeter, which allows you set an acceptable response time for that request in milliseconds, beyond which the request (and the transaction that encompasses it) would be marked as failed. However, this is still just at the individual request level, and even putting the duration assertion element at the Test Plan level only applies the same threshold to each child request. It doesn&amp;rsquo;t constitute pass/fail criteria for the test as a whole.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Timers&lt;/strong&gt;: For criteria related to throughput, you can use the Constant Throughput Timer or the Throughput Shaping Timer (plugin). This approach controls how many requests per second are spent. In my experience, it&amp;rsquo;s worth testing how these timers behave when using nested transaction controllers - it may take some rearranging to get right.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance Plugin&lt;/strong&gt;: When integrating JMeter with Jenkins, you can use the Performance Plugin to set error thresholds and mark test runs (&amp;ldquo;builds&amp;rdquo;) as unstable or failed within Jenkins.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Custom Code&lt;/strong&gt;: You can use the JSR223 Sampler to write a bit of Groovy or BeanShell code that collects and parses response metrics.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The problem is that even though these options make setting thresholds possible in JMeter, they&amp;rsquo;re still workarounds that don&amp;rsquo;t come with JMeter out of the box or don&amp;rsquo;t adequately address the creation of different types of thresholds (error, response time, throughput, CPU, memory). What I end up doing, more often than not, is exporting the raw data from JMeter and doing the analysis myself using another tool.&lt;/p&gt;
&lt;h2 id="when-youre-part-of-a-team-of-scripters"&gt;When you&amp;rsquo;re part of a team of scripters&lt;/h2&gt;
&lt;p&gt;k6 shines in situations where more than one person could be doing the scripting.&lt;/p&gt;
&lt;h3 id="it-strikes-a-middle-ground-that-developers-and-testers-can-compromise-on"&gt;It strikes a middle ground that developers and testers can compromise on&lt;/h3&gt;
&lt;p&gt;Software quality should not be the sole responsibility of testers; quality should be baked into every activity when building software. One of the challenges in implementing this concept, however, is that there has traditionally been a segmentation in tools and languages used by team members with different functions. Developers use one tool; testers use another. It&amp;rsquo;s difficult to encourage developers to test and testers to code in this environment, and many testing tools only further encourage this divide. A developer can&amp;rsquo;t use a tool like JMeter for anything but testing, so the incentive to invest the effort in learning it is lower.&lt;/p&gt;
&lt;p&gt;k6 bridges the gap by bringing testing concepts and features to an environment and language that developers are already spending their time in. Javascript is useful for more than just writing load testing scripts, and k6 works well with any IDE or text editor. A frictionless developer experience is central to the k6 philosophy.&lt;/p&gt;
&lt;h3 id="its-easier-to-collaborate-on-scripts"&gt;It&amp;rsquo;s easier to collaborate on scripts&lt;/h3&gt;
&lt;p&gt;Once you&amp;rsquo;ve convinced both devs and testers to contribute to load testing scripts, how do you keep track of changes? How do you manage scripts that multiple people are working on at the same time?
With tests as code, the easiest way is to just use versioning tools like Git, the way you probably are already using for your application code. Again, no new framework or processes to learn here.
k6&amp;rsquo;s conciseness and portability really proves to be an advantage in collaboration situations. To illustrate this, let&amp;rsquo;s consider a simple test script that contains a few things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A GET request to &lt;a href="https://test.k6.io"&gt;our test site&lt;/a&gt;, &lt;code&gt;https://test.k6.io&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A transaction that calls this request &lt;code&gt;01_Home&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A check to fail non-HTTP 200 responses or responses that don&amp;rsquo;t have the text &lt;code&gt;Collection of simple web-pages suitable for load testing&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Variable think time&lt;/li&gt;
&lt;li&gt;We&amp;rsquo;ll just run that as a single user, for a single iteration. Here&amp;rsquo;s what that script looks like in k6:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;k6/http&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;sleep&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;check&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;k6&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;res&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;https://test.k6.io&amp;#39;&lt;/span&gt;, {&lt;span style="color:#a6e22e"&gt;tags&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;01_Home&amp;#39;&lt;/span&gt; }});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;check&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;is status 200&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;) =&amp;gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;status&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;text verification&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;) =&amp;gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;body&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;includes&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Collection of simple web-pages suitable for load testing&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;sleep&lt;/span&gt;(Math.&lt;span style="color:#a6e22e"&gt;random&lt;/span&gt;() &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can track JMeter scripts on Git, too. Here&amp;rsquo;s what the same script looks like in JMeter:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;jmeterTestPlan&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;version=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;1.2&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;properties=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;5.0&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;jmeter=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;5.3&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;hashTree&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;TestPlan&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;guiclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TestPlanGui&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TestPlan&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testname=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Test Plan&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;enabled=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TestPlan.comments&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TestPlan.functional_mode&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;false&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TestPlan.tearDown_on_shutdown&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;true&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TestPlan.serialize_threadgroups&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;false&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TestPlan.user_defined_variables&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;elementType=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Arguments&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;guiclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ArgumentsPanel&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Arguments&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testname=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;User Defined Variables&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;enabled=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;collectionProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Arguments.arguments&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TestPlan.user_define_classpath&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/TestPlan&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;hashTree&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;ThreadGroup&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;guiclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ThreadGroupGui&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ThreadGroup&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testname=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Thread Group&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;enabled=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ThreadGroup.on_sample_error&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;continue&lt;span style="color:#f92672"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ThreadGroup.main_controller&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;elementType=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;LoopController&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;guiclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;LoopControlPanel&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;LoopController&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testname=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Loop Controller&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;enabled=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;LoopController.continue_forever&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;false&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;LoopController.loops&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;1&lt;span style="color:#f92672"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ThreadGroup.num_threads&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;1&lt;span style="color:#f92672"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ThreadGroup.ramp_time&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;1&lt;span style="color:#f92672"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ThreadGroup.scheduler&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;false&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ThreadGroup.duration&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ThreadGroup.delay&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ThreadGroup.same_user_on_next_iteration&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;true&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/ThreadGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;hashTree&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;TransactionController&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;guiclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TransactionControllerGui&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TransactionController&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testname=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;01_Home&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;enabled=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TransactionController.includeTimers&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;false&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;TransactionController.parent&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;true&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/TransactionController&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;hashTree&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;HTTPSamplerProxy&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;guiclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HttpTestSampleGui&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSamplerProxy&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testname=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTP Request&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;enabled=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPsampler.Arguments&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;elementType=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Arguments&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;guiclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPArgumentsPanel&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Arguments&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testname=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;User Defined Variables&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;enabled=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;collectionProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Arguments.arguments&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.domain&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;test.k6.io&lt;span style="color:#f92672"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.port&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.protocol&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;https&lt;span style="color:#f92672"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.contentEncoding&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.path&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.method&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;GET&lt;span style="color:#f92672"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.follow_redirects&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;true&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.auto_redirects&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;false&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.use_keepalive&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;true&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.DO_MULTIPART_POST&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;false&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.embedded_url_re&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.connect_timeout&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;HTTPSampler.response_timeout&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/HTTPSamplerProxy&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;hashTree&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;ResponseAssertion&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;guiclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;AssertionGui&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ResponseAssertion&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testname=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Response Assertion&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;enabled=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;collectionProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Asserion.test_strings&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;-745788246&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;Collection of simple web-pages suitable for load testing&lt;span style="color:#f92672"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/collectionProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Assertion.custom_message&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Assertion.test_field&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;Assertion.response_data&lt;span style="color:#f92672"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;boolProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Assertion.assume_success&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;false&lt;span style="color:#f92672"&gt;&amp;lt;/boolProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;intProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Assertion.test_type&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;16&lt;span style="color:#f92672"&gt;&amp;lt;/intProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/ResponseAssertion&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;hashTree/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/hashTree&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/hashTree&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;UniformRandomTimer&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;guiclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;UniformRandomTimerGui&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testclass=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;UniformRandomTimer&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testname=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Uniform Random Timer&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;enabled=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ConstantTimer.delay&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;1000&lt;span style="color:#f92672"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;RandomTimer.range&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;4000&lt;span style="color:#f92672"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/UniformRandomTimer&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;hashTree/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/hashTree&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/hashTree&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/hashTree&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/jmeterTestPlan&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which one is easier to understand? If you had to modify the script to add a request, which format would you choose to do it in?&lt;/p&gt;
&lt;p&gt;Scripting in XML makes merge conflicts more likely and breaking changes in automation pipelines way more difficult to pinpoint.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve collaborated with others on JMeter scripts in the past, and we always opened up scripts in the GUI. It&amp;rsquo;s way easier to spot changes there - but that also created some new issues.&lt;/p&gt;
&lt;h2 id="when-you-want-something-easy-to-maintain"&gt;When you want something easy to maintain&lt;/h2&gt;
&lt;h3 id="versioning-for-load-testing"&gt;Versioning for load testing&lt;/h3&gt;
&lt;p&gt;When ramping up load tests to more than one load generator, keeping track of the versions of necessary components ensures that one load generator&amp;rsquo;s traffic is the same as another&amp;rsquo;s. The value of reducing variables in scientific experiments holds true for load testing.&lt;/p&gt;
&lt;p&gt;With k6, you just need to worry about the version of k6 and the script. No other dependencies are required. If you&amp;rsquo;re using plugins, you&amp;rsquo;d need to track those too, but as mentioned previously, plugins in k6 aren&amp;rsquo;t as necessary as they are in some other tools &amp;ndash; and k6 is available as a Docker image to reduce those issues.&lt;/p&gt;
&lt;p&gt;With something like JMeter, there are more levels to consider. There&amp;rsquo;s the version of JMeter itself, Java, versions of plugins, and then the script. Every new layer introduces more changes for incompatibilities. In previous projets I&amp;rsquo;ve worked on, someone would inevitably try out a new plugin and forget to discuss it with the team, and anyone who tried to open that script in their copy of JMeter would see this error:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/10-jmeterpluginerror.png" alt="This is the error that JMeter throws when you attempt to open a test plan that includes a plugin you don’t have installed locally" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;The error means there&amp;rsquo;s a plugin that the script uses that JMeter doesn&amp;rsquo;t recognize, but depending on the plugin, it&amp;rsquo;s not always this easy to pinpoint which one (it was the &lt;code&gt;Ultimate Thread Group&lt;/code&gt; in this case).
You don&amp;rsquo;t want that happening in the middle of your load test because you forgot to add a plugin to some of your load generators!&lt;/p&gt;
&lt;h3 id="its-easier-to-link-test-code-with-application-code"&gt;It&amp;rsquo;s easier to link test code with application code&lt;/h3&gt;
&lt;p&gt;If your application code is in Javascript, k6 is a shoo-in as a load testing tool. You could build tests that are tightly integrated with application code by importing objects and having your tests interacting with them directly. This approach would reduce a lot of time spent in refactoring test scripts when objects are changed.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re already using VS Code, k6 even has a &lt;a href="https://marketplace.visualstudio.com/items?itemName=k6.k6"&gt;VS Code plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="test-as-code-gives-you-control"&gt;Test as code gives you control&lt;/h3&gt;
&lt;p&gt;Having your scripts be pure code reduces ambiguities in that you&amp;rsquo;re not limited by poor UI design or bugs in third-party plugins. k6 scripts are Typescript-typed, so most IDEs support autocompletion while you&amp;rsquo;re scripting - the code equivalent of helpful tooltips, except way more universal.
k6 scripts give you the freedom to import and use JS libraries, so you can build on code others have already written. While k6 is not NodeJS, there are even &lt;a href="https://k6.io/docs/using-k6/modules#bundling-node-modules"&gt;some NodeJS packages&lt;/a&gt; that you can bundle for use with your scripts.&lt;/p&gt;
&lt;h3 id="no-external-dependencies"&gt;No external dependencies&lt;/h3&gt;
&lt;p&gt;k6 doesn&amp;rsquo;t require NodeJS or anything else to run, which also reduces the likelihood of bugs that might affect your scripts. For example, since JMeter runs on Java, it is also dependent on Java. When Java receives a new version, that often requires a JMeter update as well. JMeter versions understandably lag a bit behind Java versions as developers refactor code, but this gap can lead to potential security issues in a previous version of Java that may remain unpatched in the meantime.&lt;/p&gt;
&lt;p&gt;With k6, development can proceed independently of any third-party component, so major issues can be addressed more easily.&lt;/p&gt;
&lt;h1 id="comparison-table-jmeter-vs-k6"&gt;Comparison table: JMeter vs k6&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;JMeter&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;k6&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Written in&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scripting language&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited: some Java (Groovy, Beanshell, etc)&lt;/td&gt;
&lt;td&gt;Javascript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Protocols&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supports most protocols via plugins (native support for HTTP/1.1, SOAP, FTP, JDBC, LDAP, MOM via JMS, SMTP, POP3, IMAP, shell scripts, TCP, Java objects)&lt;/td&gt;
&lt;td&gt;Supports fewer, modern protocols natively (HTTP/1.1, HTTP/2, WebSockets, gRPC)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;External dependencies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resource utilization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://k6.io/blog/static/b4075246f21af514c7a1554d1406b337/d5e13/RPSvMemory.png"&gt;Poor&lt;/a&gt;; One load generator can simulate a few thousand virtual users&lt;/td&gt;
&lt;td&gt;&lt;a href="https://k6.io/blog/static/b4075246f21af514c7a1554d1406b337/d5e13/RPSvMemory.png"&gt;Very good&lt;/a&gt;; One load generator can simulate tens of thousands of virtual users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JVM heap memory must be set&lt;/td&gt;
&lt;td&gt;Uses load generator memory natively&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Threading model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1 Thread: 1 Virtual User; Slower performance, higher resource cost&lt;/td&gt;
&lt;td&gt;1 Goroutine: 1 Virtual User; Faster performance, lower resource cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ease of scripting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GUI-driven, with code blocks&lt;/td&gt;
&lt;td&gt;code-driven; VSCode plugin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Test-level thresholds&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No, individual request only&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Script format&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;XML&lt;/td&gt;
&lt;td&gt;javascript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Collaboration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Difficult to work on simultaneously; tester-friendly; need the GUI app to edit&lt;/td&gt;
&lt;td&gt;Developer-friendly, easy to version; Javascript format promotes collaboration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maintenance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Verbose scripts; XML format is difficult to read&lt;/td&gt;
&lt;td&gt;More concise scripts; JavaScript is easy to read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Community&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Since 1998; Many third-party tutorials; Extensive documentation; No central community&lt;/td&gt;
&lt;td&gt;Since 2017; Extensive documentation; Fewer third-party tutorials; &lt;a href="https://community.k6.io/"&gt;Official community&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Plugin support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Requires plugins for many features, but there are lots of plugins available&lt;/td&gt;
&lt;td&gt;Most features are natively supported, but plugin support is new and availability is sparse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Native distributed load generation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No (Premium only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pre-generated reports&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Default and custom HTML reports; logging via listeners&lt;/td&gt;
&lt;td&gt;No built-in pre-generated reports; integration with analytics tools with third-party dashboards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Website&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://jmeter.apache.org/"&gt;jmeter.apache.org&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://k6.io"&gt;k6.io&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Source Code&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/apache/jmeter"&gt;Link&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/loadimpact/k6"&gt;Link&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;The best advice, when attempting to choose a load testing tool, is to do a proof of concept with the most promising candidates. Some features or bugs may prove more or less important when used in an actual testing cycle. However, don&amp;rsquo;t put too much weight on comparisons of the load test &lt;em&gt;results&lt;/em&gt; from two different tools - each tool records metrics differently, and it&amp;rsquo;s more meaningful to compare results against previous runs with the same tool. When switching tools, reestablish a baseline in the new tool each time.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a summary that might help you decide between JMeter and k6.&lt;/p&gt;
&lt;h2 id="both-tools-do-well-at"&gt;Both tools do well at:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Generating protocol-level load on an application server by scripting complex user flows&lt;/li&gt;
&lt;li&gt;Realistic scripting with the use of dynamic think time, test data generation and reuse, and customizable workload models&lt;/li&gt;
&lt;li&gt;Documentation of features and consistency of releases&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="neither-tool-supports"&gt;Neither tool supports:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Generating browser-level load and interacting with DOM elements, especially for SPA&lt;/li&gt;
&lt;li&gt;Detailed results analysis (JMeter has pre-generated HTML reports and listeners, but they are far from ideal). Users should expect to integrate results with databases and data visualization software.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="jmeter-is-best-for"&gt;JMeter is best for:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;traditional testing teams&lt;/li&gt;
&lt;li&gt;those looking for a GUI-driven testing tool with tons of third-party tutorials and extensive protocol support&lt;/li&gt;
&lt;li&gt;previous users of commercial tools like LoadRunner and NeoLoad&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="k6-is-best-for"&gt;k6 is best for:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;collaborative, cross-functional engineering teams where testing spans acrosss multiple roles&lt;/li&gt;
&lt;li&gt;those looking for a simple and lightweight, yet fully-featured load testing tool&lt;/li&gt;
&lt;li&gt;teams looking to integrate testing into existing development workflows and CI/CD pipelines&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Load testing scripting tools are by no means the most important consideration for the success of load testing. Knowing &lt;em&gt;why&lt;/em&gt; you&amp;rsquo;re testing, what the requirements are, and understanding and communicating results are all arguably more important. The right tool will enable you to address those concerns while providing as little friction as possible. There&amp;rsquo;s no unequivocal &amp;ldquo;best&amp;rdquo; tool; there&amp;rsquo;s only the right tool for &lt;em&gt;your&lt;/em&gt; project and context.&lt;/p&gt;</description></item><item><title>Week of Testing Wrap-up: My thoughts on k6 as a load testing tool</title><link>https://nicolevanderhoeven.com/blog/20201217-week-of-testing-07/</link><pubDate>Thu, 17 Dec 2020 15:29:57 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20201217-week-of-testing-07/</guid><description>&lt;p&gt;I decided to make a final wrap-up video for my &amp;ldquo;Week of Testing&amp;rdquo; with k6&amp;hellip; ok, so it&amp;rsquo;s actually three weeks later now, but I wanted to explore k6 a little bit more before I gave my opinion on it.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/zVjLBp543E4?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;And here&amp;rsquo;s the audio version:&lt;/p&gt;
&lt;iframe src="https://open.spotify.com/embed-podcast/episode/0YgYqrPpEzEMSZIloeiQtC" width="100%" height="232" frameborder="0" allowtransparency="true" allow="encrypted-media"&gt;&lt;/iframe&gt;
&lt;p&gt;Thank you, k6, for being awesome enough to agree to this video series before knowing what I&amp;rsquo;d say. Gotta love a company that welcomes transparency and feedback.&lt;/p&gt;</description></item><item><title>Cuándo JMeter no alcanza: Pruebas de carga simulando navegadores</title><link>https://nicolevanderhoeven.com/blog/20201216-cuando-jmeter-no-alcanza/</link><pubDate>Wed, 16 Dec 2020 18:18:23 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20201216-cuando-jmeter-no-alcanza/</guid><description>&lt;p&gt;Aquí está el video de mi presentación en JMeter Scripting Day, un evento organizado por &lt;a href="https://jmeterenespanol.org/"&gt;JMeter en Español&lt;/a&gt; el 31 de Oktubre, 2020.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/1KB8e2Ld08M?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Y la versión audio:&lt;/p&gt;
&lt;iframe src="https://open.spotify.com/embed-podcast/episode/1f17kzrbYmOxk8e65JBTQH" width="100%" height="232" frameborder="0" allowtransparency="true" allow="encrypted-media"&gt;&lt;/iframe&gt;
&lt;h2 id="introducción"&gt;Introducción&lt;/h2&gt;
&lt;p&gt;Hola a todos! Yo soy Nicole van der Hoeven, y soy performance tester. JMeter es una de mis herramientas favoritas porque es gratis, simple, y por muchos casos hace exactamente lo que quiero y no más. Sin embargo, como performers es parte de nuestro trabajo elegir la herramienta adecuada para cada proyecto, y hay que admitir que hay situaciones en que JMeter simplemente no es suficiente.&lt;/p&gt;
&lt;h2 id="amazon---ui--dev-tools"&gt;Amazon - UI + Dev Tools&lt;/h2&gt;
&lt;p&gt;Esto es el sitio web de Amazon.com. Tengo abierta la pantalla de Chrome Developer Tools, que me muestra las solicitudes (o requests) que componen la página. Cuándo vamos a la página, el navegador (Chrome en este caso) envia estas solicitudes para nosotros, pero eso occure en el fondo. Un usuario normal no las ve.&lt;/p&gt;
&lt;h2 id="jmeter---creando-un-script"&gt;JMeter - Creando un script&lt;/h2&gt;
&lt;p&gt;Lo que JMeter hace es grabar estas solicitudes y replicarlas. Aqui vemos una ejecución de un usuario virtual de un script en JMeter. Cada solicitud tiene la respuesta y el tiempo de respuesta. Pero eso no nos da una idea completa del rendimiento de la aplicación. ¿Por qué?&lt;/p&gt;
&lt;p&gt;Por que JMeter, como otras herramientas de nivel protocolo, tiene unas limitaciónes. La primera es que si hay javascript o otros script que deben estar ejecutado por el navegador, JMeter no los ejecuta. JMeter solo los descarga. El tiempo de respuesta mide la descarga, no la duración de la ejecución. Entonces, siempre habrá una diferencia entre los tiempos de respuesta en una prueba de JMeter y los tiempos de respuesta en práctica.&lt;/p&gt;
&lt;p&gt;A veces esta diferencia no es tan importante. Pero hay más y más aplicaciones hoy en día que se componen principalmente de estos javascript. Por esas aplicaciones, simplemente no es posible hacer un script en JMeter porque la mayoría de la lógica de la aplicación occure en el navegador, no en el servidor.&lt;/p&gt;
&lt;h2 id="flood-challenge"&gt;Flood Challenge&lt;/h2&gt;
&lt;p&gt;La segunda razón es que el aumento de la seguridad de aplicaciones conduce a solicitudes más complejas que incluyen parámetros dinámicos. Estos parámetros hacen que sea más difícil para un intermediario lanzar un ataque, pero también hacen que sea más difícil para nosotros scripters, porque tenemos que extraer información desde la última respuesta y ponerla en la próxima solicitud. Es posible, pero es la pesadilla de cada performance tester.&lt;/p&gt;
&lt;p&gt;Podemos verlo en la aplicación de muestra &lt;a href="https://challenge.flood.io"&gt;Flood Challenge&lt;/a&gt;. Ya no trabajo para Flood, pero todavía es un buen ejemplo.&lt;/p&gt;
&lt;h2 id="correlación-en-jmeter---flood-challenge-script"&gt;Correlación en JMeter - Flood challenge script&lt;/h2&gt;
&lt;p&gt;Esto es mi script en JMeter, y vemos que hay muchos parámetros que he tenido que correlacionar. La solicitud para simular hacer clic en el botón &amp;ldquo;Start&amp;rdquo; necesita los parámetros authenticity token, step ID, y step number, que son dinámicos. El contenido de los parámetros cambian cada vez que usamos esta aplicación.&lt;/p&gt;
&lt;h2 id="la-experiencia-del-usuario"&gt;La experiencia del usuario&lt;/h2&gt;
&lt;p&gt;La tercera razón es que JMeter tampoco mide la verdadera experiencia del usuario. Solo mide la duración de la comunicación entre el navegador y el servidor, pero no mide cosas como la representación de elementos en la página web, ni el efecto de un script que dura mucho tiempo para terminar.&lt;/p&gt;
&lt;p&gt;Eso es importante porque estas cosas afectan significativamente la experiencia del usuario. De hecho, Steve Souders, un conocido el la industría de performance, dice que &lt;a href="https://rigor.com/blog/80-90-of-load-times-are-spent-on-the-front-end-start-there/#:~:text=Start%20there.,-Written%20by%20Craig&amp;amp;text=Last%20month%2C%20Steve%20Souders%2C%20Google's,is%20spent%20on%20the%20frontend"&gt;hasta 90% del tiempo de respuesta&lt;/a&gt; que experimenta el usuario está en la interfaz. Con este numero podemos estar ciertos que una prueba con una herramienta de nivel protocolo no va a poder encapsular el rendimiento final de una aplicación.&lt;/p&gt;
&lt;h2 id="developer-tools---lighthouse"&gt;Developer Tools - Lighthouse&lt;/h2&gt;
&lt;p&gt;Entonces, ¿qué podemos hacer?&lt;/p&gt;
&lt;p&gt;Lo más fácil es intentar de medir la interfaz durante una prueba de cargas. Mientras ejecutamos una prueba con JMeter, podemos ir manualmente a la aplicación web en Chrome para usar Developer Tools. Podemos usar la pestaña Lighthouse, que nos da más métricos del perspectivo del usuario y sugerencias para mejorar el rendimiento.&lt;/p&gt;
&lt;h2 id="webpagetest"&gt;WebPageTest&lt;/h2&gt;
&lt;p&gt;También uso &lt;a href="https://webpagetest.org"&gt;WebPageTest&lt;/a&gt; a veces. Eso tiene más opciones para ejecutar la prueba automáticamente varias veces desde un lugar que puedo elegir. Aún podemos elegir un dispositivo para simular la experiencia de un usuario en un iPad, por ejemplo.&lt;/p&gt;
&lt;h2 id="herramientas-alternativas-para-pruebas-de-carga"&gt;Herramientas alternativas para pruebas de carga&lt;/h2&gt;
&lt;p&gt;Tambien podemos elegir herramientas alternativas para ejecutar nuestras pruebas de carga. Lo que tienen en común es que fueron diseñadas para pruebas de automatización, y utilizan un navegador real.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.selenium.dev/"&gt;Selenium&lt;/a&gt; es probablemente la más popular de esas. Selenium WebDriver en particular. Es compatible con Ruby, Java, Python, C# y Javascript. El problema con Selenium es que puede ser muy pesada. En una machina probablamente podemos ejecutar cinco usuarios de Selenium, más o menos. Eso es importante si estamos tratando de simular miles de usuarios.&lt;/p&gt;
&lt;p&gt;Hay muchas herramientas basadas en Javascript que también podemos usar. Hay varias framework que se utilizan para adaptar Javascript y nodeJS.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Puppeteer fue desarollado por Google. Tricentis Flood también ha diseñado Element que utiliza Puppeteer, pero con un enfoque en el rendimiento.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/microsoft/playwright"&gt;Playwright&lt;/a&gt; es una creación de Microsoft.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://jest.io"&gt;Jest&lt;/a&gt; fue desarrollado por Facebook&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mocha es otro framework que es la base para &lt;a href="https://cypress.io"&gt;Cypress&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Todos esas herramientas son open source y gratis. También hay alternativas propietarias, pero prefiero las soluciones open source porque en la mayoría de casos hacen la misma cosa y se actualizan con más frecuencia.&lt;/p&gt;
&lt;h2 id="element-script"&gt;Element script&lt;/h2&gt;
&lt;p&gt;Esto es un ejemplo de la misma acción, hacer clic en el botón Start en la aplicación Flood Challenge.&lt;/p&gt;
&lt;p&gt;Otra ventaja de simulando navegadores en vez de simulando las solicitudes es que es más simple crear un script. No tenemos que saber cada parámetro. Solo tenemos que describir lo que queremos que cada usuario virtual haga.&lt;/p&gt;
&lt;p&gt;Podemos ejecutar scripts usando estas herramientas al mismo tiempo que un script de &lt;a href="https://jmeter.apache.org"&gt;JMeter&lt;/a&gt; o &lt;a href="https://gatling.io"&gt;Gatling&lt;/a&gt; o lo que sea, y también tenemos la opción de reemplazar los script de protocolo con estas.&lt;/p&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Para resumir, JMeter y otras herramientas de nivel protocolo tiene algunas limitaciones.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;No ejecutan scripts del lado del navegador&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Pueden ser más complicado correlacionar parámetros dinámicos&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No miden la experiencia final de un usuario&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Para solucionar estos problemas, podemos complementar pruebas de carga tradicionales, de nivel protocolo, como JMeter, con herramientas simulando navegadores. De este modo podremos tener una comprensión más completa del rendimiento total de la aplicación.&lt;/p&gt;
&lt;p&gt;Bueno, se acabó el tiempo, entonces los dejo aquí. Gracias por escuchar, y me disculpo por mi español. Gracias a todos!&lt;/p&gt;</description></item><item><title>Week of Testing: Day 4 - Load profiles on k6</title><link>https://nicolevanderhoeven.com/blog/20201127-week-of-testing-4/</link><pubDate>Fri, 27 Nov 2020 19:54:06 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20201127-week-of-testing-4/</guid><description>&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/jDmMmc75RRM?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;k6 has a cool feature where even if you start a load test locally via the CLI, you can still stream the results to k6 Cloud. It&amp;rsquo;s an interesting compromise between debugging a test locally (and therefore not paying for cloud infrastructure) and sharing results for load tests run on the cloud. It worked seamlessly, too.&lt;/p&gt;
&lt;p&gt;I also wanted to see how to recreate a specific load profile that I commonly use - the stepped load profile. In JMeter, I typically do this with a plugin - the jp@gc Ultimate Thread Group is my thread group of choice. So, I created it in JMeter (I love that it shows a little image of it as well, while you&amp;rsquo;re building it) and then attempted to recreate it in k6.&lt;/p&gt;
&lt;p&gt;I definitely had to look at the k6 documentation for this. I used the &lt;code&gt;constant-vus&lt;/code&gt; executor for this, but k6 has &lt;a href="https://k6.io/docs/using-k6/scenarios#executors"&gt;several other executors&lt;/a&gt; to choose from, and it worked as well as I had hoped.&lt;/p&gt;
&lt;p&gt;So far, my experience with k6 has been positive. Things are well-documented, and they just work out of the box. No plugins necessary.&lt;/p&gt;</description></item><item><title>Week of Testing: Day 3 - Running a load test locally using k6</title><link>https://nicolevanderhoeven.com/blog/20201126-week-of-testing-3/</link><pubDate>Thu, 26 Nov 2020 19:31:33 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20201126-week-of-testing-3/</guid><description>&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/y5tteMKZUqk?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;rsquo;ve had my fun playing around with k6 Cloud, the SaaS component. For Day 3, I thought it was time to jump into the heart of k6: k6 the &lt;a href="https://github.com/loadimpact/k6"&gt;open source load testing tool&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First impressions: logging was a little sparser than I expect, coming from having used load testing tools that just do this for me automatically. I think one of the first things I&amp;rsquo;ll do with k6 is to create my own little &amp;ldquo;load testing starting script&amp;rdquo; that I&amp;rsquo;ll always use, with all of the appropriate logging already set up.&lt;/p&gt;
&lt;p&gt;Otherwise, I was really impressed with how quickly it installed. If you scrub over to the timestamp &lt;a href="https://www.youtube.com/watch?v=y5tteMKZUqk&amp;amp;ab_channel=k6&amp;amp;ts=106"&gt;1:46&lt;/a&gt; in the video, you&amp;rsquo;ll hear that I was actually expecting to have to speed up the installation process while editing to save time, but the installation actually finished before I could say that I was going to do so. By my count that was 7 seconds between hitting enter in my terminal and the download finishing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7 seconds&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I can&amp;rsquo;t help but compare that to &lt;a href="https://jmeter.apache.org/"&gt;JMeter&lt;/a&gt;. JMeter is honestly probably my go-to load testing right now&amp;ndash; it&amp;rsquo;s not good for absolutely everything, but it&amp;rsquo;s the tool that I reach for when I &amp;ldquo;just want to test this one thing&amp;rdquo;. I&amp;rsquo;ve used it for years, and it&amp;rsquo;s the tool that I know the most. But one of the issues with JMeter is that there&amp;rsquo;s so much to do before it&amp;rsquo;s actually usable.&lt;/p&gt;
&lt;p&gt;Before you even open JMeter, you need to install Java, and when I first started in load testing, I spent a long time wrestling with getting setting the Java environment variable in Windows before my computer would even recognize that Java was installed. Then you need to install JMeter&amp;ndash; but any JMeter tester will tell you that there are some plugins that you just can&amp;rsquo;t do without, and that really you should always install. That&amp;rsquo;s why there are so many &amp;ldquo;best plugins in JMeter&amp;rdquo; lists (&lt;a href="https://nicolevanderhoeven.com/blog/20200414-aaf11"&gt;here&amp;rsquo;s my top 3&lt;/a&gt;)&amp;hellip; because most of them are necessary, but you wouldn&amp;rsquo;t know that if you&amp;rsquo;re new to JMeter.&lt;/p&gt;
&lt;p&gt;The fact that k6 starts up in 7 seconds is&amp;hellip; shockingly good.&lt;/p&gt;</description></item><item><title>Ask a Flooder 18: How do I load test video streaming with JMeter?</title><link>https://nicolevanderhoeven.com/blog/20200722-aaf18/</link><pubDate>Wed, 22 Jul 2020 22:49:15 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200722-aaf18/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/ask-a-flooder-18-how-do-i-load-test-video-streaming-with-jmeter-video"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/ask-a-flooder-18-how-do-i-load-test-video-streaming-with-jmeter-video"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this video, I answer the question: &amp;ldquo;How do I load test video streaming with JMeter?&amp;rdquo;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/Q00briuogto?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;Or listen to the audio version here:&lt;/p&gt;
&lt;iframe src="https://open.spotify.com/embed-podcast/episode/69F5lmOeFfEJr6ZgVWFGOu" width="100%" height="232" frameborder="0" allowtransparency="true" allow="encrypted-media"&gt;&lt;/iframe&gt;
&lt;h2 id="http-live-streaming-hls-and-performance"&gt;HTTP Live Streaming (HLS) and performance&lt;/h2&gt;
&lt;p&gt;One of the most popular protocols for video streaming is &lt;a href="https://developer.apple.com/streaming/examples/"&gt;HTTP Live Streaming&lt;/a&gt;, or HLS, and that&amp;rsquo;s what I&amp;rsquo;m going to show you today. An HLS video ends with the [file extension .m3u8‍](&lt;a href="https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8%5D(https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8)"&gt;https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8](https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8)&lt;/a&gt;. According to the HLS protocol, when a video is streamed, the first request sent must be a manifest. A manifest is sometimes called a playlist, and it is a list of all the chunks or parts that make up the video. Then, each chunk is downloaded.&lt;/p&gt;
&lt;p&gt;To assess the performance of a video stream, we still want the response time of the manifest, the chunks, and the whole video. However, there are many more metrics that are important in video streaming which aren&amp;rsquo;t captured by just the response time. For example, how do you determine whether a video was played smoothly or if it stopped to buffer? A video that keeps pausing might just drive a user away, and it&amp;rsquo;s difficult to tell whether that is happening just from the response time.&lt;/p&gt;
&lt;h2 id="how-to-load-test-video-streaming-with-jmeter"&gt;How to load test video streaming with JMeter&lt;/h2&gt;
&lt;h3 id="downloading-and-installing-the-ubik-video-streaming-plugin"&gt;Downloading and installing the Ubik Video Streaming plugin&lt;/h3&gt;
&lt;p&gt;Luckily, there&amp;rsquo;s a plugin for that, created by a company called Ubik Ingénierie. The &lt;a href="https://ubikloadpack.com/"&gt;Ubik Load Pack&lt;/a&gt; is a set of enterprise-grade plugins for JMeter. One of those plugins is a &lt;a href="https://ubikloadpack.com/video-streaming-performance.php"&gt;Video Streaming Plugin&lt;/a&gt;, and it happens to be a really easy way to get started with video streaming. This is a paid plugin, but you can &lt;a href="https://ubikloadpack.com/video-streaming-performance.php#formulaire"&gt;sign up for a free 11-day trial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Once you do that, you&amp;rsquo;ll get an email from Ubik with a link to download the bundle. Go to lib/ext and then copy this .jar file into the same directory on your JMeter installation. Start up JMeter, and it&amp;rsquo;ll ask you for the license file. Browse to the license file in the bundle you downloaded. JMeter will restart.&lt;/p&gt;
&lt;h3 id="using-the-jmeter-plugin-in-your-load-testing-script"&gt;Using the JMeter plugin in your load testing script&lt;/h3&gt;
&lt;p&gt;Now let&amp;rsquo;s start creating the Test Plan. Create a Thread group, and then right click on the thread group, go to Add &amp;gt; Sampler and then select the &amp;ldquo;ULP Video Streaming sampler&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Click on the sampler and then paste in the URL to the HLS file that you&amp;rsquo;d like to test. This should end in a .m3u8. This plugin supports several protocols for video streaming, but we can just leave it at auto and it&amp;rsquo;ll automatically detect which one it is.&lt;/p&gt;
&lt;p&gt;In Play Options, you can choose whether to play the entire video or just a part of it, or even whether you want to include the video subtitles in your test.&lt;/p&gt;
&lt;p&gt;This Network Options panel is fantastic because it allows you to limit your network speed. Slow networks, like mobile networks, really affect user experience, so it&amp;rsquo;s really important to take this into account when running load tests. You might even use a parameter here and do something like throttle to 3G speeds for 80% of your traffic, and leave it on Auto 20% of the time. But I&amp;rsquo;ll just leave this blank for now.&lt;/p&gt;
&lt;p&gt;Next, let&amp;rsquo;s add a View Results Tree listener. Then, let&amp;rsquo;s run the script once, just to see if it works.&lt;/p&gt;
&lt;p&gt;As you can see, we can see the manifest retrieved first, and then all the chunks. We didn&amp;rsquo;t get any errors, so let&amp;rsquo;s run this as a load test. We can disable this listener because it just consumes extra resources on our load generator.&lt;/p&gt;
&lt;h3 id="ramping-up-your-load-test-on-flood"&gt;Ramping up your load test on Flood&lt;/h3&gt;
&lt;p&gt;To ramp this up into a load test, we&amp;rsquo;ll have to go into Thread Group and change these settings. Ideally, we want to be able to change these values from the Flood UI later so we don&amp;rsquo;t have to go into the script whenever we change them, so I&amp;rsquo;ll type in these Flood-specific properties. I&amp;rsquo;ll leave a link in the description about these properties. I&amp;rsquo;ll also set it to run Forever so that we can change the duration and the video will just keep playing to fill that duration.&lt;/p&gt;
&lt;p&gt;To capture some of Ubik&amp;rsquo;s cool metrics, let&amp;rsquo;s add a Simple Data Writer listener here and write the results to a CSV file. On Flood, all flood results are stored on /data/flood/results, so we&amp;rsquo;ll add an output.csv file in that directory that we can download after the test.&lt;/p&gt;
&lt;p&gt;So that&amp;rsquo;s our script! Now we&amp;rsquo;ll have to include the plugin and related files so that Flood can access them as well.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s go back to the bundle we downloaded and go to the bin folder to look for &lt;a href="http://user.properties/"&gt;user.properties&lt;/a&gt;. Let&amp;rsquo;s open that up, and we&amp;rsquo;ll change the license path to &lt;code&gt;/data/flood/files&lt;/code&gt;, which is the directory that Flood saves files we upload to. To preserve this directory structure, we&amp;rsquo;ll compress just the lib and bin folders.&lt;/p&gt;
&lt;p&gt;On Flood, we&amp;rsquo;ll start a new stream here and upload three things: the jmx script, the license, and the compressed archive of the lib and bin folders from the bundle.&lt;/p&gt;
&lt;p&gt;Then we&amp;rsquo;ll go through the rest of the process here, setting the test parameters. Time to launch the test!&lt;/p&gt;
&lt;h3 id="analyzing-video-streaming-load-test-results"&gt;Analyzing video streaming load test results&lt;/h3&gt;
&lt;p&gt;Flood shows you results of your load test while it&amp;rsquo;s running as well as after the test. You can see metrics like concurrency, network throughput, transaction rate, and response time for the test. You can also see these metrics for each individual transaction, including the video or sampler as a whole, the manifest, and the chunks.&lt;/p&gt;
&lt;p&gt;To see the CSV that our script generated, we can download the Archived Results from a flood.&lt;/p&gt;
&lt;p&gt;In JMeter, click on Tools &amp;gt; Generate Report and fill in the fields, selecting the output.csv from the flood&amp;rsquo;s Archived Results, JMeter&amp;rsquo;s &lt;a href="http://user.properties"&gt;user.properties&lt;/a&gt; file, and then an output directory for the report.&lt;/p&gt;
&lt;p&gt;Ubik&amp;rsquo;s plugin creates a few custom graphs in the HTML report:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Buffer fill in Millis&lt;/li&gt;
&lt;li&gt;Lag ratio in percentage&lt;/li&gt;
&lt;li&gt;Lag ratio without buffer fill in percentage&lt;/li&gt;
&lt;li&gt;Lag time in Millis&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Using Ubik&amp;rsquo;s Video Streaming plugin is an easy and thorough way to load test video streaming with JMeter, and I highly recommend it. I used an HLS video to demonstrate it, but this plugin supports several protocols:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HLS&lt;/li&gt;
&lt;li&gt;Mpeg DASH&lt;/li&gt;
&lt;li&gt;Smooth&lt;/li&gt;
&lt;li&gt;Adobe HDS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more information, read Ubik&amp;rsquo;s tutorial on how to use their plugin with Flood &lt;a href="https://www.flood.io/blog/running-a-video-streaming-performance-test-using-flood-io-and-ubikloadpack"&gt;here&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Ask a Flooder 13: How do you do mobile load testing?</title><link>https://nicolevanderhoeven.com/blog/20200428-aaf13/</link><pubDate>Tue, 28 Apr 2020 23:21:08 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200428-aaf13/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/ask-a-flooder-13-how-do-you-do-mobile-load-testing"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/ask-a-flooder-13-how-do-you-do-mobile-load-testing"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;How do you load test a native mobile app? I discuss the general approach to mobile load testing, what a device farm is, and why a device farm isn&amp;rsquo;t necessary for load testing. I also discuss the best mobile load testing tools to use.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/y_rRu0cDey4?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Or listen to the audio version here:&lt;/p&gt;
&lt;iframe src="https://open.spotify.com/embed-podcast/episode/2fevtJd7pPIAUDkMpdnzkV" width="100%" height="232" frameborder="0" allowtransparency="true" allow="encrypted-media"&gt;&lt;/iframe&gt;
&lt;p&gt;Hi everyone, Nicole here again, back with another Ask a Flooder, and today&amp;rsquo;s question is:&lt;/p&gt;
&lt;h2 id="how-do-you-do-mobile-load-testing"&gt;How do you do mobile load testing?&lt;/h2&gt;
&lt;p&gt;Now, this question came from a customer who was under the misconception that in order to do mobile load testing, they would need to use what we call a device farm. A device farm is a collection of different kinds of mobile phones. You would ideally have the most popular makes of mobile phones (the hardware models) and the operating systems and system versions. You can imagine that this can very easily get a little out of hand to coordinate because of fragmentation. There are just so many devices out on the market, and then there&amp;rsquo;s the question of how you actually generate the load from that.&lt;/p&gt;
&lt;p&gt;You would somehow need some sort of test automation script that was running and then coordinate os that they all run at the same time, and you would use that as a load test. As you can imagine, whether you use real devices or simulators, this kind of thing would get complicated and expensive very quickly. But the good news is that it&amp;rsquo;s unnecessary if it&amp;rsquo;s load testing that you want to do. Now I say that because, for functional testing or compatibility testing, you ARE going to want to test your application on a variety of different browsers. But with load testing, you&amp;rsquo;re really more concerned about the back end part of the equation. You want to generate load on your application servers. In reality, most mobile apps work by sending API requests to that server, usually by some sort of restful API. Luckily, API load testing has been around for a while, so we do have some industry-tested ways to run this.&lt;/p&gt;
&lt;h2 id="what-are-the-best-tools-for-api-load-testing"&gt;What are the best tools for API load testing?&lt;/h2&gt;
&lt;p&gt;Essentially, you&amp;rsquo;re going to want to test protocol-level tools. That means that you don&amp;rsquo;t want to be using browser-level tools in which you&amp;rsquo;re using scripts to drive a full browser. All you really need is something that sends requests on the protocol-level. That&amp;rsquo;s great because it&amp;rsquo;s actually way more efficient.&lt;/p&gt;
&lt;p&gt;You have two really good open-source options for this, JMeter and Gatling. I&amp;rsquo;ve already gone a little bit into the differences between these two in my previous video on how you choose a tool for load testing, which I will leave a link to.&lt;/p&gt;
&lt;p&gt;And here are some other resources that will help you get started with mobile load testing. I also have another video about how to record network traffic from a native mobile app on JMeter, which sounds a little complicated, but I promise it&amp;rsquo;s not. In that video, I go over the steps with you, and I&amp;rsquo;m actually doing it in real-time with you as well. I show you the screen recording from my mobile and from JMeter on my laptop, so you can always pause and watch it at your own pace.&lt;/p&gt;
&lt;p&gt;The second thing is that I already wrote a blog post, which is sort of a guide for mobile load testing, which goes into the steps into way more detail than I can here.&lt;/p&gt;
&lt;p&gt;And lastly, I have written blog posts about two real-life examples of mobile load testing. The first one was the Iowa Caucus Reporter app. I ran through it from the workload modeling to the scripting and then the actual execution. More recently, I also wrote about the Robinhood app. Be sure to check out the links in the description to find out more.&lt;/p&gt;
&lt;p&gt;Until next time, happy flooding!&lt;/p&gt;</description></item><item><title>Browser-based load testing in 2020</title><link>https://nicolevanderhoeven.com/blog/20200423-browser-based-load-testing-2020/</link><pubDate>Thu, 23 Apr 2020 16:48:09 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200423-browser-based-load-testing-2020/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/browser-based-load-testing-in-2020"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/browser-based-load-testing-in-2020"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We &lt;a href="https://flood.io/blog/level-up-your-load-testing-with-browser-level-users"&gt;first announced&lt;/a&gt; our open-source browser-based load testing tool based on Puppeteer, &lt;a href="https://element.flood.io/"&gt;Flood Element&lt;/a&gt;, in February 2018. Despite our decision to make it an entirely separate tool from Flood, we&amp;rsquo;ve enjoyed using it so much as a team that several of us have written about it:&lt;/p&gt;
&lt;p&gt;Tim Koopmans: &lt;a href="https://flood.io/blog/load-testing-for-devops-with-browser-level-users-blu"&gt;Load testing for DevOps&amp;hellip; with Browser Level Users (BLU)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Kevin Dunne: &lt;a href="https://flood.io/blog/a-new-approach-to-load-testing-with-browser-level-users"&gt;A new approach to load testing with browser level users&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;me: &lt;a href="https://flood.io/blog/prepare-for-viral-videos-with-flood-element"&gt;Prepare for viral videos with Flood Element&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Lachie Cox: &lt;a href="https://flood.io/blog/why-you-should-load-test-with-browsers"&gt;Why should you load test with real browsers?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;our friend Eduardo Riol, as translated by Antonio Jimenez: &lt;a href="https://flood.io/blog/selenium-vs-puppeteer-for-test-automation-is-a-new-leader-emerging"&gt;Puppeteer vs. Selenium for test automation: is a new leader emerging?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Clearly, we&amp;rsquo;re huge fans of load testing a web application with real browsers. But does the wider software testing industry share that sentiment?&lt;/p&gt;
&lt;h2 id="browser-based-load-testing-in-2020"&gt;Browser-based load testing in 2020&lt;/h2&gt;
&lt;p&gt;Browser-level load testing is still pretty new, and there aren&amp;rsquo;t too many providers offering it right now. Luckily, we just so happen to have access to a database of load tests run on Flood since 2013. Here&amp;rsquo;s a bar chart visualizing data we&amp;rsquo;ve collected about the load testing tools flooders have used (we support Selenium, JMeter, Gatling, and Element).&lt;/p&gt;
&lt;h3 id="load-tests-executed-on-flood-over-time-grouped-by-load-testing-tool"&gt;Load tests executed on Flood over time, grouped by load testing tool&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200423-01.png" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h3 id="browser-level-load-testing-is-increasing-in-popularity"&gt;Browser-level load testing is increasing in popularity&lt;/h3&gt;
&lt;h4 id="in-2020-almost-35-of-the-load-tests-run-on-flood-are-browser-based-load-tests"&gt;In 2020, almost 35% of the load tests run on Flood are browser-based load tests.&lt;/h4&gt;
&lt;p&gt;While the total number of load tests run across all tools increased across the board, the percentage of tests that utilized Selenium and Element, as compared to JMeter and Gatling, has also increased from 2018. Both Selenium and Element are browser-based load testing tools.&lt;/p&gt;
&lt;p&gt;By contrast, JMeter, a protocol-level load testing tool which previously enjoyed a 70% share of the traffic on Flood, now accounts for only a bit over 50% of usage. JMeter&amp;rsquo;s share of the protocol-level pie is higher than Gatling&amp;rsquo;s, but the percentage of usage for both tools appears to be contracting when compared to that of browser-based tools.&lt;/p&gt;
&lt;h3 id="element-use-is-increasing-faster-than-selenium-use"&gt;Element use is increasing faster than Selenium use&lt;/h3&gt;
&lt;p&gt;Despite the fact that Selenium has been around longer, &lt;strong&gt;25% of all floods today are run using Element&lt;/strong&gt;. This is a significant increase in just two years, and one that bodes well for the future. While we&amp;rsquo;re still fans of Selenium and still support it, one reason we see for the dominance of Element in today&amp;rsquo;s market is resource efficiency.&lt;/p&gt;
&lt;p&gt;In our baseline tests, we&amp;rsquo;ve seen that Element can run from 20-50 users per Flood node (an &lt;a href="https://aws.amazon.com/blogs/aws/m5-the-next-generation-of-general-purpose-ec2-instances/"&gt;AWS m5.xlarge instance&lt;/a&gt;), whereas Selenium can only run up to 5. This leads to some significant cost savings, as running the same number of users with Element requires fewer load generators than with Selenium.&lt;/p&gt;
&lt;p&gt;Another reason might be the fact that Element uses Puppeteer in the background. Puppeteer, developed by Google, understandably shines when driving Google Chrome (and recently, Firefox). Puppeteer load testing is growing in popularity due to the wealth of metrics it has access to.&lt;/p&gt;
&lt;h2 id="how-browser-based-load-testing-works"&gt;How browser-based load testing works&lt;/h2&gt;
&lt;p&gt;Traditional load testing is done on the protocol level by sending messages directly to the web server. These messages are sent without simulating the application interface, and the responses that are received from the server are not visualized, either. &amp;ldquo;Users&amp;rdquo; in protocol-level load testing scripts are actually threads, with each one sending a list of messages at predefined intervals, and we refer to these users as Protocol-Level Users (PLU). JMeter and Gatling use PLU to generate load.&lt;/p&gt;
&lt;p&gt;The screenshot below shows what one request for a single action might look like in a JMeter test plan.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200423-02.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;em&gt;Example of an HTTP request with parameters on JMeter&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In browser-based load testing, real browser instances are opened on load generators, and the load testing tool plays the part of a real user in navigating the web application using the GUI. We refer to the virtual users in browser-based load testing as Browser-Level Users (BLU).&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of the same action in the JMeter example above, but this time in an Element test script:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;step&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Step 1&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;browser&lt;/span&gt; =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Click Start button
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;startButton&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;findElement&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;.btn-default&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;startButton&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This version simply describes the button to be found and clicked, whereas the protocol-level version needs to be more precise in what exactly is passed to the server.&lt;/p&gt;
&lt;p&gt;Both types of load testing tools can apply the same load on an application (as long as it supports both methods— see the next section). The main difference is in how the load is generated.&lt;/p&gt;
&lt;p&gt;A protocol-level script will contain instructions on which messages to send, which protocols to use, which headers to include, and other information that a typical end-user would not see.&lt;/p&gt;
&lt;p&gt;A browser-level script will contain instructions on how to &lt;em&gt;interact&lt;/em&gt; with the application: which buttons to click, what to type in text fields, which links to follow, and other on-screen elements that an end-user would be familiar with. This leads us to one of the big advantages of browser-based load testing.&lt;/p&gt;
&lt;h2 id="pros-and-cons-of-browser-based-load-testing"&gt;Pros and cons of browser-based load testing&lt;/h2&gt;
&lt;h3 id="pros"&gt;Pros&lt;/h3&gt;
&lt;h4 id="simple-scripting-or-no-scripting-at-all"&gt;Simple scripting— or no scripting at all&lt;/h4&gt;
&lt;p&gt;Protocol-level tools require in-depth knowledge about how an application works, what format it expects requests to be in, and how it responds. On the browser-level, you don&amp;rsquo;t need to know any of that. When scripting a login process, for instance, you just need to tell the script to type a username and password in the right fields and then click Log In. The script doesn&amp;rsquo;t need to know that the form submits an encrypted request using the Auth0 API (something you&amp;rsquo;d need to know for a protocol-level script).&lt;/p&gt;
&lt;p&gt;In some cases, you might be able to get away with using something like our &lt;a href="https://flood.io/blog/record-load-tests-in-flood-element-using-qtest-explorer"&gt;qTest Explorer plugin&lt;/a&gt; to record a business process, generating a script without any scripting at all. Even when you have to write or modify the script, though, it&amp;rsquo;s a lot less intimidating than most protocol-level scripts.&lt;/p&gt;
&lt;p&gt;They&amp;rsquo;re also easier to troubleshoot. In addition to opening a real browser instance on your computer when you run a script locally, Element can also display this information on the console (shown here on iTerm):&lt;/p&gt;
&lt;p&gt;‍&lt;img src="https://nicolevanderhoeven.com/assets/20200423-03.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;em&gt;Screenshots upon execution on Element using iTerm&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;‍This allows you to understand what&amp;rsquo;s going on in the script and in the application, letting you detect bottlenecks faster.&lt;/p&gt;
&lt;h4 id="reduced-test-complexity"&gt;Reduced test complexity&lt;/h4&gt;
&lt;p&gt;The streamlined requirements for scripting lead to a straightforward test. There&amp;rsquo;s no chance of getting request parameters or values wrong.&lt;/p&gt;
&lt;h4 id="ability-to-test-entire-stack-from-the-user-perspective"&gt;Ability to test entire stack from the user perspective&lt;/h4&gt;
&lt;p&gt;Unlike testing APIs, you don&amp;rsquo;t need to decide which server you want to hit or make sure you have the appropriate requests to hit all the servers. A browser-level test script interacts with page elements like a real user would, so all underlying application servers are tested. Pair this with &lt;a href="https://guides.flood.io/infrastructure/demand-infrastructure/advantages-of-testing-in-the-cloud"&gt;cloud-based infrastructure on Flood&lt;/a&gt;, and you&amp;rsquo;ve got a compact package for testing your application.&lt;/p&gt;
&lt;h4 id="capable-of-testing-any-user-behavior"&gt;Capable of testing any user behavior&lt;/h4&gt;
&lt;p&gt;Protocol-level load test tools struggle with some types of applications, such as single-page apps (SPAs), where a lot of the processing is done on the client side. Browser-level load testing tools shine here, because scripted interactions for these apps are no different for SPAs than other web apps.&lt;/p&gt;
&lt;h4 id="record-network-and-user-interaction-times-for-front-end-optimization"&gt;Record network and user interaction times for front-end optimization&lt;/h4&gt;
&lt;p&gt;Browser-level tools show you response times from the user&amp;rsquo;s perspective: how long after a user clicks the log in button does the user see his or her account balance? This metric is a practical one that may differ wildly from the traditional response times that a protocol-level tool reports. Measuring real user experience is a great value add for your test.&lt;/p&gt;
&lt;h4 id="easier-to-maintain"&gt;Easier to maintain&lt;/h4&gt;
&lt;p&gt;Lower script complexity means that a browser-based test script is more resilient to changes in the codebase. A change in the underlying requests sent will not require a change in the test script, making it perfect for regression testing.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also easier to pass on to other members of the team due to high readability. Here&amp;rsquo;s an example of how to select a value from a dropdown menu in Element:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;selectByValue&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;#challenger_age&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;34&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s easy to see that the script is looking for an element with the ID &amp;ldquo;challenger_age&amp;rdquo; and selecting the value &amp;ldquo;34&amp;rdquo;. This step could correspond to dozens of requests that need to be scripted if testing on the protocol level, which makes those scripts harder to understand without a proper handover.&lt;/p&gt;
&lt;h3 id="cons"&gt;Cons&lt;/h3&gt;
&lt;p&gt;Browser-based load testing tools have a higher CPU and memory footprint than protocol-based tools. Test scripts in JMeter and Gatling send messages to and record responses from a server without really needing to parse responses. By contrast, browser-based tools parse the server response in order to access the Domain Object Model (DOM) elements on the page.&lt;/p&gt;
&lt;p&gt;Using real browsers might be closer to the real user experience, but it also takes its toll on node resources. It is possible to run in headless mode, where browsers are started &amp;ldquo;invisibly&amp;rdquo; without actually graphically rendering them. However, even then, a browser-level tool can run fewer concurrent users on a node than a protocol-level tool.&lt;/p&gt;
&lt;h2 id="best-tools-and-applications-for-browser-based-load-testing"&gt;Best tools and applications for browser-based load testing&lt;/h2&gt;
&lt;p&gt;While other commercial tools exist for this, we&amp;rsquo;re partial to open source tools at Flood.&lt;/p&gt;
&lt;h3 id="selenium"&gt;Selenium&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200423-04.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Selenium load testing is appealing because Selenium is already well-known for test automation and functional testing, and a lot of companies already have full test suites in Selenium. The possibility of reusing those resources and just running them at scale as load tests is, by far, the most compelling reason to use Selenium.&lt;/p&gt;
&lt;h3 id="puppeteer"&gt;Puppeteer&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200423-05.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Google&amp;rsquo;s just getting started with Puppeteer, and the amount of metrics it exposes is exciting: it seems like anything in Chrome Developer Tools can be accessed by Puppeteer. Imagine running a load test on ONE tool that gives you statistics about back-end performance (response times, the effect of bandwidth restrictions, resources returning errors) AND front-end performance (client-side script console logs, render times, time to first paint, etc). It&amp;rsquo;s hard to imagine a future where this ISN&amp;rsquo;T a valuable tool in the performance arsenal.&lt;/p&gt;
&lt;p&gt;Under Puppeteer, of course, is &lt;a href="https://element.flood.io/"&gt;Element&lt;/a&gt;— our load-flavored version of Puppeteer.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200423-06.png" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="is-protocol-based-load-testing-dead"&gt;Is protocol-based load testing dead?&lt;/h2&gt;
&lt;p&gt;No. Testing on the protocol-level may have its drawbacks, but it&amp;rsquo;s popular for a reason. If you&amp;rsquo;re testing mobile apps or API endpoints, protocol-level testing tools allow you to focus on hitting what you want to test and only what you want to test. Sometimes you don&amp;rsquo;t want to test the whole stack. It really depends on your test scenarios.&lt;/p&gt;
&lt;p&gt;Plus, protocol-level tools tend to be really resource efficient. We&amp;rsquo;ve been able to easily run about 1000 users per Flood node with JMeter and Gatling, easily outstripping browser-level tools. It makes sense, since JMeter and Gatling don&amp;rsquo;t need to start browser instances to generate load.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s significantly cheaper to generate very high loads with protocol-level tools. This efficiency makes protocol-level tools a good choice for high concurrency load testing and especially stress testing.&lt;/p&gt;
&lt;h2 id="what-are-we-doing-to-support-blu"&gt;What are we doing to support BLU?&lt;/h2&gt;
&lt;p&gt;Clearly, our usage metrics show that browser-based load testing is on the rise, and we&amp;rsquo;re planning to ramp up our offerings in this area while also maintaining support for protocol-level tools. Here&amp;rsquo;s what you can look forward to from us:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New releases
&lt;ul&gt;
&lt;li&gt;We just released &lt;a href="https://element.flood.io/docs/1.0/install"&gt;version 1.2.3 of Element&lt;/a&gt; a few weeks ago, which addresses some bugs and improve stability for certain actions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Dedicated Element team
&lt;ul&gt;
&lt;li&gt;We&amp;rsquo;ve put together a team of developers who will be focusing on improving Element exclusively. Despite Element being an open source tool, we&amp;rsquo;re putting our own resources behind it to improve it faster.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Partnering with consulting services
&lt;ul&gt;
&lt;li&gt;It can be difficult to get started on a new tool, and Element is no exception. While we provide a load testing platform to run Element scripts, some companies want help to create the scripts in the first place. To this end, we&amp;rsquo;ve partnered with expert consultants who have already been using Element with great success: &lt;a href="https://foulkconsulting.com/"&gt;Foulk Consulting&lt;/a&gt; and &lt;a href="https://www.planittesting.com/"&gt;Planit Testing&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;When choosing a performance testing tool, it&amp;rsquo;s important to consider the advantages and disadvantages of protocol-level and browser-level testing tools. We think both types of tools deserve to be in a solid performance and load testing strategy. They can also be used in tandem in a hybrid load testing approach, improving overall application performance and scalability.&lt;/p&gt;
&lt;p&gt;In 2018, we predicted that testing web-based applications with real browsers would increase in popularity, so we&amp;rsquo;re thrilled to see our theory validated in 2020. Browser-based load testing is increasing in usage, and our open source tool, Element, is leading the charge. It&amp;rsquo;s exciting to be at the forefront of this revolution, and we intend to increase support for load testing with real browsers even more this year.&lt;/p&gt;</description></item><item><title>Ask a Flooder 11: What are the best JMeter plugins?</title><link>https://nicolevanderhoeven.com/blog/20200414-aaf11/</link><pubDate>Tue, 14 Apr 2020 19:47:53 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200414-aaf11/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/ask-a-flooder-11-what-are-the-best-jmeter-plugins"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/ask-a-flooder-11-what-are-the-best-jmeter-plugins"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this video, I talk about how to install the JMeter Plugin Manager as well as other plugins, what the best JMeter plugins are, and why you need them. JMeter is an open-source load testing tool that is already robust, but there are some fantastic plugins that have been developed for it that you might want to use in your next load test.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/eYyLoH-FQrk?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Audio version here:&lt;/p&gt;
&lt;iframe src="https://open.spotify.com/embed-podcast/episode/36GUgvf17bRwmJxg8CNkvy" width="100%" height="232" frameborder="0" allowtransparency="true" allow="encrypted-media"&gt;&lt;/iframe&gt;
&lt;p&gt;Hi everyone, Nicole here, back again for another Ask a Flooder, and I hope everybody is staying alert, not anxious, during these crazy times. In today&amp;rsquo;s Ask a Flooder, our customer asks: &amp;ldquo;What are the best JMeter plugins?&amp;rdquo;&lt;/p&gt;
&lt;h2 id="what-is-a-jmeter-plugin"&gt;What is a JMeter plugin?&lt;/h2&gt;
&lt;p&gt;So first, I want to talk about what a JMeter plugin is and how you can actually install one. Apache JMeter is a really great, robust load testing that is one of my personal favorites. There are still some things that could be done better or could be extended, and the great thing about being an open-source tool is that anybody, pretty much, can just jump in and develop these plugins for JMeter to extend functionality, so that it supports more protocols or to customize load profiles in a way that is easier. We already have &lt;a href="https://flood.io/blog/jmeter-plugins-the-top-10-plugins-and-how-they-help"&gt;a blog post on this&lt;/a&gt;, and I will leave a link to that article as well in the description because it goes into a lot more detail. However, I still want to give you my personal top 3 JMeter plugins.&lt;/p&gt;
&lt;h2 id="how-do-you-install-a-jmeter-plugin"&gt;How do you install a JMeter plugin?&lt;/h2&gt;
&lt;p&gt;You can install a plugin for JMeter in two ways.&lt;/p&gt;
&lt;p&gt;One is to download it from &lt;a href="https://jmeter-plugins.org/"&gt;JMeter Plugins&lt;/a&gt;, which I will give you a link to, and then you paste that into either the lib — it&amp;rsquo;s usually in the lib folder, but it could be in the ext (extensions) folder. Each plugin is going to differ as to what you need to copy into what folder, but that&amp;rsquo;s why I prefer the second method, which is the &lt;a href="https://jmeter-plugins.org/wiki/PluginsManager/"&gt;Plugin Manager&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Plugin Manager is a plugin itself, so you will initially need to do that copy and pasting of the jar file. Once you have the JMeter Plugin Manager installed, downloading and installing a plugin is as simple as choosing which ones you want and then clicking install. JMeter restarts, and that&amp;rsquo;s pretty much it. So I do recommend that the Plugin Manager be the first plugin that you install. But that&amp;rsquo;s still not my top 3 favorite - that&amp;rsquo;s just an optional step.&lt;/p&gt;
&lt;h2 id="what-are-the-top-3-jmeter-plugins"&gt;What are the top 3 JMeter plugins?&lt;/h2&gt;
&lt;h3 id="custom-thread-groups"&gt;Custom Thread Groups&lt;/h3&gt;
&lt;p&gt;Now for the actual plugins. My #1 favorite is the Custom Thread Groups. See, with JMeter, you get the standard default thread group, and all that does is it asks you how many users you want to run, how many loops, the duration, and the ramp-up. That&amp;rsquo;s it. So that&amp;rsquo;s good for a lot of uses, but it doesn&amp;rsquo;t really help you in cases where maybe you want to plan a spike test, and you want to make sure that all the users have fully ramped up and gotten to a certain point, and then all hit the server at once. Or maybe you want to do a step load. Previously I&amp;rsquo;ve discussed stress testing and how a step load can be useful for that. In that case, the Thread Group doesn&amp;rsquo;t quite cut it because it only ramps up a user, and then it continues at the same level of load for the duration of the test.&lt;/p&gt;
&lt;p&gt;So, if you want any sort of variation in the middle (increasing users or decreasing), then you&amp;rsquo;re going to want something else.The Custom Thread Groups plugin has a lot of different types of thread groups. My favorite is the Ultimate One because you can probably do almost anything on that one. It also has the Stepping, Concurrency, Arrivals, and Free-Form Arrivals, so you have quite a few options.&lt;/p&gt;
&lt;h3 id="throughput-shaping-timer"&gt;Throughput Shaping Timer&lt;/h3&gt;
&lt;p&gt;Plugin #2 is the Throughput Shaping Timer. I love it because not a lot of load testing tools, even the proprietary ones, actually have this. This is really handy when you have a project where you&amp;rsquo;re given a requirement that isn&amp;rsquo;t in terms of the number of users; it&amp;rsquo;s in terms of hits per second, or requests per second, or something to do with the actual throughput of the test.&lt;/p&gt;
&lt;p&gt;The problem with that is that the throughput tends to change, so you can&amp;rsquo;t actually take as a given that it&amp;rsquo;ll remain constant for the duration of the test. Things like response time or latency are going to affect that throughput. For instance, when you have one user or one thread that&amp;rsquo;s running, and it sends a request and receives the response back in one second, you can&amp;rsquo;t necessarily say that that&amp;rsquo;s going to be the same when there are a thousand threads doing the same thing. The server&amp;rsquo;s under more load, so maybe it&amp;rsquo;ll take five seconds instead of one second— but that&amp;rsquo;s already changed your throughput. Before, one thread was doing one request per second, and now it&amp;rsquo;s doing one request every five seconds.&lt;/p&gt;
&lt;p&gt;So it can get a little complicated, and the Throughput Shaping Timer is one of my favorites because it promises to solve all that. The Throughput Shaping Timer dynamically changes the think time, so at the beginning of a test, for instance, when there are no response time issues and requests are being returned really quickly, it might increase the think time so that it slows down your load test. So you&amp;rsquo;re not going over that throughput that you wanted to maintain. And then later on in the test, when all the users are ramped up, then it&amp;rsquo;ll decrease the think time that it uses. So it&amp;rsquo;s great because you just have this consistent throughput throughout your test. It&amp;rsquo;s a really intelligent way to test.&lt;/p&gt;
&lt;p&gt;I do want to say, though, that you do also want to play around with this a bit and make sure you understand how this works. One page could have several requests in it, and you&amp;rsquo;ll want to take that into consideration when you&amp;rsquo;re choosing what to set in that timer.&lt;/p&gt;
&lt;h3 id="http2-request-sampler"&gt;HTTP/2 Request Sampler&lt;/h3&gt;
&lt;p&gt;My #3 is the HTTP/2 Sampler. If you don&amp;rsquo;t know what HTTP/2 is, it&amp;rsquo;s an upgraded or next-generation protocol to the normal HTTP that we already use. The HTTP/2 protocol is supposed to be faster and more efficient, so more and more web apps are switching to it because of that.&lt;/p&gt;
&lt;p&gt;The problem is that JMeter&amp;rsquo;s HTTP request sampler is only really for HTTP sites, so the HTTP/2 sampler is an upgraded version of the HTTP sampler. It&amp;rsquo;s really easy to use. The experience is pretty much going to be the same for you, but in the background, it uses the faster HTTP/2 protocol rather than the slower one.&lt;/p&gt;
&lt;p&gt;My colleague, Jason Rizio, actually &lt;a href="https://flood.io/blog/jmeter-tutorial-http2-test"&gt;wrote a whole blog post about this&lt;/a&gt;, so if you want to learn more, I will put a link in the description.&lt;/p&gt;
&lt;p&gt;I hope that answered your question, and until next time, happy flooding!&lt;/p&gt;</description></item><item><title>Ask a Flooder 09: What are the best tools for load testing?</title><link>https://nicolevanderhoeven.com/blog/20200331-aaf09/</link><pubDate>Tue, 31 Mar 2020 20:35:36 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200331-aaf09/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/ask-a-flooder-09-what-are-the-best-tools-for-load-testing-video"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/ask-a-flooder-09-what-are-the-best-tools-for-load-testing-video"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;One of our most commonly-asked questions is: &amp;ldquo;What are the best tools for load testing?&amp;rdquo; The answer will depend on a few things: your reason for load testing, the application you want to test, what kind of load testing you want to carry out, your team&amp;rsquo;s experience with scripting, and how many virtual users you want to run.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: In this video, I say that traditional load testing tools can&amp;rsquo;t simulate requests that are triggered by interactions on the client-side. This isn&amp;rsquo;t technically true: if you know what the requests are, you can build those requests manually on a protocol-level tool (like JMeter or Gatling). However, this takes more work compared to browser-level tools that just do this natively.&lt;/em&gt;
‍
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/I5Wo6x2OoZU?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;Transcript:&lt;/p&gt;
&lt;p&gt;Hi everyone, Nicole back again with another Ask a Flooder, and this time I&amp;rsquo;m tackling one of the questions we get asked A LOT, which is:&lt;/p&gt;
&lt;h2 id="what-are-the-best-tools-for-load-testing"&gt;What are the best tools for load testing?&lt;/h2&gt;
&lt;h3 id="why-open-source-load-testing-tools-are-awesome"&gt;Why open-source load testing tools are awesome&lt;/h3&gt;
&lt;p&gt;Now, I want to preface this by saying that we really love open-source tools here at Flood, because 1) they&amp;rsquo;re really pretty full-fledged these days. You don&amp;rsquo;t have to make any compromises on features, and, in fact, some of these open-source tools have more features than some newer load testing tools just because they&amp;rsquo;ve been out longer. And secondly, they have large communities. Because they&amp;rsquo;re open-source, lots of people are using it, and lots of people are developing for it. So there are lots of plugins normally, and they support any kind of protocol that you can think of. And lastly, cost. It&amp;rsquo;s hard not to mention cost because it can be a really important factor depending on the budget of your project. And if you&amp;rsquo;re starting out as a load tester, I think that it might even be the best way to start with load testing, because you can take that knowledge with you and apply it to other projects and other companies regardless of the budget that they have.&lt;/p&gt;
&lt;h3 id="questions-to-ask-yourself-in-choosing-a-load-testing-tool"&gt;Questions to ask yourself in choosing a load testing tool&lt;/h3&gt;
&lt;h4 id="why-are-you-doing-load-testing"&gt;Why are you doing load testing?&lt;/h4&gt;
&lt;p&gt;I always advocate starting with WHY. Why are you actually load testing? Is there a particular production defect that you noticed that you&amp;rsquo;re trying to solve? Is there already a problem, or are you just preparing to launch? These are things that are going to inform the type of tool that you use because you might want to make sure that that tool supports the protocols that you need.&lt;/p&gt;
&lt;h4 id="what-are-you-load-testing"&gt;What are you load testing?&lt;/h4&gt;
&lt;p&gt;Secondly, what type of app are you testing? Because if you have a single-page app, where your end-user is interacting with the page and client-side scripts are running to make requests to servers, then that&amp;rsquo;s something that most traditional load testing tools aren&amp;rsquo;t going to be able to do.&lt;/p&gt;
&lt;p&gt;There are two general types of load testing tools: there&amp;rsquo;s browser-based, and there&amp;rsquo;s protocol-based. I&amp;rsquo;ll leave a link in the description talking about the differences between the two, but in general, if you want to go for browser-level testing, I would suggest Selenium and Element. Now, they&amp;rsquo;re both very good options. Selenium is probably the more robust in terms of automation of the two, but Element is better one in terms of efficiency because it was built with performance in mind. So Selenium&amp;rsquo;s automation-first and Element is really performance-first.&lt;/p&gt;
&lt;p&gt;Now, for protocol-level tools, you can&amp;rsquo;t go wrong with either JMeter or Gatling.&lt;/p&gt;
&lt;h4 id="what-experience-does-your-team-have-with-scripting"&gt;What experience does your team have with scripting?&lt;/h4&gt;
&lt;p&gt;Thirdly, what&amp;rsquo;s the level of technical expertise that your team has? I think it&amp;rsquo;s important to be realistic about what your team can do, given the amount of time that they have. So if you have a team that has never done load testing and has never done any scripting before, then I would suggest using our Test Builder or something similar. On Flood, we have a Test Builder that is really just an easy interface that actually runs JMeter under the hood, but it just kind of simplifies JMeter and boils it down to what are the URLs that you want to test. That is a really easy way to get started, and it&amp;rsquo;s also a great [way to run a] proof of concept. If you have some automation testers on your team that are trying to do the load testing, well, maybe you should stick to tools that they already use. So it might be easier for them to get up and running with either Selenium or Element rather than learning a new tool. And if you have developers on your team, you might consider Ruby JMeter rather than the vanilla JMeter because Ruby JMeter is a lot easier to deal with&amp;mdash; because you don&amp;rsquo;t have to deal with the XML files of a JMeter file (a normal JMX script). You can just plan out your load tests in Ruby. Or, Gatling is also a really good option because it allows you to write scripts in Scala. Scala is really really powerful, and you can create an entire framework with Gatling, which is also something to keep in mind.&lt;/p&gt;
&lt;h4 id="how-many-virtual-users-do-you-want-to-run-in-your-load-tests"&gt;How many virtual users do you want to run in your load tests?&lt;/h4&gt;
&lt;p&gt;And lastly, how many users do you want to simulate? Now protocol-level tools are going to really shine here because Element and Selenium both require a higher usage of resources on your load generators just because of the complexities involved in starting a browser instance, whereas protocol-level tools are just super efficient at sending these requests. So I would suggest that if you&amp;rsquo;re talking about thousands of users, I would use the protocol-level tools unless there&amp;rsquo;s a really good reason why that&amp;rsquo;s not going to give you the results that you&amp;rsquo;re looking for. Between JMeter and Gatling&amp;ndash; well, they&amp;rsquo;re both excellent tools, but Gatling has been shown to particularly be good for really high levels of usage. But JMeter is also a good alternative, and you can run thousands of users of JMeter without any problem.&lt;/p&gt;
&lt;h2 id="just-get-started"&gt;Just get started!&lt;/h2&gt;
&lt;p&gt;As always, I&amp;rsquo;d suggest just getting started. Pick whatever tool sounds like it might be the best for you, do a proof of concept on that one, and you can always try the other ones as well. On Flood, we don&amp;rsquo;t restrict you to just using one tool, so you can use one; you can use all four; you can run them at the same time if you want. It all depends on what you need for your testing.&lt;/p&gt;
&lt;p&gt;Till next time, happy flooding!&lt;/p&gt;</description></item><item><title>Ask a Flooder 06: How to record traffic from a mobile app with JMeter</title><link>https://nicolevanderhoeven.com/blog/20200319-aaf06/</link><pubDate>Thu, 19 Mar 2020 20:50:44 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200319-aaf06/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/ask-a-flooder-06-how-to-record-traffic-from-a-mobile-app-with-jmeter-video"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/ask-a-flooder-06-how-to-record-traffic-from-a-mobile-app-with-jmeter-video"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;How do you record the traffic from your native mobile app using Apache JMeter? In this video, I explain step-by-step how to begin load testing a native mobile app.&lt;/p&gt;
&lt;p&gt;‍&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/VVUyYF1VPlo?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;You might want to be doing this because you&amp;rsquo;re load testing a mobile app but either you don&amp;rsquo;t have access to your developers right now so they can&amp;rsquo;t help you with how the requests are made or what the requests are, or maybe you just want to verify what you&amp;rsquo;ve already been told. Either way, I&amp;rsquo;m going to show you how using my Android device (it&amp;rsquo;s a Samsung Galaxy Note 10+) and a Macbook Pro 13&amp;quot;. However, the same principles should apply to other mobile devices and laptops.&lt;/p&gt;
&lt;h2 id="step-1-download-and-install-the-mobile-app"&gt;Step 1: Download and install the mobile app&lt;/h2&gt;
&lt;p&gt;The first thing you&amp;rsquo;ll want to do is download and install the app. Now, if the app has already been released, then that&amp;rsquo;s no problem. You just go to the Google Play Store and download it. However, if it hasn&amp;rsquo;t been released yet and you&amp;rsquo;ve been given an APK file for the app, then you&amp;rsquo;ll have to tweak your settings a little bit in order to get your phone to allow you to download it.&lt;/p&gt;
&lt;p&gt;And I&amp;rsquo;m going to do this right with you. So go into Settings: pull down the little notification screen and hit the little gear icon, and you&amp;rsquo;ll see a bunch of settings there. Scroll down all the way to the bottom until you see About phone. Click that and then click Software Information. You&amp;rsquo;ll see the Build number halfway through the screen here&amp;ndash; and I know this is weird, but click on it seven times. You have to draw your pattern if you have one set up, but you&amp;rsquo;ll see here that it says Developer Mode has been enabled. That&amp;rsquo;s all you need to do; from now on you can install any APK, but be careful, because if you don&amp;rsquo;t trust the source, you know, they could do some damage to your phone.&lt;/p&gt;
&lt;h2 id="step-2-set-up-the-https-test-script-recorder-on-jmeter"&gt;Step 2: Set up the HTTP(S) Test Script Recorder on JMeter&lt;/h2&gt;
&lt;p&gt;The second step is setting up an HTTP recorder on JMeter. So let&amp;rsquo;s head over to our laptop. Make sure you&amp;rsquo;re connected to a wifi network. Now, this is a completely new JMeter test plan here. So just right-click on Test Plan and then hover over Add, and then you&amp;rsquo;re going to go down to Non-Test Elements. Select the HTTP(S) Test Script Recorder. You&amp;rsquo;ll see here that the port it uses is 8888. We&amp;rsquo;ll need that for later. Now right-click on the Test Script Recorder, hit Add, and then Listener. We&amp;rsquo;ll add a View Results Tree to be able to capture the results that we need later. Now we&amp;rsquo;ll click on the Test Plan - right-click - and then we&amp;rsquo;re going to Add a Thread Group. Now let&amp;rsquo;s right-click on the Thread Group and go to Add &amp;gt; Logic Controller &amp;gt; Recording Controller. This is where the requests that we&amp;rsquo;re going to send are going to be recorded, and we&amp;rsquo;ll see both the requests and the responses in View Results Tree.&lt;/p&gt;
&lt;h2 id="step-3-set-up-your-mobile-to-use-the-https-test-script-recorder-as-a-proxy"&gt;Step 3: Set up your mobile to use the HTTP(S) Test Script Recorder as a proxy&lt;/h2&gt;
&lt;p&gt;Now, the third step is to set up your mobile to use a proxy. So, back on the mobile, go back to Settings and hit Connections. And then click on Wifi. Now verify that the wifi network that you&amp;rsquo;re connected to on your mobile is the same one as the wifi network that you&amp;rsquo;re connected to on your laptop. If it&amp;rsquo;s the same, click the gear icon. And then hit Advanced all the way at the bottom. Now the Proxy settings are on the second option here so hit the down menu here and then hit Manual. Now, for the Proxy host name we&amp;rsquo;ll have to go back to the computer to see what our local IP address is.&lt;/p&gt;
&lt;p&gt;So, in order to do that, you just have to go to System Preferences. I&amp;rsquo;m doing it from the Apple menu here and from System Preferences, click on Network. And once you&amp;rsquo;ve selected the wifi network, hit Advanced, and then TCP/IP. So what you&amp;rsquo;re looking for will be this IPv4 Address. Now you&amp;rsquo;re going to type that into the Host name field on your mobile. So let me just type that in.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll note that this is actually a local IP address. It&amp;rsquo;s not your public IP address. Now for our proxy port, we&amp;rsquo;ll go and look at the laptop to see the Test Script Recorder Settings and it was 8888, so that&amp;rsquo;s what we&amp;rsquo;re going to put in here. All right. And then click on Save.&lt;/p&gt;
&lt;h2 id="step-4-start-recording"&gt;Step 4: Start recording&lt;/h2&gt;
&lt;p&gt;Step 4 is recording the traffic. Now, go back to your laptop on JMeter and click on the Test Script Recorder. Now we&amp;rsquo;re going to click on Start. It&amp;rsquo;ll come up with this popup box here and you can just click OK since we already trust the source. You&amp;rsquo;ll see this little popup here to confirm that we are recording traffic. Now let&amp;rsquo;s see if we&amp;rsquo;ve actually configured it correctly.&lt;/p&gt;
&lt;p&gt;On our mobiles, let&amp;rsquo;s go back and open the app that you want to use. So I&amp;rsquo;m going to be using the IowaReporterApp. I just did an article on this on The New Stack (link in the description below) about how I would load test the Iowa Caucus Reporter App. So that&amp;rsquo;s what I&amp;rsquo;m going to be using for this tutorial as well. So I&amp;rsquo;m going to open that (&amp;ldquo;getting ready to caucus&amp;rdquo;) and I don&amp;rsquo;t have a valid precinct ID so I&amp;rsquo;m just going to put flood.io and I&amp;rsquo;m going to click Login. So it&amp;rsquo;s telling me that the connection isn&amp;rsquo;t private. I don&amp;rsquo;t actually expect this to work, because the app has been taken down and I don&amp;rsquo;t have valid login credentials, but I&amp;rsquo;m still just going to go forward. So, Proceed. You might have to do this as well if your certificates haven&amp;rsquo;t been set up correctly.&lt;/p&gt;
&lt;p&gt;Okay, so now we&amp;rsquo;ve gotten this error here and it says, &amp;ldquo;Oops, something went wrong&amp;rdquo;. So it&amp;rsquo;s handy to know what it looks like on your mobile so that you can go into JMeter and see if that&amp;rsquo;s what you see as well.&lt;/p&gt;
&lt;p&gt;So on JMeter let&amp;rsquo;s go to the View Results Tree and it looks like Google Play tried to do a few things beforehand but what we&amp;rsquo;re really looking for is this IDP caucus thing. So, these are the requests that my phone made and these are the responses. So this is where we got the certificate error because it says &amp;ldquo;certificate unknown&amp;rdquo;. Now this is the actual request we sent for login. You can see the request here - the full request - and also the full response. Now, just to check we&amp;rsquo;ll make sure we got the same response in the body here on JMeter that we saw on our mobile phones.&lt;/p&gt;
&lt;p&gt;And here it is; it says &amp;ldquo;Oops!, something went wrong&amp;rdquo;. You can of course just search for this. So we&amp;rsquo;ll stop the recording now because we&amp;rsquo;ve confirmed that we&amp;rsquo;ve gotten what we wanted. So in the recording controller, we can see the requests that were recorded from our mobile app and the first one looks like it was one to Google so that&amp;rsquo;s not one we want. If we were doing this again, we could actually go into the Test Script Recorder, go into this Requests Filtering tab, and we could just filter out or exclude the domains that we don&amp;rsquo;t want to test, like Google. But this looks like the request that we were actually looking for. You&amp;rsquo;ll see the full request here with all the parameters and the values.&lt;/p&gt;
&lt;h2 id="whats-next"&gt;What&amp;rsquo;s next?&lt;/h2&gt;
&lt;p&gt;And that&amp;rsquo;s how you record traffic from a native mobile app on JMeter. From here, you can then play around with the request. Like we saw, there were a lot of dynamic values that were recorded in the request. We would probably want to correlate those and make sure that we&amp;rsquo;re doing those correctly. But this is a really great starting point for testing a mobile app.&lt;/p&gt;
&lt;p&gt;Till the next Ask a Flooder, happy Flooding!&lt;/p&gt;</description></item><item><title>Load Testing Lessons from the Iowa Caucus</title><link>https://nicolevanderhoeven.com/blog/20200306-load-testing-lessons/</link><pubDate>Fri, 06 Mar 2020 21:59:02 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200306-load-testing-lessons/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/load-testing-lessons-from-the-iowa-caucus"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/load-testing-lessons-from-the-iowa-caucus"&gt;here&lt;/a&gt; and &lt;a href="https://thenewstack.io/how-id-load-test-the-iowa-caucus-app/"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR? Here are the highlights in this article:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Shadow, Inc. created a mobile app for the Iowa Caucus in February 2020, and the app failed, causing reported results to be delayed.
The app reported different vote totals due to a system integration bug where the output was in a different format than what it needed to be.
Here are the steps to load testing a mobile app:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Test planning: Does the app require load testing? If yes, what is the underlying technology? How do we create a workload model?&lt;/li&gt;
&lt;li&gt;Scripting: Which mobile load testing tool should we use? How do we record traffic from a mobile device?&lt;/li&gt;
&lt;li&gt;Execution: What load test scenarios should we have? How can we scale up the load generated?
Conclusion: While the Iowa Reported App failure was not due entirely to load testing, load testing could have helped make it more robust.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;A company called Shadow, Inc. made headlines earlier this week when they developed an app to count and report votes during the Iowa Democratic Caucus in the US. This app, called IowaReporterApp, ended up failing on several fronts, resulting in a &lt;a href="https://www.nytimes.com/2020/02/06/upshot/iowa-caucuses-errors-results.html"&gt;days-long delay&lt;/a&gt; in publishing the total votes, during which manual methods had to be employed.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200306-01.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://twitter.com/ShadowIncHQ/status/1224773796307050497"&gt;@ShadowIncHQ on Twitter&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This delay led to significant criticism from the software testing industry as well as from the general public. Some developers raised questions about the &lt;a href="https://www.vice.com/en_us/article/3a8ajj/an-off-the-shelf-skeleton-project-experts-analyze-the-app-that-broke-iowa"&gt;code quality of the app&lt;/a&gt;. The app &lt;a href="https://twitter.com/iowademocrats/status/1225170253778444291"&gt;inaccurately reported voting totals&lt;/a&gt; that differed from the Democratic Party&amp;rsquo;s own manual reports, suggesting an issue with functional testing, particularly system integration testing. Shadow&amp;rsquo;s &lt;a href="https://thehill.com/policy/cybersecurity/481409-dhs-chief-says-offer-to-vet-iowa-caucus-app-was-declined"&gt;refusal to accept the Department of Homeland Security&amp;rsquo;s help with security testing&lt;/a&gt; also raised eyebrows. What was perhaps the most damning, though, was the question of &lt;a href="https://twitter.com/zeynep/status/1224545350364672001"&gt;whether such an app was necessary in the first place&lt;/a&gt;, when cheaper and more effective solutions existed.&lt;/p&gt;
&lt;p&gt;What I&amp;rsquo;m most interested in, however, are the load issues that the app faced. Let&amp;rsquo;s rewind a little to before the caucus. How would I have load tested an app like the IowaReporterApp?&lt;/p&gt;
&lt;h2 id="planning-a-mobile-load-testing"&gt;Planning a mobile load testing&lt;/h2&gt;
&lt;p&gt;One of the first things to figure out when planning a load test is whether a load test is even necessary.&lt;/p&gt;
&lt;h3 id="do-you-even-need-to-load-test-your-mobile-app"&gt;Do you even need to load test your mobile app?&lt;/h3&gt;
&lt;p&gt;To answer that, I had to find out more about the app.&lt;/p&gt;
&lt;p&gt;In the caucus, residents of Iowa who registered themselves as Democratic voters gathered to vote on whom they thought should be the party&amp;rsquo;s candidate for the presidential elections later this year.&lt;/p&gt;
&lt;p&gt;There are a few things that I think make this app the perfect candidate for load testing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;It was highly publicized.&lt;/strong&gt; The caucuses would always have been an event of international interest, but the hype surrounding electronic voting increased media attention on the caucus even further.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;It was mission-critical&lt;/strong&gt;. The precinct chairs would use the app as the primary device for capturing votes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;It needed to handle significant simultaneous load&lt;/strong&gt;. There were &lt;a href="https://en.wikipedia.org/wiki/2020_Iowa_Democratic_caucuses"&gt;over a thousand precinct caucuses&lt;/a&gt; organized, each with a precinct chair that would be using the app.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For these reasons, the answer is a resounding &amp;ldquo;Yes.&amp;rdquo;&lt;/p&gt;
&lt;h3 id="what-type-of-app-is-it"&gt;What type of app is it?&lt;/h3&gt;
&lt;p&gt;The best way to learn about an app is to ask its developers. In this case, I opted to do a little research on my own by &lt;a href="https://www.vice.com/en_us/article/z3b3g9/here-is-a-link-to-the-shadow-inc-app-that-blew-up-the-iowa-caucus"&gt;downloading the .apk file that Motherboard (Vice) made available&lt;/a&gt; and looking through the code myself.&lt;/p&gt;
&lt;p&gt;The app is a mobile-only app for Android and iOS devices, written mostly using Facebook&amp;rsquo;s React Native package. The primary function of the app was to sent the vote totals to Shadow Inc.&amp;rsquo;s &lt;a href="https://cloud.google.com/functions/?utm_source=google&amp;amp;utm_medium=cpc&amp;amp;utm_campaign=emea-nl-all-en-dr-bkws-all-all-trial-e-gcp-1008073&amp;amp;utm_content=text-ad-none-any-DEV_c-CRE_253510459861-ADGP_Hybrid+%7C+AW+SEM+%7C+BKWS+~+EXA_M:1_NL_EN_General_Cloud+Functions_ETL+Warehouse-KWID_43700019207359819-kwd-135583196912-userloc_9065312&amp;amp;utm_term=KW_google%20functions-ST_google+functions&amp;amp;ds_rl=1242853&amp;amp;ds_rl=1245734&amp;amp;ds_rl=1245734&amp;amp;gclid=EAIaIQobChMI6bKKzNi_5wIVk-R3Ch04HA1XEAAYASAAEgKTcPD_BwE"&gt;Google Cloud Functions&lt;/a&gt; server.&lt;/p&gt;
&lt;p&gt;The technology involved is worth noting because it can help determine which load testing tool to use. Since the Iowa Reporter App, like most mobile apps, sends requests to a RESTful API, JMeter or Gatling, both well-tested, robust, and open-source protocol-level tools with large user bases, were perfect for the job. I decided to go with JMeter, my personal tool of choice.&lt;/p&gt;
&lt;h3 id="how-do-we-create-a-workload-model"&gt;How do we create a workload model?&lt;/h3&gt;
&lt;p&gt;Now let&amp;rsquo;s talk about the workload model, which is a plan for how the load we generate needs to look. The objective here is to simulate the load that matches the expected real-life load as closely as possible.&lt;/p&gt;
&lt;p&gt;At this point, I would typically look at historical data to try to see the amount of load and the load profile. If I had metrics on the server traffic after previous releases of the app using something like Google Analytics or an APM tool, I would have used that data as a starting point for the workload model of this release. However, in this case, the app hadn&amp;rsquo;t been publicly released before, so I needed to make some educated guesses.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/2020_Iowa_Democratic_caucuses"&gt;According to Wikipedia&lt;/a&gt;, there were a total of 1,777 Iowa precinct caucuses, of which 99 were global satellite caucuses set up for Iowa residents temporarily not able to attend the local caucuses.&lt;/p&gt;
&lt;p&gt;In a Democratic caucus, the actual voting process generally takes &lt;a href="https://www.theguardian.com/us-news/2020/feb/03/iowa-caucuses-2020-elections-candidates"&gt;about two hours&lt;/a&gt;. In the Iowa caucus, the precinct chairs would have used the app twice - once for each round of voting. Around the end of the two hours, each chair&amp;rsquo;s app would have sent the main payload, containing total votes for each candidate, to the backend server. All this is done simultaneously across all 1,777 precincts.&lt;/p&gt;
&lt;p&gt;At a minimum, there are two main events here:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The login - Precinct chairs needed to log in to the app, which would presumably have happened around the same time across all precincts towards the beginning of the voting process, because the app also contained instructions on how to run a caucus.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The submission - This is the transmission of the total vote counts for each candidate, sent to Google Cloud Functions, and would also have happened around the same time.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It&amp;rsquo;s possible that the app also sent other requests between these two events, but since most of the app is inaccessible without a valid login, I&amp;rsquo;ll focus on the initial login request.&lt;/p&gt;
&lt;p&gt;In a situation like this where I don&amp;rsquo;t have previous data to show how spread out those requests was, it&amp;rsquo;s prudent to err on the side of caution. Assuming the precinct chairs triggered those requests within 10 minutes of each other and rounding up the number of requests for some wiggle room, I estimated that there would have been 1,800 login requests within 10 minutes.&lt;/p&gt;
&lt;p&gt;I decided to test this as a gradual ramp-up of users within 10 minutes.&lt;/p&gt;
&lt;h2 id="scripting-for-mobile"&gt;Scripting for mobile&lt;/h2&gt;
&lt;p&gt;Okay, time to write the script. Since I didn&amp;rsquo;t have the luxury of being able to ask the developers for the format of the login request, I did the next best thing and tried to find out myself by recording the app traffic in action.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200306-02.png" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h3 id="recording-mobile-traffic-on-a-laptop-with-jmeter"&gt;Recording mobile traffic on a laptop with JMeter&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s how I was able to see the request from the mobile app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I downloaded the app to a spare Android mobile by using the APK link above.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I set up an HTTP(S) Test Script Recorder on JMeter on my laptop with the port 8888. I also made sure my laptop was connected to my wifi network.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I set up my mobile to use a proxy using my laptop&amp;rsquo;s local IP address on the network and port 8888.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then, I went back to JMeter on my laptop and started the HTTP(S) Test Script Recorder.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally, I navigated to the app, typed in flood.io in the Precinct ID field (obviously not a real ID), and clicked the &amp;ldquo;Click here to log in&amp;rdquo; button.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;rsquo;s the traffic as seen on JMeter&amp;rsquo;s View Results Tree listener afterward:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200306-03.png" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;And here&amp;rsquo;s the recorded request within the recording controller:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200306-04.png" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h3 id="analyzing-the-request"&gt;Analyzing the request&lt;/h3&gt;
&lt;p&gt;It looks like at least the initial login request is a GET to an Auth0 service, with several parameters being passed in the body. It also has some authorization headers.&lt;/p&gt;
&lt;p&gt;The parameter values also look like they might be dynamic, meaning they change from session to session. At this point, I would typically change some of these from being hardcoded values into dynamic ones so that the application receives a request in the right format, and I could look through &lt;a href="https://auth0.com/docs/api/authentication"&gt;Auth0&amp;rsquo;s API documentation&lt;/a&gt; to find out how the authentication message should be formulated.&lt;/p&gt;
&lt;p&gt;Since I don&amp;rsquo;t have a valid login for testing purposes, I skipped this step and just used the raw request for demonstration purposes.&lt;/p&gt;
&lt;h3 id="preparing-to-run"&gt;Preparing to run&lt;/h3&gt;
&lt;p&gt;Think time is a delay between requests meant to simulate the time it takes for a user to think before taking another action. Without think time, JMeter would fire off requests one after another, which often isn&amp;rsquo;t realistic and drains resources. I don&amp;rsquo;t want that, so I added a JMeter timer. There are plenty of timers available, but I settled on a Uniform Random Timer.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.vice.com/en_us/article/3a8ajj/an-off-the-shelf-skeleton-project-experts-analyze-the-app-that-broke-iowa"&gt;The CEO of Shadow told Motherboard&lt;/a&gt; that many precinct chairs were confused by the login process as they had to put in three strings of numbers in the right sequence. So, I decided to work that into the script with the timer. I set it up with a constant delay of 2 minutes and a random delay of 1 minute so that the delay would vary from 2 minutes to 3 minutes to simulate a precinct chair attempting to log in a few times.&lt;/p&gt;
&lt;h2 id="execution-running-your-mobile-load-test"&gt;Execution: Running your mobile load test&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.vice.com/en_us/article/z3b3g9/here-is-a-link-to-the-shadow-inc-app-that-blew-up-the-iowa-caucus"&gt;According to Motherboard&lt;/a&gt;, Shadow has already taken the app servers offline. However, it&amp;rsquo;s not a good idea to run a full load test against an endpoint that you don&amp;rsquo;t own, so I decided not to run a test.&lt;/p&gt;
&lt;p&gt;Usually, though, I’d want to start with a shakeout test of 10 users or so, and then gradually increase the user load until the peak of 1,800 users. I also would have played around with changing the load profile, such as by increasing or decreasing the ramp-up or steady-state durations, experimenting with stress tests and soak tests, and adding traffic from another availability zone to simulate the 99 satellite precincts around the world. Running multiple load generators can quickly get out of hand if you want to use physical machines, so I would run load tests on the cloud with something like &lt;a href="https://flood.io/"&gt;Flood&lt;/a&gt;. All of these little changes would have given valuable data that would help me gauge the app’s performance in production-like situations.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Building quality software is not a trivial task. There are many moving parts to account for, and critical errors can be introduced in every stage of an app&amp;rsquo;s development. While load issues were not the main culprit in the failure of the IowaReporterApp, a simple load test like the one I describe here, might have improved app stability and reliability. Even in cases where load testing doesn&amp;rsquo;t seem necessary, it can still uncover gross issues in configuration, usability, or security for an app developed on a deadline.&lt;/p&gt;</description></item><item><title>How AirTasker uses Ruby JMeter and Flood for their load testing</title><link>https://nicolevanderhoeven.com/blog/20200224-airtasker/</link><pubDate>Mon, 24 Feb 2020 18:23:31 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200224-airtasker/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/how-airtasker-uses-ruby-jmeter-and-flood-for-their-load-testing"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/how-airtasker-uses-ruby-jmeter-and-flood-for-their-load-testing"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the recent RubyConf 2020 held in Melbourne, Australia, Nancy Cai from AirTasker talked about how they built a performance testing framework using Ruby JMeter and Flood. Luckily, we had some pleasantly surprised Flooders in attendance to take notes during this fantastic talk!&lt;/p&gt;
&lt;p&gt;AirTasker is a platform allowing the outsourcing of everyday tasks. When discussing the reasons that AirTasker decided they wanted to carry out performance and load testing, Nancy told a fascinating story about an overly successful marketing campaign—a good problem to have, but a problem nonetheless. The Sydney Cats and Dogs Home, an animal shelter, teamed up with AirTasker to pay one lucky person $500 to spend the day playing with the resident animals. The prospect of this dream job created an enormous surge in AirTasker&amp;rsquo;s traffic that caused alarm bells to go off on the underlying application servers, resulting in an end-user experience that was less than desired.&lt;/p&gt;
&lt;p&gt;Nancy included this hilarious slide about some common feelings regarding application performance.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200224-01.png" alt="A common feeling when application performance is brought up" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="steps-for-running-a-performance-test-the-airtasker-way"&gt;Steps for running a performance test, the AirTasker way&lt;/h2&gt;
&lt;p&gt;To avoid repeating that mistake, Nancy and her team set out to run performance testing by using the following simple steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Determine performance criteria.&lt;/li&gt;
&lt;li&gt;Configure the test environment to be as production-like as possible.&lt;/li&gt;
&lt;li&gt;Plan and design based on user behavior, including preparing test data.&lt;/li&gt;
&lt;li&gt;Implement test design and set up the framework (which in AirTasker&amp;rsquo;s case involved Ruby JMeter as the performance testing tool and Flood as a load testing solution).&lt;/li&gt;
&lt;li&gt;Run test.&lt;/li&gt;
&lt;li&gt;Analyze and fine-tune results.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="setting-up-a-load-testing-tool-and-framework"&gt;Setting up a load testing tool and framework&lt;/h2&gt;
&lt;p&gt;When it came to selecting the right tools for the job, AirTasker wanted tools that met the following criteria:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ability to simulate production-like traffic easily&lt;/li&gt;
&lt;li&gt;Widespread use in the industry&lt;/li&gt;
&lt;li&gt;Ease of creation and maintenance of tests for everyone&lt;/li&gt;
&lt;li&gt;Historical results aggregation&lt;/li&gt;
&lt;li&gt;Visualization of performance metrics&lt;/li&gt;
&lt;li&gt;Integration with CI and monitoring tools&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nancy&amp;rsquo;s team compared several load testing tools and found they enjoyed using the Apache JMeter tool, which is a popular open source load testing software. However, they quickly ran into an &amp;ldquo;out of memory&amp;rdquo; error after attempting to run about 400-800 concurrent users on a single machine. She and her team decided to use a distributed load testing platform to run the load they required to scale up more effectively.&lt;/p&gt;
&lt;p&gt;Enter Flood.&lt;/p&gt;
&lt;h2 id="why-airtasker-chose-flood"&gt;Why AirTasker chose Flood&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200224-02.png" alt="JMeter, Flood, and the Ruby JMeter gem combination is a winner" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We also chose Flood.io [&amp;hellip;] because it comes in with a really good open-source gem called Ruby JMeter. It is a Ruby-based DSL for building JMeter test plans. - Nancy Cai, AirTasker&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Nancy and her team enjoyed the benefits of being able to write load tests natively in Ruby and then using Flood&amp;rsquo;s Ruby JMeter gem, which is a Domain-Specific Language (DSL). Flood allowed them to turn their Ruby scripts into .jmx files, which is the native XML format that JMeter uses.&lt;/p&gt;
&lt;p&gt;When they were ready to scale up, AirTasker ran the same JMeter script in Flood.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200224-03.png" alt="Sample of a report on Flood from a JMeter test" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;The real-time Flood dashboard allowed them to see that there was a problem on one of the API endpoints, called &amp;ldquo;Get pet reviews.&amp;rdquo; Further investigations revealed a performance issue due to a long-running query against a database server in the code, which AirTasker&amp;rsquo;s developers could fix.&lt;/p&gt;
&lt;h2 id="best-practices"&gt;Best practices&lt;/h2&gt;
&lt;p&gt;Nancy gives some great advice for anyone running a performance test, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;asking the right questions as a load tester&lt;/li&gt;
&lt;li&gt;running baseline tests&lt;/li&gt;
&lt;li&gt;being aware of the difference between your test and production environments&lt;/li&gt;
&lt;li&gt;keeping in mind the caching and autoscaling mechanisms that may drastically change the results&lt;/li&gt;
&lt;li&gt;the differences between stress testing and other types of performance testing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We were so thrilled to hear Nancy&amp;rsquo;s story on how Flood helped AirTasker run their performance tests. Catch the entirety of Nancy&amp;rsquo;s talk below, and check out the resource links at the end of the post to follow Nancy&amp;rsquo;s story.‍&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/Q09wJm4P8Xw?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/flood-io/ruby-jmeter"&gt;Flood&amp;rsquo;s Ruby JMeter gem&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nancy-cai/performance-test-ruby-jmeter"&gt;Nancy&amp;rsquo;s GitHub repo&lt;/a&gt; where you can find a copy of her test scripts&lt;/p&gt;
&lt;p&gt;Follow Nancy on &lt;a href="https://twitter.com/nancycai8"&gt;Twitter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow Nancy on &lt;a href="https://github.com/nancy-cai"&gt;GitHub&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Performance Testing Interview Questions, Part 2: JMeter</title><link>https://nicolevanderhoeven.com/blog/20181220-performance-testing-interview-questions-part-2/</link><pubDate>Thu, 20 Dec 2018 14:47:18 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20181220-performance-testing-interview-questions-part-2/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/performance-testing-interview-questions-part-2-jmeter-interview-questions"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/performance-testing-interview-questions-part-2-jmeter-interview-questions"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this part, we’ll go over some questions that are commonly asked in technical interviews about the use of the most popular open-source load testing tool, &lt;a href="http://jmeter.apache.org/"&gt;Apache JMeter&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="using-jmeter-you-record-a-key-business-process-upon-playing-it-back-however-you-notice-an-error-on-the-first-page-what-could-have-gone-wrong-and-how-would-you-fix-this"&gt;Using JMeter, you record a key business process. Upon playing it back, however, you notice an error on the first page. What could have gone wrong and how would you fix this?&lt;/h3&gt;
&lt;p&gt;While recorders have gone a long way towards making scripting easier, modern security measures like the implementation of viewstates have also made scripting more complicated to record. Some more complicated applications will pass dynamic values in responses that it expects to see in the succeeding request, otherwise the request is blocked. This is great for security, but it also means that you will need to manually extract these values in your script.&lt;/p&gt;
&lt;p&gt;In JMeter, you would do this by adding a response extractor to your sample that will extract the dynamic string according to rules you set, and then save the string to a parameter. This parameter must then be used in the next request that you send.&lt;/p&gt;
&lt;p&gt;While running your test plan, you get the error: &lt;code&gt;java.lang.OutOfMemoryError: Java heap space&lt;/code&gt;. How do you fix it?
The easy fix is to edit &lt;code&gt;jmeter.bat&lt;/code&gt; and increase the heap memory (search for &lt;code&gt;HEAP&lt;/code&gt;) and increase heap space allocated like this:
&lt;code&gt;HEAP=&amp;quot;-Xms512m -Xmx2048m&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The part in bold increases the heap space to 2 GB.&lt;/p&gt;
&lt;p&gt;However, it’s also worthwhile looking at your test plan and removing any obvious memory hogs. One of the things we see a lot is enabled listeners that aren’t even being used. Listeners are great while debugging, but should be disabled when running a load test. Writing too many lines to the log is another culprit here that should also be commented out when running important tests. And of course, you should always run JMeter in non-GUI mode during load tests!&lt;/p&gt;
&lt;h3 id="after-running-a-load-test-the-results-show-that-300-transactions-were-executed-with-a-passed-status-and-returning-responses-of-http-200-however-the-dba-tells-you-that-there-were-no-records-written-to-the-database-as-a-result-of-the-transactions-how-would-you-troubleshoot-this"&gt;After running a load test, the results show that 300 transactions were executed with a PASSED status and returning responses of HTTP 200. However, the DBA tells you that there were no records written to the database as a result of the transactions. How would you troubleshoot this?&lt;/h3&gt;
&lt;p&gt;I see this happening with clients all the time, so I think this makes a great technical interview question. This is also why I said earlier that you shouldn’t count on a test tool to tell you a test has passed. It’s possible for a transaction to have the status PASSED and return an HTTP 200 but still be hiding an error.&lt;/p&gt;
&lt;p&gt;This is mainly due to poor scripting that does not include validations that check whether the script has gotten to the right page. For example, you could use a Response Assertion as a child of your home page sample with the words “Welcome, Nicole” to determine whether the user Nicole has logged in successfully.&lt;/p&gt;
&lt;p&gt;This is a critical step, because without it, it’s possible for a server to return a nice error page, or an incorrect one, such as the home page, with an HTTP 200.&lt;/p&gt;
&lt;h3 id="how-do-you-use-a-data-file-to-read-user-account-details-from-a-csv-in-jmeter"&gt;How do you use a data file to read user account details from a CSV in JMeter?&lt;/h3&gt;
&lt;p&gt;JMeter has a &lt;a href="https://jmeter.apache.org/usermanual/component_reference.html#CSV_Data_Set_Config"&gt;CSV Data Set Config Element&lt;/a&gt; built specifically for this purpose. You can simply add one to your test plan, browse to the CSV file that you’d like to use, and select the options for how to share that data among the threads in your JMeter script.&lt;/p&gt;
&lt;h3 id="how-would-you-go-about-testing-a-website-that-uses-http2-on-jmeter"&gt;How would you go about testing a website that uses HTTP/2 on JMeter?&lt;/h3&gt;
&lt;p&gt;There is a JMeter plugin called HTTP/2 Sampler that accomplishes just this. My colleague Jason just wrote &lt;a href="https://flood.io/blog/jmeter-tutorial-http2-test/"&gt;a blog post&lt;/a&gt; on this very topic, but basically the plugin adds new HTTP/2 versions to the standard HTTP request and request defaults samplers as well as the Simple Data Writer and View Results Tree listener. These elements will need to be used in order to test an application using HTTP/2.&lt;/p&gt;
&lt;h3 id="what-can-you-do-to-synchronise-the-execution-of-multiple-jmeter-instances-on-different-load-generators"&gt;What can you do to synchronise the execution of multiple JMeter instances on different load generators?&lt;/h3&gt;
&lt;p&gt;Apache JMeter has released &lt;a href="https://jmeter.apache.org/usermanual/jmeter_distributed_testing_step_by_step.pdf"&gt;this handy PDF file&lt;/a&gt; to describe the steps necessary to run JMeter in distributed mode. This involves installing Java and JMeter on all machines and setting them up in a master and slave configuration so that one machine controls the rest. On the master, you’ll need to add remote hosts to the jmeter.properties file. When everything is set up, you should be able to open up JMeter on the master and do a a remote start of your current test plan on any or all slaves that you choose.&lt;/p&gt;
&lt;p&gt;The problem with this setup is the clunkiness of working with different machines and essentially having to set them up the same way. After the test, there’s the daunting task of logging back onto each machine, gathering the data, and transferring them back into a central repository. Then you’re faced with consolidating the data from each injector in order to see a picture of the whole test. You can see that this set up quickly goes from time-consuming to a nightmare, especially when potentially thousands of different machines are involved.&lt;/p&gt;
&lt;p&gt;If only there were &lt;a href="https://flood.io/"&gt;an easier way&lt;/a&gt;&amp;hellip;&lt;/p&gt;</description></item><item><title>Should I Upgrade to JMeter 4.0? 5 Reasons to Upgrade</title><link>https://nicolevanderhoeven.com/blog/20180223-should-i-upgrade-to-jmeter-4/</link><pubDate>Fri, 23 Feb 2018 23:43:25 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20180223-should-i-upgrade-to-jmeter-4/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/should-i-upgrade-to-jmeter-4-0-5-reasons-to-upgrade"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/should-i-upgrade-to-jmeter-4-0-5-reasons-to-upgrade"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Apache has just launched &lt;a href="http://jmeter.apache.org/download_jmeter.cgi"&gt;JMeter 4.0&lt;/a&gt;, a big step up from their previous release, 3.3, which was only released in September last year. Apache seems to be stepping up the frequency of it’s releases, and we’re not complaining. JMeter is an amazing open source load testing tool and the most popular one used at &lt;a href="http://flood.io/"&gt;Tricentis Flood&lt;/a&gt; by far.&lt;/p&gt;
&lt;p&gt;The big question is: Should you upgrade? Are the new features worth the leap? Will the new black UI make you a better load tester? While this choice should be made on a case-by-case basis and we certainly can’t pretend to give one-size-fits-all advice, here are some good arguments to do it:&lt;/p&gt;
&lt;h3 id="1-java-9-support"&gt;#1: Java 9 support&lt;/h3&gt;
&lt;p&gt;JDK 9 was released back in September 2017, and if you were one of the people who upgraded to it when prompted, you would have noticed to your frustration that JMeter 3.3 did not play well with it, yielding the error:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Error: Java version -- 9.0.1 -- is too low to run JMeter. Needs a Java version greater than or equal to 1.8.0 errorlevel&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Good news! This is now fixed. JMeter 4.0 runs smoothly on JDK 9. We&amp;rsquo;ll continue running on JDK 8 at Flood for consistency amongst all our open source load testing tools.&lt;/p&gt;
&lt;h3 id="2-new-boundary-extractor"&gt;#2: New Boundary Extractor&lt;/h3&gt;
&lt;p&gt;Previously, my preferred way to extract dynamic values in JMeter was to use a regular expression extractor, but there’s no doubt that it can sometimes be tricky to get just the right text out of a response. Enter the &lt;a href="http://jmeter.apache.org/usermanual/component_reference.html#Boundary_Extractor"&gt;Boundary Extractor&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The boundary extractor allows you to simply set the text immediately before and after the text you want to extract. This saves you wondering whether you should have used a + or a * in your regular expression, and is also easier to validate.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20180223-01.png" alt="Boundary Extractor in JMeter" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h3 id="3-new-json-assertion-element"&gt;#3: New JSON assertion element&lt;/h3&gt;
&lt;p&gt;While XPath assertion was great, there was previously no counterpart for JSON. The &lt;a href="http://jmeter.apache.org/usermanual/component_reference.html#JSON_Assertion"&gt;JSON Assertion&lt;/a&gt; element fills that void nicely, using &lt;a href="https://github.com/json-path/JsonPath"&gt;JsonPath&lt;/a&gt; to quickly assert the existence (or non-existence, with the Invert assertion option ticked) of a particular element.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20180223-02.png" alt="JSON Assertion element in JMeter" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h3 id="4-new-throughput-timer"&gt;#4: New throughput timer&lt;/h3&gt;
&lt;p&gt;We have a new throughput timer to play with, and it’s called &lt;a href="http://home.apache.org/~milamber/jmeter-4.0RC4/docs/usermanual/component_reference.html#Precise_Throughput_Timer"&gt;Precise Throughput Timer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20180223-03.png" alt="Precise Throughput Timer in JMeter" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Whereas the Constant Throughput Timer also had the disadvantage of constant pacing of requests, the Precise Throughput Timer is based on the &lt;a href="http://home.apache.org/~milamber/jmeter-4.0RC4/docs/usermanual/component_reference.html#Poisson_Random_Timer"&gt;Poisson Random Timer&lt;/a&gt; and randomly generates the delay between each request. The implementation seems to be well thought out, with the component reference section listing a lot of scenarios they’ve tested for that the previous Constant Throughput Timer might have struggled with. Throughput timers are one of my favourite JMeter features, and still rather unique in the industry.&lt;/p&gt;
&lt;h3 id="5-test-plan-autosave"&gt;#5: Test Plan Autosave&lt;/h3&gt;
&lt;p&gt;This one’s more of a usability tweak, but it’s a good one. JMeter now automatically saves your script when you run a test, saving you from those all-too-familiar “Wait… did I CTRL+S before I hit CTRL+R?” moments.&lt;/p&gt;
&lt;p&gt;Click &lt;a href="http://home.apache.org/~milamber/jmeter-4.0RC4/docs/changes.html"&gt;here&lt;/a&gt; to see the full release notes for version.&lt;/p&gt;
&lt;h3 id="bonus-reason-tricentis-flood-support"&gt;BONUS reason: Tricentis Flood support&lt;/h3&gt;
&lt;p&gt;You can now upload JMeter 4.0 scripts to flood.io and be up and running with your first test hosted on one of our grid nodes around the world. Our customer support team is always happy to help you make the switch to 4.0.&lt;/p&gt;</description></item></channel></rss>