RousselTMLEARNING

DevOps

Browser testing and synthetic monitoring with k6

Test a web application in a real browser with the k6 browser module, measure Core Web Vitals, and continuously monitor user journeys with synthetic tests.

1. The browser module #

A Chromium driven by k6.

Script #

import { browser } from 'k6/browser';
import { check } from 'k6';

export const options = {
  scenarios: {
    ui: {
      executor: 'shared-iterations',
      options: { browser: { type: 'chromium' } },
    },
  },
  thresholds: {
    browser_web_vital_lcp: ['p(75)<2500'],
    browser_web_vital_cls: ['p(75)<0.1'],
  },
};

export default async function () {
  const page = await browser.newPage();
  try {
    await page.goto('https://boutique.example.org/');
    await page.locator('input[name="q"]').fill('casque');
    await page.locator('button[type="submit"]').click();
    await page.waitForSelector('.resultats');
    check(await page.locator('h1').textContent(), { 'titre présent': (t) => t.includes('Résultats') });
  } finally {
    await page.close();
  }
}
docker run --rm -i grafana/k6:latest-with-browser run - < ui.js

The module measures Core Web Vitals (browser_web_vital_lcp, cls, inp, fcp, ttfb) like a real user.

Good practice: Combine a few browser VUs (user experience) and many HTTP VUs (load) in the same test: you then measure the degradation users feel when the backend is under pressure.

2. Synthetic monitoring #

Testing continuously, not just before a release.

Principle #

Synthetic monitoring regularly replays (every minute, from several regions) a journey or a request and alerts on failure. It detects an outage even without real traffic (at night, on a rarely visited page).

ToolUsage
Prometheus Blackbox exporterSimple HTTP, TCP, ICMP, DNS probes, open source
Grafana Synthetic MonitoringProbes and k6 scripts from global points of presence (Grafana Cloud)
Scheduled k6 (cron, Kubernetes CronJob)Full k6 scripts run periodically, results sent to Prometheus

Blackbox exporter #

# prometheus.yml
scrape_configs:
  - job_name: sondes-http
    metrics_path: /probe
    params: { module: [http_2xx] }
    static_configs:
      - targets: [https://boutique.example.org, https://api.example.org/health]
    relabel_configs:
      - { source_labels: [__address__], target_label: __param_target }
      - { source_labels: [__param_target], target_label: instance }
      - { target_label: __address__, replacement: blackbox:9115 }
- alert: SiteInjoignable
  expr: probe_success{job="sondes-http"} == 0
  for: 3m
  labels: { severity: critical }

Related articles

Load testing with Grafana k6: why, and which types of tests

Why test performance before production, the types of tests (smoke, load, stress, spike, soak, breakpoint) and…

Writing k6 scripts: requests, checks, scenarios and executors

The structure of a k6 script (init, setup, default, teardown), HTTP requests, checks, groups and tags, and mo…

Thresholds, metrics and results of a k6 test

Read the summary of a k6 test, understand the built-in metrics (http_req_duration, http_req_failed, iteration…

Keep learning

Support us

♥ SUPPORT US

Support RousselTM Learning

Courses, articles, labs and certificates stay free with no intrusive ads. A voluntary contribution, of any amount you choose, pays for hosting, lab environments and new content.

Contribute with PayPal Any amount · card or PayPal accountLearn more
QR code PayPal
Or scan this QR code with your phone

Thank you, every contribution counts!