Integrate k6-browser with LambdaTest

No more setting up Selenium to run concurrently with the load testing tool to understand user experience when the application is under heavy load; you have k6 now.

Donald Le
Automation with Love
6 min readAug 10, 2023

--

Photo by Rodion Kutsaiev on Unsplash

k6 is one of the first performance testing tools supporting protocol and browser-based testing. You can now run the performance test for your web application through the web browser, just like normal users would do. Sometimes you want to run the test in a device farm, such as saving the local machine’s resources to do other tasks, or you don’t have the operating system the tests require.

Understanding those needs, k6 recently implemented new features allowing you to integrate k6-browser with LambdaTest to trigger your performance testing for your web application on any device you want. In this article, let’s see how you could do it with k6-browser

The demo application

You will run the k6-browser test on an application showing my top ten favorite artists and songs on Spotify. :D

This application was built using Next.js for the front end and Spotify API to collect favorite artists and favorite songs.

The test scripts

Create a new file named spotifyDashboard-k6.js with the following code in it:

import { chromium } from 'k6/experimental/browser';
import { expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.3/index.js'


export default async function () {
const capabilities = {
'browserName': 'Chrome',
'browserVersion': '108',
'LT:Options': {
'platform': 'Windows 8',
'build': 'K6 Build',
'name': 'K6 Spotify Dashboard Test',
'user': __ENV.LT_USERNAME,
'accessKey': __ENV.LT_ACCESS_KEY,
'network': true,
'video': true,
'console': true,
'tunnel': false,
'tunnelName': '',
'geoLocation': 'None'
}
}

const wsURL = `wss://cdp.lambdatest.com/k6?capabilities=${encodeURIComponent(JSON.stringify(capabilities))}`
const browser = chromium.connect(wsURL)
const page = browser.newPage()

await page.goto('https://twilio-music-info-app-ha8m.vercel.app/');
page.screenshot({ path: 'screenshots/browserTestScreenshot.png' });

const songElements = await page.$$('a[class*="bg-gray-100 hover"]');
const artistElements = await page.$$('a[class*="flex items-center gap-5 p-4 overflow-hidden bg-gray-100 border-b"]');

expect(songElements.length).to.equal(10),

expect(artistElements.length).to.equal(10),

page.close()
browser.close();
}

In this scenario, you only use one virtual user with one iteration only because we are focusing on how to run the k6-browser test in LambdaTest. When you do not include the export const options variable in the test file, k6 will use only one virtual user with one iteration by default.

The capabilities the variable defines the browser and the machine that the test will be executed on LambdaTest. You’re telling LambdaTest to run the test using Windows 8 machine and Chrome version 108.

The wsURL variable defines the WebSocket address to connect to LambdaTest browser based on the encoded capabilities value.

To connect with the Chrome browser in LambdaTest, you use chromium.connect(wsURL) .

await page.goto('https://twilio-music-info-app-ha8m.vercel.app/');
page.screenshot({ path: 'screenshots/browserTestScreenshot.png' });

const songElements = await page.$$('a[class*="bg-gray-100 hover"]');
const artistElements = await page.$$('a[class*="flex items-center gap-5 p-4 overflow-hidden bg-gray-100 border-b"]');

expect(songElements.length).to.equal(10),

expect(artistElements.length).to.equal(10),

In this block of code, you tell the k6-browser to navigate to the Spotify music app URL to verify if the number of songs and the number of artists are equal to ten. To get all web elements that match a specific CSS collector, you’re using page.$$('css-Selector') method.

Note: Currently, if you’re using page.locator to locate an element, the k6-browser will only return one element that matches the locator, so you cannot get the correct song and artist number. That’s why you’re using page.$$() the method here, even though k6 recommends you use page.locator it to locate elements instead.

Run the test

To run the test, you need to export the information for your LambdaTest username and its access key.

export LT_USERNAME=your-user-name
export LT_ACCESS_KEY=your-access-key

Then run the following command:

K6_BROWSER_ENABLED=true k6 run spotifyDashboard-k6.js

You should see the similar result in the console as below:

 ✓ expected ${this} to equal 10

checks.................................: 100.00% ✓ 2 ✗ 0
data_received..........................: 1.1 MB 535 kB/s
data_sent..............................: 15 kB 6.9 kB/s
http_req_connecting....................: avg=3.18ms min=0s med=0s max=118ms p(90)=0s p(95)=0s
http_req_duration......................: avg=162.08ms min=33.26ms med=100.23ms max=449.34ms p(90)=348.07ms p(95)=353.14ms
http_req_receiving.....................: avg=138.24ms min=0s med=89ms max=425ms p(90)=303.59ms p(95)=319.19ms
http_req_sending.......................: avg=324.32µs min=0s med=0s max=2ms p(90)=1ms p(95)=1ms
http_req_tls_handshaking...............: avg=2.16ms min=0s med=0s max=80ms p(90)=0s p(95)=0s
http_reqs..............................: 37 17.501859/s
iteration_duration.....................: avg=2.11s min=2.11s med=2.11s max=2.11s p(90)=2.11s p(95)=2.11s
iterations.............................: 1 0.473023/s
vus....................................: 1 min=1 max=1
vus_max................................: 1 min=1 max=1
webvital_first_contentful_paint........: avg=615.59ms min=615.59ms med=615.59ms max=615.59ms p(90)=615.59ms p(95)=615.59ms
webvital_first_contentful_paint_good...: 1 0.473023/s
webvital_time_to_first_byte............: avg=194.19ms min=194.19ms med=194.19ms max=194.19ms p(90)=194.19ms p(95)=194.19ms
webvital_time_to_first_byte_good.......: 1 0.473023/s


running (00m02.1s), 0/1 VUs, 1 complete and 0 interrupted iterations
default ✓ [======================================] 1 VUs 00m02.1s/10m0s 1/1 iters, 1 per VU

Going to the LambdaTest dashboard, you can see the video recording of executing the test.

Understanding the metrics

k6-browser adopts the Google best practices for vital metrics to understand three important aspects of user experience:

  • Loading Performance
  • Interactivity
  • Visual Stability

In the console report, you can see the recorded performance metrics for your application. Besides default metrics like http_reqs or data_sent that you have when running tests for HTTP requests, you now have custom metrics for the UI web application performance:

webvital_first_contentful_paint........: avg=615.59ms min=615.59ms med=615.59ms max=615.59ms p(90)=615.59ms p(95)=615.59ms
webvital_first_contentful_paint_good...: 1 0.473023/s
webvital_time_to_first_byte............: avg=194.19ms min=194.19ms med=194.19ms max=194.19ms p(90)=194.19ms p(95)=194.19ms
webvital_time_to_first_byte_good.......: 1 0.473023/
  • webvital_first_contentful_paint : this metric measures the time from the application starts until the first content on the application page is rendered.
  • webvital_first_contentful_paint_good : the rating for the webvital_first_contentful_paint` . Because you only sent one iteration, the result is good.
  • webvital_time_to_first_byte : this metric measures the time from the time that the request is executed until the first byte of the response is received
  • webvital_time_to_first_byte_good : the rating for the webvital_time_to_first_byte. Because you only sent one iteration, the result is good.

Visualize the metrics

The console report is a short version of available metrics that the k6-browser captures. If you want to have all the metrics and be able to visualize them so that you can quickly understand how your UI web application works, you can visualize them using Prometheus to store the data and Grafana to visualize.

Clone the xk6-output-prometheus-remote repository created by Grafana team.

Run the following command from the root directory of the cloned repository:

docker compose up -d

You should see the Prometheus and Grafana containers up and running.

[+] Running 23/23
✔ grafana 9 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled 34.3s
✔ 4db1b89c0bd1 Pull complete 4.4s
✔ 5d826d07bc4b Pull complete 4.4s
✔ bd304fdbf49f Pull complete 4.8s
✔ ed59c63897ad Pull complete 4.9s
✔ 64bc06362185 Pull complete 5.0s
✔ a02d3acd2d42 Pull complete 5.0s
✔ c5d09a6787ef Pull complete 12.4s
✔ 749ebef77de4 Pull complete 27.4s
✔ a72374eecc76 Pull complete 27.4s
✔ prometheus 12 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled 40.5s
✔ 30ec41fb8fed Pull complete 10.6s
✔ e5f8ba06cb61 Pull complete 12.7s
✔ 5d47f929abda Pull complete 32.4s
✔ f98450aaa79e Pull complete 33.4s
✔ 2ca2eba21948 Pull complete 33.4s
✔ ff129d3d6d74 Pull complete 33.4s
✔ 4fee571a1cf5 Pull complete 33.5s
✔ ebe7f681b016 Pull complete 33.5s
✔ 51d55bf673c1 Pull complete 33.5s
✔ d033d1656b56 Pull complete 33.6s
✔ 93e64195a1ec Pull complete 33.6s
✔ 13595d3b00dd Pull complete 33.6s
[+] Building 86.6s (13/16)
[+] Building 86.9s (13/16)
[+] Building 88.6s (13/16)
[+] Building 89.5s (13/16)
[+] Building 89.8s (13/16)
[+] Building 140.2s (17/17) FINISHED
=> [k6 internal] load build definition from Dockerfile

Then run the following command to export metrics to the Prometheus database.

K6_BROWSER_ENABLED=true k6 run -o experimental-prometheus-rw spotifyDashboard-k6.js

You should see a similar output as below:

          /\      |‾‾| /‾‾/   /‾‾/   
/\ / \ | |/ / / /
/ \/ \ | ( / ‾‾\
/ \ | |\ \ | (‾) |
/ __________ \ |__| \__\ \_____/ .io

execution: local
script: localSpotifyDashBoardApp.js
output: Prometheus remote write (http://localhost:9090/api/v1/write)

scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
* default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)

Now, when you go to the Prometheus dashboard, you can see the k6 metrics are stored in the Prometheus database.

You can also go to the Grafana dashboard to create the dashboard for the captured k6 metrics. Below is an example Grafana dashboard with metrics for webvitals , HTTP requests receiving 99 percentile, and iterations.

The article taught you how to integrate k6 with LambdaTest to implement browser testing. You also learned how to export test metrics to the Prometheus database so that you can visualize the metrics using the Grafana dashboard to grasp the test result quickly.

If you want to learn more about how k6-browser works, visit k6 documentation.

--

--

Donald Le
Automation with Love

A passionate automation engineer who strongly believes in “A man can do anything he wants if he puts in the work”.