Run load test/performance test with Artillery
Introduction
What is performance testing? And why should you do a load test?
Performance testing is software testing that evaluates how well an application performs under different workloads.
This involves measuring various metrics such as response time, bandwidth, and scalability to ensure that the application can handle the expected number of requests from users without degrading performance or crashing. Performance testing can also identify performance issues and bottlenecks, it helps you make necessary changes to optimize performance. The goal of this is to ensure that the application delivers a smooth, fast, and reliable user experience even under heavy load conditions.
About Artillery.io
Artillery.io is an open-source performance testing tool that allows you to test the performance and scalability of your web applications, APIs, and microservices. You can simulate real user behavior, generate load from multiple sources, and test your application flow according to the scenario.
Supported protocols
Artillery.io is written in Node.js and supports HTTP, Websocket, and socket.io protocols.
Also, you can use Artillery’s plugin to test another stack like HLS (HTTP Live Streaming), Amazon Kinesis, Apache Kafka, etc.
Script formatting
Unlike other popular testing tools, Artillery.io provides a flexible YAML-based syntax for defining your load-testing scenarios. It also supports a JSON format.
Install & Basic features
Install
You can globally install Artillery.io via npm or yarn by following this command:
#npm npm install -g artillery
#yarn yarn global add artillery
or you can also install it as a dev dependency of a Node.js project with:
npm install -D artillery
Fast test
Use the quick subcommand so that you can run a test without writing a test script. For example, to run 10 virtual users (VUs), each of them makes 20 requests to the address http://localhost:3000/:
artillery quick -c 10 -n 20 http://localhost:3000/api/user
The -c parameter specifies the total number of VUs, and the -n indicates the number of requests per VU.
Run a test script
The run subcommand runs a test script from the local machine. The basic way to run a test is with:
artillery run script.yaml -o report.json
The -o parameter is the option to write a JSON report to a file.
Export report
artillery report report.json -o report.html
The report subcommand allows converting the JSON report generated by the run subcommand into a new HTML report.
Writing a simple load test
In the tutorial below we will use YAML syntax, first we need to create a file name like “script.yml”, then we start by defining the “config” section at the top of a file.
Config Section
We need to set the base URL for your test script with the target option:
config: target: "http://localhost:3000/api"
Next, we’ll start to define the load phase, a load phase defines how Artillery generates new VUs in a specified time period:
config: ... phases: - duration: 60 arrivalRate: 100
Scenarios Section
We can define one or more scenarios. Each scenario definition is an object which requires a flow attribute.
scenarios: - name: "Get All Users" flow: - get: url: "/user" qs: limit: 10 offset: 20
In the ‘flow’ property, we continue to define the HTTP method as an object attribute, then we need to define the path of the API, we also can set a query string or set form body like URL-encoded forms, Multipart forms or JSON.
Save the scripts and then run your test script.
Realistic User Flows
For example, a user flow could be:
config: target: "http://localhost:3000/api" phases: - duration: 120 arrivalRate: 10 name: "Preparing" - duration: 240 arrivalRate: 30 rampTo: 100 name: "Increasing" - duration: 600 arrivalRate: 100 name: "Sustained Load" payload: path: "login.csv" cast: false fields: - "user" - "pass" processor: "./processor.js" before: flow: - log: "Get auth token" - post: url: "/auth/login" json: username: "{{user}}" password: "{{pass}}" capture: - json: $.tokens.accessToken as: token scenarios: - name: "Search Users" flow: - get: url: "/user" headers: authorization: "Bearer {{ token }}" - name: "Create New User" flow: - post: url: "/user" beforeRequest: "setJsonBody" headers: authorization: "Bearer {{ token }}"
In the above script, we have three phases in the configuration:
- The first phase creates 10 VUs per second and sends them to the application for 2 minutes.
- In the second phase, the load test will start at 30 users per second and gradually increase to 100 users per second over 4 minutes.
- The final phase simulates a sustained load of 100 users per second for 10 minutes.
By using multiple phases allows you to accurately simulate realistic traffic scenarios and evaluate your application’s ability to handle a sudden barrage of requests.
In the first flow of scenarios, each of the VUs requests GET | “Search user”, then in the second flow they’ll request POST | “Create user”.
To make it easy to generate data. In this way, before executing the request. We use the setJsonBody function on the custom hook beforeRequest, The function setJsonBody is defined in the processor.js file referenced in config.processor.
# processor.js const { faker } = require("@faker-js/faker"); function setJsonBody(requestParams, context, ee, next) { var body = { username: faker.internet.userName(), password: faker.internet.password(3), email: faker.internet.exampleEmail(), name: faker.name.fullName(), role: faker.datatype.number({ min: 0, max: 1 }), }; requestParams.json = body; return next(); } module.exports = { setJsonBody, };
Compare to K6 load testing
Artillery and k6 are both open-source tools for performance testing and have similar features such as extensibility, integration with CI/CD tools, and the ability to set test patterns. However, there are some differences between them. Artillery is written in Node.js while k6 is written in Go. So, Artillery is slower than k6, because it isn’t multithreaded and uses more memory. Here are the charts comparing memory usage between k6 with Artillery and other tools:
Memory usage
Memory usage per VU level
In conclusion, Artillery and k6 are both powerful tools. However, k6 has more advantages than Artillery. If you want to write a simple load test, Artillery is a good solution that uses YAML syntax.
References
https://www.artillery.io/
https://k6.io/blog/comparing-best-open-source-load-testing-tools/