<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Flood Element on Nicole van der Hoeven</title><link>https://nicolevanderhoeven.com/tags/flood-element/</link><description>Recent content in Flood Element on Nicole van der Hoeven</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>Nicole van der Hoeven</copyright><lastBuildDate>Sat, 07 Aug 2021 22:15:13 +0200</lastBuildDate><atom:link href="https://nicolevanderhoeven.com/tags/flood-element/index.xml" rel="self" type="application/rss+xml"/><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>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>Pros and Cons of API load testing</title><link>https://nicolevanderhoeven.com/blog/20200818-pros-and-cons/</link><pubDate>Tue, 18 Aug 2020 21:22:49 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200818-pros-and-cons/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/pros-and-cons-of-api-load-testing"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/pros-and-cons-of-api-load-testing"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;‍API load testing is one of the most popular ways to run a load test because of the number of open source and commercial load testing tools available on the market that support it. Creating a script to hit your application&amp;rsquo;s API endpoints is the traditional approach to load testing, but it&amp;rsquo;s not the only one.&lt;/p&gt;
&lt;p&gt;Here are some things to consider when deciding whether or not API load testing is right for your application.&lt;/p&gt;
&lt;h2 id="disadvantages-of-api-load-testing"&gt;Disadvantages of API load testing&lt;/h2&gt;
&lt;h3 id="api-load-testing-does-not-simulate-real-users-interacting-with-elements-of-your-webpage"&gt;API load testing does not simulate real users interacting with elements of your webpage.&lt;/h3&gt;
&lt;p&gt;‌In contrast to a customer opening up a browser and filling out forms on your site, an API load testing script will consist only of the underlying requests to the server that are made by clicking on those on-screen elements. Exactly how the customer triggers those requests, and what buttons they’ve pressed, is irrelevant. It’s all about the raw requests.‌&lt;/p&gt;
&lt;p&gt;The format of these requests will be dictated by the type of API your application uses, and it may take some technical knowledge or expertise to be able to formulate requests correctly. However, a RESTful API is one of the most common types, and it is considered to be relatively simple to use.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200818-01.png" alt="" loading="lazy" decoding="async"&gt;
&lt;em&gt;HTTPS requests for amazon.com. This is what an API load testing script would need to replicate.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="it-doesnt-give-you-an-idea-of-how-user-friendly-your-application-is"&gt;It doesn’t give you an idea of how user-friendly your application is.&lt;/h3&gt;
&lt;p&gt;‌API load testing tools don’t give you feedback on how long your pictures took to render on your users’ browsers or whether that “SUBMIT” button is in an obvious spot.&lt;/p&gt;
&lt;h3 id="it-doesnt-measure-front-end-performance-or-how-quickly-pages-render-in-different-browsers"&gt;‌It doesn’t measure front-end performance or how quickly pages render in different browsers.&lt;/h3&gt;
&lt;p&gt;‌While all the resources that the server returns can be downloaded by your tool of choice, there is no browser on which to run them.&lt;/p&gt;
&lt;h3 id="api-load-testing-doesnt-run-client-side-scripts"&gt;‌API load testing doesn’t run client-side scripts.&lt;/h3&gt;
&lt;p&gt;‌It isn’t what you’re looking for if your application is a single-page web app that relies heavily on JavaScript or AJAX to dynamically populate and update the page. Your load testing tool will download the scripts, but not execute them.‌&lt;/p&gt;
&lt;p&gt;‌This includes scripts like those required to trigger Google Analytics, which prompts many an engineer to question the results of an API load test due to the inability to see the traffic come in on Google Analytics. API load testing won’t help you with that. Running browser-level load tests using tools like &lt;a href="https://element.flood.io"&gt;Flood Element&lt;/a&gt; or &lt;a href="https://selenium.dev"&gt;Selenium&lt;/a&gt; may be more useful.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;ve decided that API load testing is not the best way to load test your application, you can look at browser-based load testing as an alternative.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200818-02.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Executing a browser-based load testing script using Flood Element.&lt;/em&gt;
‌&lt;/p&gt;
&lt;h2 id="advantages-of-api-load-testing"&gt;‌Advantages of API load testing&lt;/h2&gt;
&lt;p&gt;Now that we’ve talked about what API load testing isn’t good at, let’s talk about what it IS good at.&lt;/p&gt;
&lt;p&gt;‌### It allows you to load test specific servers rather than the whole stack.&lt;/p&gt;
&lt;p&gt;‌API load testing allows you to tailor your load testing by applying load only on particular servers. This is particularly useful in more complicated applications that involve several components and would require substantial effort to reproduce in a test environment. Using APIs, you can test only the functions you want to test.&lt;/p&gt;
&lt;h3 id="it-is-well-supported-"&gt;It is well-supported. ‌&lt;/h3&gt;
&lt;p&gt;API load testing has been around for decades. There are lots of robust tools you can choose from, both commercial and open-source, and many of these tools have large communities and extensive documentation around how to script the most common cases. It’s a far cry from the browser-level testing space, which is relatively new and sparsely populated by comparison.&lt;/p&gt;
&lt;p&gt;‍&lt;img src="https://nicolevanderhoeven.com/assets/20200818-03.png" alt="" loading="lazy" decoding="async"&gt;
&lt;em&gt;The &lt;a href="https://jmeter.apache.org/usermanual/index.html"&gt;JMeter site&lt;/a&gt; contains a wealth of information, including a User&amp;rsquo;s Manual&lt;/em&gt;
‍&lt;/p&gt;
&lt;h3 id="its-not-as-resource-intensive-as-browser-level-testing"&gt;It’s not as resource-intensive as browser-level testing.&lt;/h3&gt;
&lt;p&gt;You can simulate more users with API load testing than with browser-level load testing. Since most interactions on the browser-level get translated to requests anyway, generating load this way is incredibly efficient, allowing you to hit your server with requests while bypassing the UI layer and the resource overhead that that entails.&lt;/p&gt;
&lt;p&gt;For example, at &lt;a href="https://flood.io"&gt;Flood&lt;/a&gt; we’ve baselined some of the tools that we support to see how many users we can run on an AWS m5.xlarge instance:&lt;/p&gt;
&lt;p&gt;Selenium: 5 users
Flood Element: 20-40 users
JMeter: 1000 users
Gatling: 1000 users&lt;/p&gt;
&lt;p&gt;‌You’ll see that the browser-level test tools, Selenium and Flood Element, can run significantly fewer users on the same sized node as can the protocol-level tools, JMeter and Gatling. This isn’t due to an inefficiency in the tools but rather to the fact that browser-level tools inherently need more CPU and memory to start separate instances of browsers per user and render pages graphically. You can run more users per node (or machine) by carrying out API load testing with protocol-level tools.&lt;/p&gt;
&lt;h3 id="its-cheaper"&gt;It’s cheaper.&lt;/h3&gt;
&lt;p&gt;‌The efficiency in resource utilization translates directly into cost savings because every node that you don’t need to execute your tests on is one fewer node that you’ll have to pay to provision (whether on premises or in the cloud).&lt;/p&gt;
&lt;p&gt;‌For this reason, API load testing is one of the most cost-efficient ways you can get started with load testing, allowing you to scale up your load relatively cheaply while getting immediate results.&lt;/p&gt;
&lt;h2 id="how-to-get-started-with-api-load-testing"&gt;How to get started with API load testing&lt;/h2&gt;
&lt;p&gt;API load testing isn&amp;rsquo;t for every application, but depending on your test scenario, it may be the easiest way to test application performance.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re new to non-functional testing or API load testing in particular and would like some step-by-step tutorials on how to get started, check out my free ebook, &lt;a href="https://guides.flood.io/ebooks/api-load-testing"&gt;API Load Testing: A Beginner&amp;rsquo;s Guide&lt;/a&gt;. It takes you through the basics of API load testing, including planning your first load test, selecting an open source tool, scripting, executing a test on the cloud, analyzing results, and even integrating it into your CI/CD pipelines.&lt;/p&gt;</description></item><item><title>Ask a Flooder 17: How do I use unique test data on Element?</title><link>https://nicolevanderhoeven.com/blog/20200618-aaf17/</link><pubDate>Thu, 18 Jun 2020 21:58:49 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200618-aaf17/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/ask-a-flooder-17-how-do-i-use-unique-test-data-on-element"&gt;
&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://www.flood.io/blog/ask-a-flooder-17-how-do-i-use-unique-test-data-on-element"&gt;Tricentis Flood&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this video, I talk about how to ensure that Flood Element uses unique test data, using the example of a customer wanting to script unique logins for his application.&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/qVpX7MX3jxE?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 instead:&lt;/p&gt;
&lt;iframe src="https://open.spotify.com/embed-podcast/episode/7k5TXtoHnswJwBbKHXgJR7" width="100%" height="232" frameborder="0" allowtransparency="true" allow="encrypted-media"&gt;&lt;/iframe&gt;
&lt;h2 id="transcript"&gt;Transcript:&lt;/h2&gt;
&lt;p&gt;Hi everyone, Nicole van der Hoeven here again back with another Ask a Flooder, and this week&amp;rsquo;s question is a follow-up question from last week. That user had previously asked about test data in Flood Element. This week he&amp;rsquo;s asking: &amp;ldquo;How do I ensure that Flood Element uses unique test data?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;So this user is actually trying to script a login for an application. He has a list of usernames and corresponding passwords that he wants to use. He&amp;rsquo;s already set both of these up in a CSV file, and he&amp;rsquo;s also set up the Element script in the same way that I outline in my previous video. However, this user is seeing errors in the test due to the application not allowing a given user account to be used simultaneously in two or more devices. The problem is that the way that he&amp;rsquo;s set it up is that he has Element running on multiple nodes, and each node has the chance to pick the same user account.&lt;/p&gt;
&lt;p&gt;So how do you make sure that it&amp;rsquo;s a unique 1:1 ratio for an instance of Element and a user account in the CSV file? If you haven&amp;rsquo;t already watched the previous week&amp;rsquo;s video, you should pause this, watch that, and then come back here, so it makes a little more sense because the script that I&amp;rsquo;m using is building on what we already did in the previous week.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s talk about the differences between this script and the previous week&amp;rsquo;s.&lt;/p&gt;
&lt;p&gt;First, I&amp;rsquo;m declaring a global variable here called &lt;code&gt;globalBrowserID&lt;/code&gt;. The idea is to create a unique and globally identifiable string that I can attach to every account in the CSV file.&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;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;globalBrowserID&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ENV&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FLOOD_GRID_INDEX&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;_&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ENV&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FLOOD_GRID_NODE_SEQUENCE_ID&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;_&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ENV&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;BROWSER_ID&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toString&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The global browser ID consists of three parts:- The first is a grid index, which is a number assigned to every grid, and it&amp;rsquo;s also globally unique. So if there are three grids being used in the test, then the grid indexes would be 0, 1, and 2.- The second one is a grid node sequence ID, and this is unique within the grid. The node sequence ID is a number that is assigned to every node in a single grid.- The last one is a browser ID. The browser ID is a number assigned to an instance of Element running on a single node.&lt;/p&gt;
&lt;p&gt;These are all zero-based, so the very first instance of Element running on the very first node and on the very first grid in the entire test would be &lt;code&gt;0_0_0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re going to have to modify our CSV file to make use of this browser ID. So whereas the user previously had username and password, I&amp;rsquo;ve added an ID column. From then, these will have to be sequential. So &lt;code&gt;0_0_0&lt;/code&gt;, &lt;code&gt;0_0_1...&lt;/code&gt; And &lt;code&gt;0_0_1&lt;/code&gt; would be the second instance of Element running still on the first node, on the first grid. And you can make as many of these as you need.&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-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;id,username,password
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0_0_0,user1,password1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0_0_1,user2,password2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0_0_2,user3,password3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1_0_0,user4,password4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1_0_1,user5,password5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve also modified the interface &lt;code&gt;UserData&lt;/code&gt; to describe the fields in the CSV file. So there&amp;rsquo;s &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt;, and &lt;code&gt;password&lt;/code&gt;, and I&amp;rsquo;ve defined them all as strings.&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;TestData&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;fromCSV&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;UserData&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;users_multiplegrids.csv&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;filter&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;line&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;index&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;browserID&lt;/span&gt;) =&amp;gt; &lt;span style="color:#a6e22e"&gt;line&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;globalBrowserID&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;circular&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This line is telling Element to take this data file with this filename and filter it based on the line, the index, and the browserID such that &lt;code&gt;id&lt;/code&gt; is equal to the browser ID. So what happens here is that Element will take the global browser ID, which let&amp;rsquo;s say is &lt;code&gt;0_0_0&lt;/code&gt; for the very first one. It&amp;rsquo;ll then take that &lt;code&gt;0_0_0&lt;/code&gt; and look at the CSV file for anything in the ID field that has the value &lt;code&gt;0_0_0&lt;/code&gt;. And then it will continue to use the rest of that line.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve also made the CSV file circular just because that&amp;rsquo;s always a good practice to get into.&lt;/p&gt;
&lt;p&gt;And as always, I think it&amp;rsquo;s a great idea to debug this, especially when you&amp;rsquo;re dealing with multiple grids and multiple nodes on that grid.&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;Print to console&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;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Browser&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UserData&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;global browser ID: &amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;globalBrowserID&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;| user: &amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;username&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39; | password: &amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;password&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve also added the username and password here, just in case we need to verify the state that that user is in.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s run the test. Since we&amp;rsquo;re just running this locally, we&amp;rsquo;ll see that the first value indeed is &lt;code&gt;0_0_0&lt;/code&gt;, and the user we&amp;rsquo;re selecting is &lt;code&gt;user1&lt;/code&gt; and &lt;code&gt;password1&lt;/code&gt;, which lines up with the username and password values corresponding to &lt;code&gt;0_0_0&lt;/code&gt; in the CSV file.&lt;/p&gt;
&lt;p&gt;I hope that helped, and until next time, happy flooding!&lt;/p&gt;
&lt;p&gt;Download the &lt;a href="https://github.com/flood-io/load-testing-playground/blob/master/element/test-data/example.ts"&gt;full script&lt;/a&gt; and the &lt;a href="https://github.com/flood-io/load-testing-playground/blob/master/element/test-data/users.csv"&gt;data file&lt;/a&gt; to follow along.&lt;/p&gt;</description></item><item><title>Ask a Flooder 16: How do I use test data with Element?</title><link>https://nicolevanderhoeven.com/blog/20200609-aaf16/</link><pubDate>Tue, 09 Jun 2020 22:18:41 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200609-aaf16/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/ask-a-flooder-16-how-do-i-use-test-data-with-element-video"&gt;
&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://www.flood.io/blog/ask-a-flooder-16-how-do-i-use-test-data-with-element-video"&gt;Tricentis Flood&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this video, I discuss how to make your load testing scripts more realistic by including test data. The load testing tool I use is &lt;a href="https://element.flood.io/"&gt;Flood Element&lt;/a&gt;, but you can apply these principles to any tool. You&amp;rsquo;ll find a copy of the Element script I used below.&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/EGhVm-R12qI?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;And, if you prefer, here&amp;rsquo;s the audio version:&lt;/p&gt;
&lt;iframe src="https://open.spotify.com/embed-podcast/episode/4OW5slSCmAuBc9NPa1NKtk" width="100%" height="232" frameborder="0" allowtransparency="true" allow="encrypted-media"&gt;&lt;/iframe&gt;
&lt;h2 id="transcript"&gt;Transcript&lt;/h2&gt;
&lt;p&gt;Hi everyone, Nicole van der Hoeven here back with another Ask a Flooder, and this time the question is: How do I use test data with Flood Element?&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s talk about why you might want to use test data. In load testing, it&amp;rsquo;s important to make your scripts behave as similarly to real users as possible so that the load that you generate is production-like. The problem is that if you send the same data over and over again to the server, that server is probably going to cache that response. The response being cached means that the server will return the response way faster than it normally would if it had been a unique request. So we can use test data, instead of static data hardcoded in your scripts, to make sure that this doesn&amp;rsquo;t happen.&lt;/p&gt;
&lt;p&gt;Using test data can also help us test different responses. For example, let&amp;rsquo;s say we&amp;rsquo;re testing a loan application system, where a user inputs the application ID, the server looks it up, and returns the status of that loan application. Now, loan applications might be in different stages of the process. For instance, some might be saved but not submitted, or maybe they&amp;rsquo;ve been submitted but failed the identity verification check.&lt;/p&gt;
&lt;p&gt;If we used the same application ID every time, then the server would always return the same status and the same details. Instead, let&amp;rsquo;s create a CSV file that we can use as test data. It might look something like this.‍&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-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;applicationId
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;A100001
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;B100002
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;C100003
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;D100004
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can have &lt;code&gt;applicationId&lt;/code&gt; as the single header here, and we can populate this with a list of different application IDs in different stages of the process. That way, when we run the script, the server will have to respond authentically to every request without it being cached.&lt;/p&gt;
&lt;p&gt;Now to create our script. This is an empty Element script. To start with, make sure you&amp;rsquo;re importing &lt;code&gt;TestData&lt;/code&gt; here in the first line of your 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:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;step&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;TestSettings&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Until&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;By&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Browser&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;TestData&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;@flood/element&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The first thing we&amp;rsquo;re going to need to do is to create an interface for the CSV file. Let&amp;rsquo;s call it &lt;code&gt;AppData&lt;/code&gt;. Within this interface, we&amp;rsquo;ll need to define all the fields that we intend to use in our data file and what type of values we can expect to be in those fields. Looking at our CSV here, we&amp;rsquo;ve just got the application ID, so I&amp;rsquo;m just going to copy that, and it&amp;rsquo;s a mixture of characters and numbers, so I&amp;rsquo;m going to put that in as a string.&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;interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AppData&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;applicationId&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;string&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;Now we need to tell Element how to find this test data. We&amp;rsquo;ll say that it&amp;rsquo;s from the CSV, using the interface we&amp;rsquo;ve just created. Now we&amp;rsquo;ll tell Element the filename. In this situation, the CSV file that I&amp;rsquo;m using is actually in the same directory, so I don&amp;rsquo;t need to specify a path here, but if you&amp;rsquo;re putting it somewhere else, then you&amp;rsquo;ll need to specify the folder and the path to it.&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;TestData&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;fromCSV&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;AppData&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;applicationids.csv&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s use the data in a step. In real life, you might want to use an application ID to type it into a text field, but for demonstration purposes, I&amp;rsquo;m just going to show you how to output it to the console log. Printing to the console is also a good way to debug your tests, especially if you&amp;rsquo;re dealing with test data.&lt;/p&gt;
&lt;p&gt;We need to let Element know that we want to use AppData. So now, let&amp;rsquo;s output this to the console. Since we&amp;rsquo;re just debugging, let&amp;rsquo;s output the application ID. To actually get the value from the data file, we&amp;rsquo;ll use this syntax:&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;Print to console&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;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Browser&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AppData&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;application ID: &amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;applicationId&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;‍By default, Element reads the data files sequentially. The problem with that is we only have a handful of application IDs. So if we wanted to run this one script 100 times, we&amp;rsquo;re going to run out of data. What we can do here is add &lt;code&gt;circular&lt;/code&gt;. That way, when the script reaches the very last value of the file, the next value it selects will be the first one, and it never runs out of test data.&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;TestData&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;fromCSV&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;AppData&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;applicationids.csv&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;circular&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Another thing you might be wondering is how to make it so that Element chooses a random value every time. To do that, we&amp;rsquo;ll also have to add &lt;code&gt;shuffle&lt;/code&gt;:&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;TestData&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;fromCSV&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;AppData&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;applicationids.csv&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;circular&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;‍Now let&amp;rsquo;s try to run the test.&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-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;element run test-data.ts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, it&amp;rsquo;s been finished. The application ID that was selected was indeed a random one because the first one would have started with A. So, it actually chose the last one randomly.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s it for test data with Element. Now, this user actually had a follow-up question, which was about unique test data. I&amp;rsquo;m going to answer that in the next video. Until next time, happy Flooding!&lt;/p&gt;
&lt;h2 id="sample-script"&gt;Sample script&lt;/h2&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;step&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;TestSettings&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Until&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;By&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Browser&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;TestData&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;@flood/element&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:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;as&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;assert&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;assert&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;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;settings&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TestSettings&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;loopCount&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,    
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;description&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Test Data&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;screenshotOnFailure&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,    
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;disableCache&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,    
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;clearCache&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,    
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;clearCookies&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&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:#75715e"&gt;/*** Test Data * Version: 1.0 */&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; () =&amp;gt; {    
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AppData&lt;/span&gt; {        
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;applicationId&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;string&lt;/span&gt;    }    
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;TestData&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;fromCSV&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;AppData&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;applicationids.csv&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;circular&lt;/span&gt;()    
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;shuffle&lt;/span&gt;()    
&lt;/span&gt;&lt;/span&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;Print to console&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;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Browser&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AppData&lt;/span&gt;) =&amp;gt; {        
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;application ID: &amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;applicationId&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Ask a Flooder 15: How do I install Element?</title><link>https://nicolevanderhoeven.com/blog/20200512-aaf15/</link><pubDate>Tue, 12 May 2020 22:45:18 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200512-aaf15/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/ask-a-flooder-15-how-do-i-install-element-video"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/ask-a-flooder-15-how-do-i-install-element-video"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this Flood Element tutorial, I demonstrate the steps required to install Flood Element, including dependencies it requires. Flood Element is an open-source browser-based load testing tool created by Tricentis Flood.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bit.ly/2YM1mnV"&gt;Learn more about Flood Element&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nodejs.org/en/download/current/"&gt;Installation instructions for NodeJS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://classic.yarnpkg.com/en/docs/install/"&gt;Installation instructions for Yarn&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bit.ly/2yuYrWl"&gt;Installation instructions for Element&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=oWtnStKrh98"&gt;Video: Getting Started with Element&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bit.ly/2YJIQg5"&gt;Guides: Using Element with Flood‍&lt;/a&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/N7VLqqueqJE?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/6EZ97ImNGUiDAGcEyGGNYM" width="100%" height="232" frameborder="0" allowtransparency="true" allow="encrypted-media"&gt;&lt;/iframe&gt;
&lt;h2 id="transcript"&gt;Transcript&lt;/h2&gt;
&lt;p&gt;Hi everyone, Nicole van der Hoeven here again, back with another Ask a Flooder, and today&amp;rsquo;s question is: &amp;ldquo;How do I install Element?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Now, I already made a previous video on how to get started with Element, but I didn&amp;rsquo;t actually go into the details of how to install it, so that&amp;rsquo;s what I&amp;rsquo;m going to do in this video today. There are actually a few parts to installing Element, and all of these instructions are going to be on &lt;a href="http://element.flood.io/"&gt;element.flood.io&lt;/a&gt;. If you go onto the site and click on Install, you&amp;rsquo;ll see all of the instructions depending on which operating system you&amp;rsquo;re on.&lt;/p&gt;
&lt;p&gt;First, you need to install NodeJS. This is sort of like how, if you&amp;rsquo;re familiar with JMeter, you have to install Java before installing JMeter. NodeJS is what Element runs on. Secondly, you&amp;rsquo;ll need a package manager. You can use NPM or Yarn, but in this video, I&amp;rsquo;m going to take you through how to do it with Yarn. And thirdly, there&amp;rsquo;s installing Element itself.&lt;/p&gt;
&lt;p&gt;First, download NodeJS. I&amp;rsquo;m going to leave links in the description to all of the sites that I visit so that you can go through all of the instructions later. On the Node site, download whichever installer suits your operating system. Go through the installation steps, and afterwards, check to make sure that NodeJS is properly installed on your machine. You can do that by going into the terminal and typing:&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-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;node -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Just make sure that the version that&amp;rsquo;s shown here is the same version that you&amp;rsquo;ve downloaded.&lt;/p&gt;
&lt;p&gt;Secondly, install the latest version of Yarn. On the Yarn site, you&amp;rsquo;re going to have to choose your operating system and the version. We recommend using the latest stable version. And then go through the instructions for your operating system. After you&amp;rsquo;ve done that, check your Yarn installation by typing:&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-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yarn --version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the last step is installing Element. On the Element site, you can find the exact code that you need to type into your terminal. It&amp;rsquo;s:&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-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yarn global add @flood/element-cli
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So you can just copy that into your terminal. As of the time of this recording, the latest version of Element is 1.2.3. Looks like that&amp;rsquo;s installed. To check the version of Element, type:&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-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;element --version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So that&amp;rsquo;s how to install Element. We&amp;rsquo;ve gotten a lot of questions recently about Element in particular, so I&amp;rsquo;m going to answering them in future videos. Hope this helped, 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 05: How do I get started with Flood Element?</title><link>https://nicolevanderhoeven.com/blog/20200317-aaf05/</link><pubDate>Tue, 17 Mar 2020 20:58:12 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200317-aaf05/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/ask-a-flooder-05-how-do-i-get-started-with-flood-element-video"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/ask-a-flooder-05-how-do-i-get-started-with-flood-element-video"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;On this Ask a Flooder, I talk about getting started with Flood Element. Element is an open-source tool that is a good Selenium alternative for browser-based load testing. It runs Puppeteer under the hood to drive real browsers at scale and can be paired with Flood for cloud load testing.&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/oWtnStKrh98?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;If you&amp;rsquo;re sold on browser-based load testing and want to get started on Element, I think the easiest way to do that is by going to &lt;a href="http://element.flood.io"&gt;element.flood.io&lt;/a&gt; and clicking on Install on the upper left corner. You can follow those instructions to get started, and you can also click on the links on the left side if you get stuck.&lt;/p&gt;
&lt;p&gt;Once Element is installed, open up the directory and look at the examples folder. There you&amp;rsquo;ll find a lot of sample scripts that we&amp;rsquo;ve already made up for you. The easiest way to get started is to just modify some of these slightly so that you&amp;rsquo;re testing your site. For example, you could just change the URL and step names to make it appropriate for what you&amp;rsquo;re testing.&lt;/p&gt;
&lt;p&gt;Then, you can run it locally using the command element run the name of your test script, like test.ts, and then I also like to include the no-headless flag.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;element run test.ts --no-headless&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The no-headless flag is going to run a real browser, a Chromium browser, on your machine, so that you can see what the script is actually doing. This is a great way to debug and troubleshoot.&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;re ready to run your load test on the cloud, you can simply drag and drop your Element script into the Flood stream editor and then start your load test as usual.&lt;/p&gt;
&lt;p&gt;Check out the links in the description below for more information about Element, how to get started, and how to run an Element script on Flood.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://element.flood.io/"&gt;More about Element&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://guides.flood.io/scripting-and-tools/flood-element/getting-started-with-element"&gt;Getting started with Element&lt;/a&gt;&lt;/p&gt;</description></item><item><title>FOMO and performance testing: Why Robinhood went down</title><link>https://nicolevanderhoeven.com/blog/20200309-fomo-and-performance-testing/</link><pubDate>Mon, 09 Mar 2020 20:29:40 +0100</pubDate><guid>https://nicolevanderhoeven.com/blog/20200309-fomo-and-performance-testing/</guid><description>
&lt;link rel="canonical" href="https://www.flood.io/blog/fomo-and-performance-testing-why-robinhood-went-down"&gt;
&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.flood.io/blog/fomo-and-performance-testing-why-robinhood-went-down"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Angry customers flocked to the internet when the Robinhood investment brokerage app went down last Monday and part of Tuesday, leaving them unable to trade stocks on a day where Wall Street reported historic gains. Could this have been prevented?&lt;/p&gt;
&lt;p&gt;The answer is yes. Applications should always be assessed for risk and tested accordingly. Risk-based load testing helps unearth problems that would otherwise only surface in production. Testing applications end-to-end as a system instead of just as a collection of isolated components allows us to build software that is more resilient. The problem is that this type of testing can be difficult to carry out. In this article, I&amp;rsquo;ll go through the entire process.&lt;/p&gt;
&lt;h2 id="what-is-robinhood"&gt;What is Robinhood?&lt;/h2&gt;
&lt;p&gt;Robinhood is an app I&amp;rsquo;ve personally had my eye on since it opened a waiting list about five years ago for Australians wanting to see the American company come to our shores. It &lt;a href="https://australianfintech.com.au/local-start-stake-beats-us-giant-robinhood-bring-australians-free-share-trading/"&gt;doesn&amp;rsquo;t look like it&amp;rsquo;s happening&lt;/a&gt; now, but if that waiting list still exists, I&amp;rsquo;m on it.&lt;/p&gt;
&lt;p&gt;Robinhood is a brokerage app that takes inspiration from the legend it was named after to &amp;ldquo;give to the poor,&amp;rdquo; bring zero-commission trading to its customers. Instead of earning from commissions, Robinhood makes its money from &lt;a href="https://www.investopedia.com/articles/active-trading/020515/how-robinhood-makes-money.asp"&gt;a variety of other methods&lt;/a&gt;, including premium platform fees, interest on customers&amp;rsquo; uninvested capital, and payments received in exchange for coursing customers&amp;rsquo; orders through third-party market-makers. It&amp;rsquo;s an enticing premise, and one that the company has used in conjunction with mobile apps to appeal to millennials and technophiles.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200309-01.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Source: From &lt;a href="https://robinhood.com/us/en/"&gt;Robinhood&amp;rsquo;s homepage&lt;/a&gt;&lt;/em&gt;
‍&lt;/p&gt;
&lt;h2 id="what-caused-the-robinhood-app-to-fail"&gt;What caused the Robinhood app to fail?&lt;/h2&gt;
&lt;p&gt;Unfortunately, its wild success with the tech-savvy crowd also meant that when it went down last Monday morning in the US, its customers took to the internet in droves to draw attention to the failure. In a &lt;a href="https://blog.robinhood.com/news/2020/3/3/an-update-from-robinhoods-founders"&gt;blog post from Robinhood&lt;/a&gt;, the company&amp;rsquo;s co-founders, Baiju Bhatt and Vladimir Tenev, admitted that the outage was due to &amp;ldquo;stress on [their] infrastructure— which struggled with unprecedented load.&amp;rdquo;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The outages you have experienced over the last two days are not acceptable and we want to share an update on the current situation. Our team has spent the last two days evaluating and addressing this issue. We worked as quickly as possible to restore service, but it took us a while. Too long. - &lt;a href="https://blog.robinhood.com/news/2020/3/3/an-update-from-robinhoods-founders"&gt;Baiju Bhatt and Bladimir Tenev&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Bhatt and Tenev went on to explain that the load on their servers had caused a &amp;ldquo;thundering herd&amp;rdquo; effect. This effect describes a situation in which a backend server receives a large number of concurrent requests and, instead of different threads processing these requests simultaneously, all threads attempt to process the same request.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;ve ever played four-player Overcooked, it&amp;rsquo;s like having everyone sprint to a fire extinguisher to try to put out a fire from overcooked pasta, but instead, the constant button mashing means you just pass the extinguisher around and yell at each other while the fire rages on. Before you know it, the entire kitchen is on fire.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200309-02.jpeg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Source: From &lt;a href="https://twitter.com/csac0425/status/963053160259510277"&gt;Twitter user @csac0425&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So the technical cause of the outage was an infrastructure problem.&lt;/p&gt;
&lt;p&gt;But I think the REAL cause was FOMO.&lt;/p&gt;
&lt;h2 id="what-is-fomo"&gt;What is FOMO?&lt;/h2&gt;
&lt;p&gt;FOMO is the Fear Of Missing Out, and it&amp;rsquo;s a phenomenon that&amp;rsquo;s been particularly exacerbated by social media. Instead of only hearing news from people you interact with in the physical world, it just takes a few seconds to open up Twitter on your smartphone and see what thousands of people are talking about. Twitter will even helpfully tell you what&amp;rsquo;s &amp;ldquo;trending&amp;rdquo; in your country, and other social networks also employ algorithms to determine what messages to show you.&lt;/p&gt;
&lt;h2 id="how-does-fomo-affect-application-performance"&gt;How does FOMO affect application performance?&lt;/h2&gt;
&lt;p&gt;We can see FOMO in how people have reacted to the coronavirus COVID-19. Despite pleas to leave masks for medical professionals at real risk, people have bought out the stock for these masks despite living in countries with little to no sign of the coronavirus. In Sydney, Australia, residents are stockpiling toilet paper (of all things) in large quantities, clearing out shelves from supermarkets, and &lt;a href="https://www.bbc.com/news/world-australia-51731422"&gt;getting into knife fights over toilet paper&lt;/a&gt; due to their panic at the thought of doing without.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200309-03.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This photo of an empty toilet paper aisle was taken by our Principal Engineer, &lt;a href="https://github.com/lachie"&gt;Lachie Cox&lt;/a&gt;, in a supermarket in Sydney last week.&lt;/em&gt;
‍
FOMO of this magnitude ultimately also manifests itself in the stock market. The Dow Jones Industrial Average, which represents the performance of the top 30 largest companies in the US, dropped by 3,500 points last week amidst fears that the coronavirus would stall production in countries most affected by COVID-19, leading to lower returns across the board.&lt;/p&gt;
&lt;p&gt;Then, an abrupt about-face. The Dow went from recording its &lt;a href="https://nypost.com/2020/03/09/dow-loses-over-2000-points-worst-single-day-drop-ever-as-oil-prices-crash/"&gt;biggest &lt;em&gt;ever&lt;/em&gt; loss in a single day on Thursday&lt;/a&gt; to posting a record gain of 1,200 points on Monday.&lt;/p&gt;
&lt;p&gt;Guess who gets to adjust to all this volatility.&lt;/p&gt;
&lt;p&gt;Robinhood&amp;rsquo;s founders reported that the &amp;ldquo;highly volatile and historic market conditions; record volume; and record sign-ups&amp;rdquo; contributed to the infrastructure issues they faced. We can only imagine just how many users they saw on their systems during this period.&lt;/p&gt;
&lt;p&gt;FOMO creates mass hysteria and panic, both of which cause customers to behave irrationally and likely very differently than previously recorded. So how do you create a workload model that accounts for this volatility? How do you tailor your load tests for FOMO? I&amp;rsquo;ll run you through the process, using Robinhood as an example.&lt;/p&gt;
&lt;h2 id="does-your-application-require-fomo-load-testing"&gt;Does your application require FOMO load testing?&lt;/h2&gt;
&lt;p&gt;All testing should be risk-based. Start with why: why should you test an application component? Why does your application require this kind of testing or that one?&lt;/p&gt;
&lt;p&gt;In Robinhood&amp;rsquo;s case, there were a few indicators that pointed to the necessity of FOMO testing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A customer base made up of a younger, tech-savvy generation&lt;/strong&gt;. ‍This demographic is very likely to take to social media with complaints, making negative publicity a real risk.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Complexity&lt;/strong&gt;. ‍Robinhood&amp;rsquo;s systems must receive customers&amp;rsquo; orders, forward and place those orders to market makers, and display real-time market data. Robinhood customers can also purchase options on stocks as well as cryptocurrency, further increasing the complexity.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Financial component&lt;/strong&gt;. ‍Anything that involves taking people&amp;rsquo;s money should have a high priority for any testing.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;When it comes to your money, we know how important it is for you to have answers. - &lt;a href="https://blog.robinhood.com/news/2020/3/3/an-update-from-robinhoods-founders"&gt;Baiju Bhatt and Bladimir Tenev&lt;/a&gt;, co-founders of Robinhood&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Record-breaking growth&lt;/strong&gt;. ‍Robinhood had 1 million users in 2016, 6 million in 2018, and 10 million last December, &lt;a href="https://www.cnbc.com/2019/12/04/start-up-robinhood-tops-10-million-accounts-even-as-industry-follows-in-free-trading-footsteps.html"&gt;according to CNBC&lt;/a&gt;. Exponential growth brings some major growing pains.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Industry history of expensive failures&lt;/strong&gt;. ‍&lt;a href="https://qz.com/1812086/robinhood-brokerage-app-suffers-second-day-of-outages/"&gt;Quartz points out&lt;/a&gt; that software or infrastructure failures have cost the financial industry millions in recent years.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Recent legal action&lt;/strong&gt;. The regulatory body FINRA &lt;a href="https://www.cnn.com/2019/12/19/investing/robinhood-trading-app-fine-finra/index.html"&gt;fined Robinhood&lt;/a&gt; US$1.25 million just last December for placing orders for customers without looking for the lowest price. While this isn&amp;rsquo;t a huge fine for a company that was &lt;a href="https://www.bloomberg.com/news/articles/2019-07-22/robinhood-is-worth-7-6-billion-after-new-funding-round"&gt;valued at US$7.6 billion last July&lt;/a&gt;, any legal action should make a company tread more carefully.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are solid reasons to warrant load testing Robinhood&amp;rsquo;s systems beyond just &amp;ldquo;expected&amp;rdquo; load.&lt;/p&gt;
&lt;h2 id="planning-for-fomo"&gt;Planning for FOMO&lt;/h2&gt;
&lt;p&gt;Once you&amp;rsquo;ve determined that your application is susceptible to FOMO, the next thing to do is plan how to structure your load tests to include its effect in your test runs.&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;Robinhood consists of three apps: two for mobile (iOS and Android) and one for the web. It is currently only available to US residents, which means that getting mobile apps downloaded is problematic as it would entail changing countries in the app stores to get access. Since I live in the Netherlands and I don&amp;rsquo;t want to do that, I&amp;rsquo;ll focus on the web app specifically when scripting the load test, and I&amp;rsquo;ll assume that the same underlying application servers service both web and mobile apps.&lt;/p&gt;
&lt;h3 id="workload-modeling"&gt;Workload modeling&lt;/h3&gt;
&lt;h4 id="business-processes-to-test"&gt;Business processes to test&lt;/h4&gt;
&lt;p&gt;Given that the app went down on a day where markets were &lt;em&gt;up&lt;/em&gt;, we can assume that most of the people on Robinhood&amp;rsquo;s apps were doing one of two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Signing up&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Buying shares&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We should ideally test both, but let&amp;rsquo;s focus on signups here because it&amp;rsquo;s easier to test without access to the actual app (which requires a US social security number).&lt;/p&gt;
&lt;h4 id="number-of-virtual-users-at-peak-load"&gt;Number of virtual users at peak load&lt;/h4&gt;
&lt;p&gt;Let&amp;rsquo;s try to come up with a number of users that we can use as Robinhood&amp;rsquo;s peak hourly load. This task would be easier if Robinhood shared their analytics, but we can still make some educated guesses with what &lt;em&gt;has&lt;/em&gt; been made public.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200309-04.png" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Source: Image from &lt;a href="https://blog.apptopia.com/robinhood-now-has-more-mobile-monthly-active-users-than-the-top-legacy-providers-combined"&gt;Apptopia&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.apptopia.com/robinhood-now-has-more-mobile-monthly-active-users-than-the-top-legacy-providers-combined"&gt;According to Apptopia&lt;/a&gt;, Robinhood&amp;rsquo;s highest number of mobile installations was in 2018, when it saw 2 million downloads of its mobile app in a quarter. This period coincides with when Robinhood released cryptocurrency trading support, which looks like increased signups—in the third quarter of 2019, this figure was about 1.5 million. 2 million quarterly downloads translates to about 666,666 downloads per month. Let&amp;rsquo;s call that 700,000 and take this number of mobile downloads as a starting figure.&lt;/p&gt;
&lt;p&gt;The stock market is only open on the weekdays, so we can divide 700,000 signups a month by 20 days, and we get 35,000 signups a day. The markets are also only open for about 7 hours a day, but the load probably isn&amp;rsquo;t evenly spread out across the 7 hours— I would expect that people would have more time during lunch to sign up for Robinhood. So let&amp;rsquo;s say that the majority of those signups would happen within three hours (from 11 am to 2 pm, for example). By dividing 35,000 signups per day by 3 hours, we get about 11,667 users per hour. Let&amp;rsquo;s round that up to 12,000.&lt;/p&gt;
&lt;p&gt;How do we translate this to the number of virtual users we need to run? Let&amp;rsquo;s think about how long each user stays on the app. The signup process does require approval, so that&amp;rsquo;s a hard stop— new users won&amp;rsquo;t be able to sign up and then start trading immediately afterwards. &lt;a href="https://robinhood.com/us/en/support/articles/360001213123/open-my-account/"&gt;This approval could take up to a day&lt;/a&gt;, or up to seven days if documents are required.&lt;/p&gt;
&lt;p&gt;Looking at the application form itself, we can see it is relatively standard and requires only information that most people are likely to have handy (social security number and contact details). I timed how long it took me to go through the part of it I could access, and I estimated that 10 minutes would be sufficient time to go through all the tabs.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200309-05.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://signup.robinhood.com/?"&gt;Robinhood&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We want to spread out users evenly across the hour— that is, we don&amp;rsquo;t want 12,000 users to sign up and leave, all within 10 minutes. We want equal portions of those users to be signing up throughout the entire hour. Dividing 12,000 by 6 (the number of 10-minute intervals in an hour), we get 2,000. 2,000 is the number of threads we need active at any one point of time. Each of those threads signs up one user for 10 minutes, then signs up 5 more users until the hour is up.&lt;/p&gt;
&lt;p&gt;So we have our figure: we need 2,000 &lt;em&gt;virtual&lt;/em&gt; users per hour to simulate 12,000 signups in an hour.&lt;/p&gt;
&lt;h3 id="test-scenarios"&gt;Test scenarios&lt;/h3&gt;
&lt;p&gt;In addition to running the standard battery of load tests, testing for FOMO requires exploring the upper limits of the application. Assuming the peak load testing goes well, we can use the 2,000 virtual users per hour figure from our peak load calculations as a starting point for these more destructive tests. To this end, here are some test scenarios I&amp;rsquo;d consider running if I were testing the Robinhood app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Soak testing&lt;/strong&gt;. ‍Soak testing means running typically a little less than the peak load profile, but over a longer amount of time. In Robinhood&amp;rsquo;s case, perhaps we could run 1,000 virtual users for 8 hours. We would expect that the response times reported during this test would be the same; otherwise, there is likely a performance bottleneck, such as a memory leak.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stress testing&lt;/strong&gt;. ‍Stress testing means increasing the number of users on an application at regular increments until the application crashes. We can start with 2,000 virtual users per hour, and then add 500 users every 30 minutes to see how the application handles it. This test helps determine how much room there is for growth.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200309-06.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Source: Stepped load profile for stress testing, generated in JMeter&lt;/em&gt;
‍&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Resilience testing&lt;/strong&gt;. ‍Resilience testing involves running the peak load test and then simulating an outage by turning off key components to see how the application behaves. If two servers share the load, for instance, we could turn one off and check to make sure that the user sessions on the terminated node are moved over onto the remaining node. This test shows whether the application recovers gracefully from an unforeseen event.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All these tests help us prepare for the unexpected, and they might have identified the &amp;ldquo;thundering herd&amp;rdquo; problem that contributed to Robinhood&amp;rsquo;s outage.&lt;/p&gt;
&lt;h2 id="scripting-for-fomo"&gt;Scripting for FOMO&lt;/h2&gt;
&lt;h3 id="tool-selection"&gt;Tool selection&lt;/h3&gt;
&lt;p&gt;To test mobile as well as web apps, I would typically use a protocol-level load testing tool like JMeter to simulate the load. However, &lt;a href="https://thenewstack.io/how-id-load-test-the-iowa-caucus-app/"&gt;I&amp;rsquo;ve already done that&lt;/a&gt;. I also noticed that Robinhood makes use of some dynamic parameters, such as a csrf token:&lt;/p&gt;
&lt;p&gt;‍&lt;img src="https://nicolevanderhoeven.com/assets/20200309-07.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Source: Chrome Developer Tools on &lt;a href="https://signup.robinhood.com/?"&gt;Robinhood&lt;/a&gt;&lt;/em&gt;
‍
We can usually find the value of this token in the response of the previous page. It is a security feature to allow Robinhood to verify that the same users make all requests in the same session. Tokens can be scripted around in a tool like JMeter, but it can be time-consuming. So for this article, I decided to show another tool that makes this problem go away. I used &lt;a href="https://element.flood.io/"&gt;Flood Element&lt;/a&gt;, which is an open-source tool we created based on Puppeteer. One of its advantages is that it runs on the browser level. Instead of diving into HTTP requests and tokens, I just told Element which buttons to click.&lt;/p&gt;
&lt;p&gt;I wanted a script that would do the following things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Navigate to Robinhood&amp;rsquo;s home page.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click on &amp;ldquo;Sign Up&amp;rdquo;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click on the &amp;ldquo;Get Your Free Stock&amp;rdquo; button.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fill out the signup form.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note that I stopped short of actually submitting the form because I don&amp;rsquo;t want to create dummy accounts on Robinhood&amp;rsquo;s database— I just want to show how this flow can be scripted with Element.&lt;/p&gt;
&lt;p&gt;To help me identify the elements on the page that I wanted the script to interact with, I used Chrome&amp;rsquo;s built-in Developer Tools. Specifically, I used the Inspect Element button (in orange below) to click on a field and find where it was in the code.&lt;/p&gt;
&lt;p&gt;‍&lt;img src="https://nicolevanderhoeven.com/assets/20200309-08.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;For instance, to find out how to identify the email field, I right-clicked on the code on the right, hovered over Copy, and then clicked Copy selector.&lt;/p&gt;
&lt;p&gt;‍&lt;img src="https://nicolevanderhoeven.com/assets/20200309-09.png" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;This gave me the value &lt;code&gt;#signup_email_field&lt;/code&gt;, which I then used in the script like this:&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:#75715e"&gt;//Type Email address
&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;By&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;signup_email_field&amp;#39;&lt;/span&gt;),&lt;span style="color:#e6db74"&gt;&amp;#39;nicole@flood.io&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s the script that I ended up with:&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;step&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;TestSettings&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Until&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;By&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;MouseButtons&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Device&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Driver&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ENV&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;@flood/element&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:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;as&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;assert&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;assert&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;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;settings&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TestSettings&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;loopCount&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;clearCache&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;disableCache&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;actionDelay&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;stepDelay&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;screenshotOnFailure&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;userAgent&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;flood-element-test&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; () =&amp;gt; {
&lt;/span&gt;&lt;/span&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;01_Home&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;//Navigate to Robinhood homepage
&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;visit&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;lt;https://robinhood.com&amp;gt;&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:#75715e"&gt;//Validate text
&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;validation&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;By&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;visibleText&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;It’s Time to Do Money&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;wait&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Until&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;elementIsVisible&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;validation&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;takeScreenshot&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:#a6e22e"&gt;step&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;02_Signup&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 &amp;#34;Sign Up&amp;#34;
&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;signupBtn&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:#a6e22e"&gt;By&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;xpath&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;//a[@href=&amp;#34;&amp;lt;https://signup.robinhood.com&amp;gt;&amp;#34;]&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;signupBtn&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;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Validate text
&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;validation&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;By&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;visibleText&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Free Stock Waiting For You&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;wait&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Until&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;elementIsVisible&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;validation&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;takeScreenshot&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:#a6e22e"&gt;step&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;03_GetFreeStock&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 Get Your Free Stock
&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;freestockBtn&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:#a6e22e"&gt;By&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;xpath&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;//a[@href=&amp;#34;&amp;lt;https://signup.robinhood.com/?&amp;#34;&amp;gt;]&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;freestockBtn&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;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//Validate text
&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;validation&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;By&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;visibleText&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Make Your Money Move&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;wait&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Until&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;elementIsVisible&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;validation&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;takeScreenshot&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:#a6e22e"&gt;step&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;04_FillForm&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;//Type First name
&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;By&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;xpath&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;//input[@name=&amp;#34;first_name&amp;#34;]&amp;#39;&lt;/span&gt;),&lt;span style="color:#e6db74"&gt;&amp;#39;Nicole&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:#75715e"&gt;//Type Last name
&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;By&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;xpath&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;//input[@name=&amp;#34;last_name&amp;#34;]&amp;#39;&lt;/span&gt;),&lt;span style="color:#e6db74"&gt;&amp;#39;van der Hoeven&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:#75715e"&gt;//Type Email address
&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;By&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;signup_email_field&amp;#39;&lt;/span&gt;),&lt;span style="color:#e6db74"&gt;&amp;#39;nicole@flood.io&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:#75715e"&gt;//Type password
&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;By&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;xpath&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;//input[@name=&amp;#34;password&amp;#34;]&amp;#39;&lt;/span&gt;),&lt;span style="color:#e6db74"&gt;&amp;#39;demo123456&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&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;browser&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;takeScreenshot&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In every step, I also added a &lt;code&gt;takeScreenshot()&lt;/code&gt; , which is one of my very favorite features of Element. It&amp;rsquo;s so useful to be able to save these screenshots and use them to determine exactly what&amp;rsquo;s happening in the script. Here&amp;rsquo;s what it looks like running my Element script locally. The automated browser is on the left, and my terminal (iTerm) is on the right, running Element.&lt;/p&gt;
&lt;p&gt;‍&lt;img src="https://nicolevanderhoeven.com/assets/20200309-10.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="running-a-fomo-test"&gt;Running a FOMO test&lt;/h2&gt;
&lt;p&gt;Now we&amp;rsquo;ve got a script that runs locally. How do we run it at scale? Additionally, Robinhood won&amp;rsquo;t allow users outside the US to sign up. How do we make sure that our virtual users are allowed to sign up?&lt;/p&gt;
&lt;p&gt;The answer is a load testing platform like &lt;a href="https://flood.io/"&gt;Flood&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With Flood, running our script is a matter of uploading the script and selecting some options.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200309-11.png" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The Flood test design interface&lt;/em&gt;
‍
Flood also lets us choose which regions to generate load from. Below I&amp;rsquo;ve got it set up to run for an hour from four different US cities, with each one starting 500 users. This configuration gives us our 2,000 virtual user figure.&lt;/p&gt;
&lt;p&gt;‍&lt;img src="https://nicolevanderhoeven.com/assets/20200309-12.png" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;If this peak load test goes well, we could then go on to run the other test scenarios that we described earlier. Each one puts pressure on application servers in different ways, identifying performance bottlenecks.&lt;/p&gt;
&lt;h2 id="results-and-reruns"&gt;Results and reruns&lt;/h2&gt;
&lt;p&gt;Since Robinhood is a live application, I didn&amp;rsquo;t run the test— it&amp;rsquo;s never a good idea to load test a domain you don&amp;rsquo;t own when you&amp;rsquo;re talking about thousands of users. However, &lt;a href="https://api.flood.io/pfQuAGz3"&gt;here&amp;rsquo;s a shareable link&lt;/a&gt; to another small Element test I ran previously.&lt;/p&gt;
&lt;p&gt;Real-time dashboards like that one on Flood allow you to get a quick look into how the load test is running and to make any changes if necessary. When testing for FOMO, I think they&amp;rsquo;re invaluable. For example, during a stress test where users are added at regular intervals, a real-time dashboard would help you identify increases in response time as a result of the increased number of users. It would also let you monitor the test and stop it when necessary.&lt;/p&gt;
&lt;p&gt;From the link above, click on the right arrow on the lone transaction.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200309-13.jpg" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;That will take you to the Transaction Detail page. Remember those screenshots from Element? If you have any in your script, you&amp;rsquo;ll see them here, arranged according to time.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolevanderhoeven.com/assets/20200309-14.png" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;This lets you troubleshoot issues during FOMO testing and react quickly.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Even with sound load testing strategies in place, it&amp;rsquo;s challenging to plan for the massive spike in traffic that FOMO can bring, yet it&amp;rsquo;s necessary to do so. FOMO, as a phenomenon, is only going to increase in magnitude as social networks make it easier to spread fear, uncertainty, and doubt as well as information.&lt;/p&gt;
&lt;p&gt;We may not be able to determine precisely what will break, or when, but what we can do is put systems into place to plan for it. We can assess an application&amp;rsquo;s susceptibility to FOMO and plan for end-to-end performance engineering of the system as a whole. We can start with the assumption that applications will fail and then determine the most likely candidates for that failure. We can routinely expose systems to traffic and circumstances that are extraordinary, and in doing so, we can improve our preparedness for something like FOMO.&lt;/p&gt;
&lt;p&gt;FOMO is irrational and unpredictable— but that doesn&amp;rsquo;t mean it needs to be unexpected.&lt;/p&gt;</description></item></channel></rss>