TESTEVERYTHING

Friday, 16 October 2026

Performance Testing with K6 and Playwright

 

Performance Testing with K6 and Playwright

A step-by-step guide from setup to execution—combining functional browser journeys with realistic performance testing.

K6PlaywrightBrowser performanceCI/CD ready
In brief: Playwright validates that a user journey works. k6 measures how that journey behaves under load. This guide shows how to use both in one JavaScript-oriented workflow.

Why Combine K6 with Playwright?

Modern web applications must be fast and functionally correct under real-world traffic. Playwright is excellent for end-to-end verification, while k6 is purpose-built for load and performance testing. K6’s experimental browser module provides a Playwright-inspired API for browser-level performance checks.

Playwrightk6
Primary purposeFunctional and E2E testingLoad and performance testing
Execution modelReal browser, single/few sessionsThousands of VUs at protocol level, or smaller browser-level loads
ScriptingJavaScript/TypeScript, Python, Java, .NETJavaScript (Goja runtime)
MetricsPass/fail assertionsLatency, throughput, error rate, thresholds
Browser APINativek6/experimental/browser, Playwright-inspired

Pairing the tools lets teams reuse selectors and user flows, validate critical journeys such as login or checkout, capture browser metrics alongside load metrics, and run tests from CI/CD.

Prerequisites and Setup

You’ll need Node.js v16 or later with npm, a code editor, optional Git, basic JavaScript and selector knowledge, and administrator or sudo access for k6 and browser dependencies.

Initialize a Node.js project

mkdir k6-playwright-perf-test
cd k6-playwright-perf-test
npm init -y

Install Playwright

npm install -D @playwright/test
npx playwright install --with-deps

Keep a Playwright functional suite in the repository so the journey can be verified before it is performance-tested.

Install k6

# macOS
brew install k6

# Windows
choco install k6

# Debian / Ubuntu
sudo apt-get update
sudo apt-get install k6

# Docker alternative
docker pull grafana/k6

k6 version

Enable the browser module

Modern k6 releases bundle the experimental browser module. A recent release such as k6 v0.47.0 or later is recommended. Older releases may require an xk6 custom build:

go install go.k6.io/xk6/cmd/xk6@latest
xk6 build --with github.com/grafana/xk6-browser@latest

Recommended project structure

k6-playwright-perf-test/
├── playwright-tests/
│   └── login.spec.js
├── k6-tests/
│   └── login.perf.js
├── package.json
└── playwright.config.js

Writing the Playwright Functional Test

First validate the login flow functionally, then translate the same selectors and steps into the k6 script.

// playwright-tests/login.spec.js
const { test, expect } = require('@playwright/test');

test('user can log in', async ({ page }) => {
  await page.goto('https://test.k6.io/my_messages.php');
  await page.fill('#login', 'admin');
  await page.fill('#password', '123');
  await page.click('input[type="submit"]');
  await expect(page.locator('h3')).toContainText('Welcome, admin!');
});
npx playwright test playwright-tests/login.spec.js

Writing the K6 Performance Test

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

export const options = {
  scenarios: {
    ui: {
      executor: 'shared-iterations',
      vus: 5,
      iterations: 10,
      options: { browser: { type: 'chromium' } },
    },
  },
  thresholds: {
    checks: ['rate==1.0'],
    browser_http_req_duration: ['p(95)<2000'],
  },
};

export default async function () {
  const page = browser.newPage();
  try {
    await page.goto('https://test.k6.io/my_messages.php');
    await page.locator('#login').type('admin');
    await page.locator('#password').type('123');
    await Promise.all([
      page.waitForNavigation(),
      page.locator('input[type="submit"]').click(),
    ]);
    const heading = page.locator('h3');
    check(heading, {
      'welcome message is visible': (h) =>
        h.textContent().includes('Welcome, admin!'),
    });
  } finally {
    page.close();
  }
}

Key concepts: browser.newPage() creates a browser page, page.locator() mirrors Playwright’s selector model, scenarios define the load shape, thresholds define objective pass/fail criteria, and check() records assertions without acting like a test-runner exception.

Configuring Test Options

export const options = {
  scenarios: {
    ui: {
      executor: 'ramping-vus',
      startVUs: 1,
      stages: [
        { duration: '30s', target: 5 },
        { duration: '1m', target: 5 },
        { duration: '30s', target: 0 },
      ],
      options: { browser: { type: 'chromium' } },
    },
  },
  thresholds: {
    browser_http_req_duration: ['p(90)<1500', 'p(95)<2500'],
    checks: ['rate>0.95'],
  },
};
  • Executors: Choose shared-iterations, per-vu-iterations, constant-vus, ramping-vus, constant-arrival-rate, or ramping-arrival-rate according to the desired concurrency or arrival rate.
  • Stages: Ramp VUs gradually. Browser VUs are resource-intensive; keep counts modest, typically under 10–20 concurrent browser VUs per machine.
  • Thresholds: Tie automated pass/fail behavior to measurable SLAs.

Executing the Performance Test

k6 run k6-tests/login.perf.js

# Docker
docker run --rm -i -v $(pwd):/scripts grafana/k6 \
  run /scripts/k6-tests/login.perf.js

# JSON output
k6 run --out json=results.json k6-tests/login.perf.js

# InfluxDB output
k6 run --out influxdb=http://localhost:8086/k6 k6-tests/login.perf.js

Analyzing and Interpreting Results

checks.........................: 100.00% ✓ 10  ✗ 0
browser_http_req_duration......: avg=812ms p(95)=1.3s
browser_web_vital_lcp...........: avg=1.1s
iteration_duration..............: avg=2.3s
vus..............................: 5
  • checks: The pass rate of all check() assertions.
  • browser_http_req_duration: Time taken by browser-initiated HTTP requests.
  • browser_web_vital_*: Browser-level LCP, FCP, and CLS metrics when supported.
  • iteration_duration: Total duration of a complete script iteration.
  • Threshold results: k6 returns a non-zero exit status when a threshold fails, making it suitable for CI/CD gates.

Best Practices and Common Pitfalls

  • Keep browser-level VUs low. Use protocol-level k6 tests for high concurrency and browser tests for representative journeys.
  • Separate concerns. Use Playwright for strict functional assertions and cross-browser coverage; use k6 for performance-focused checks.
  • Use realistic think-time. Prefer wait-for-selector patterns or carefully chosen pauses to mimic user pacing.
  • Set meaningful thresholds tied to actual service-level objectives.
  • Run in CI/CD and use k6’s exit code as a quality gate.
  • Isolate test data with unique users or records per VU and iteration.
  • Monitor the test runner. CPU and memory limits can bottleneck the generator before the target system.

Conclusion

Combining k6 with a Playwright-style browser API provides a consistent way to validate functional correctness and real-world performance. Verify the flow with Playwright, translate it to a k6 browser script, define a realistic scenario and thresholds, execute it, and use the resulting metrics to catch regressions early.

Frequently Asked Questions

Is k6’s browser module the same as Playwright?

No. It is a Playwright-inspired API designed for performance testing in k6. Playwright remains the dedicated functional and E2E tool.

Can I run thousands of virtual users with the browser module?

Browser-level VUs are resource-heavy. Use protocol-level k6 tests for high-concurrency load and browser-level tests for smaller, representative populations.

Do I need Playwright installed to use k6’s browser module?

No. k6 runs its browser module independently. Playwright is complementary and useful for validating flows and reusing selectors.

Can these tests run in a CI/CD pipeline?

Yes. Both tools are CLI-driven and return process exit codes suitable for GitHub Actions, GitLab CI, Jenkins, and similar systems.

Version note: The browser module is experimental and its API may change. Verify code samples and configuration against the current official k6 and Playwright documentation before publishing or adopting them in production.

Tuesday, 13 October 2026

 Windows automation guide

How to Set Up Playwright on Windows

A practical, step-by-step path from installing Node.js to running your first cross-browser automated test.

Introduction

Playwright is a modern end-to-end testing and browser automation framework built by Microsoft. It supports Chromium, Firefox, and WebKit through a single API, making cross-browser testing faster and more reliable.

If you’re a QA engineer, developer, or automation enthusiast using Windows, this guide covers everything you need to get Playwright running—from installing prerequisites to executing your first automated test script.

What you’ll have at the end: a functional Playwright environment on Windows and a working test example you can build on.

Prerequisites

  • A Windows 10 or Windows 11 machine
  • Administrator access to install software
  • A stable internet connection for browser binaries
  • A code editor such as Visual Studio Code (recommended)

Step-by-step setup

1. Install Node.js

Playwright runs on Node.js. Visit nodejs.org, download the Windows LTS release, and run the .msi installer with the default options.

Verify the installation in Command Prompt or PowerShell:

node -v
npm -v

If both commands return version numbers, Node.js and npm are ready.

2. Install Visual Studio Code

VS Code is optional, but its Playwright Test extension provides convenient test running and debugging. Download it from code.visualstudio.com, then install the Playwright Test for VSCode extension from the Extensions Marketplace.

3. Create a project folder

mkdir playwright-demo
cd playwright-demo

4. Initialize a Node.js project

npm init -y

This creates a package.json file for managing project dependencies.

5. Install Playwright

npm init playwright@latest

Choose your preferences when prompted:

  • Language: TypeScript is recommended, though JavaScript is supported.
  • Test folder: The default tests folder is a good choice.
  • GitHub Actions: Optional, and useful for CI/CD.
  • Browsers: Choose Yes to download them now.

The generated project will look like this:

playwright-demo/
├── tests/
│   └── example.spec.ts
├── playwright.config.ts
├── package.json
└── node_modules/

6. Verify browser installation

If browsers were not installed automatically, or you want to reinstall them, run:

npx playwright install

This downloads the Chromium, Firefox, and WebKit binaries needed for multi-browser testing.

7. Run your first test

npx playwright test

Playwright runs the generated sample test in headless mode and prints the results in your terminal.

8. View the HTML report

npx playwright show-report

The interactive report opens in your default browser and includes test steps, screenshots, traces, and execution timelines.

9. Run tests in headed mode

Watch browser actions in real time, or target one browser project:

npx playwright test --headed
npx playwright test --project=chromium

10. Write a custom test

Create tests/sample.spec.ts:

import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  await expect(page).toHaveTitle(/Playwright/);
});

Run the test with:

npx playwright test sample.spec.ts

If it passes, your Playwright environment is fully functional.

Common setup issues on Windows

IssuePossible causeSuggested fix
npx not recognizedNode.js is missing or not on PATHReinstall Node.js and ensure “Add to PATH” is checked.
Browsers fail to downloadFirewall or antivirus blocks downloadsCheck security software or run the terminal as Administrator.
Timeout errorsSlow network or incorrect selectorsIncrease the timeout in playwright.config.ts and verify selectors.
PowerShell scripts blockedExecution policy restrictionRun Set-ExecutionPolicy RemoteSigned -Scope CurrentUser in PowerShell (Admin).

Always check configuration changes and security-related commands against your organization’s IT policies.

Best practices after setup

  • Update Playwright and browser binaries with npm install -D @playwright/test@latest, followed by npx playwright install.
  • Use the Trace Viewer with npx playwright show-trace to debug failures.
  • Organize larger test suites using the Page Object Model (POM).
  • Integrate with GitHub Actions, Jenkins, or Azure DevOps for CI/CD.

Conclusion

Once Node.js is installed, setting up Playwright on Windows takes only a few commands. You now have multi-browser support, rich reporting, and powerful debugging tools ready for your automation work.

Take your test automation further

Subscribe for more Playwright tutorials, best practices, and real-world automation strategies delivered to your inbox.

FAQs

Does Playwright work on Windows 11?Yes. Playwright supports both Windows 10 and Windows 11.
Do I need to install browsers separately?No. The setup flow can download them automatically; use npx playwright install when needed.
Can I use JavaScript instead of TypeScript?Yes. Playwright supports both JavaScript and TypeScript.
Is Playwright free?Yes. It is an open-source framework maintained by Microsoft.
How do I update Playwright?Run npm install -D @playwright/test@latest, followed by npx playwright install.

Steps for API Testing in Playwright: A Complete Step-by-Step Guide

 Playwright guide

Steps for API Testing in Playwright

A complete, practical walkthrough for building fast, reliable API tests—from your first request to authenticated CRUD flows and CI-ready reporting.

Meta description
Learn how to perform API testing in Playwright with setup, HTTP methods, assertions, authentication, fixtures, and best practices for reliable automated tests.

Introduction

Modern applications are built on APIs, and ensuring those APIs work correctly is just as important as testing the UI. While Playwright is widely known as a powerful end-to-end browser automation tool, it also ships with a built-in APIRequestContext for API testing.

You can validate backend services, mock data for UI tests, or build a full API test suite—all without installing a separate HTTP client library. This guide walks through the complete process, from installation to robust, production-ready test suites.

What is API testing?

API testing verifies that an application programming interface meets expectations for functionality, reliability, performance, and security. Instead of interacting with a UI, API tests send requests directly to REST, GraphQL, or other endpoints and validate status codes, headers, response bodies, and timing.

Why use Playwright for API testing?

Playwright includes a dedicated request context that lets you:

  • Send GET, POST, PUT, PATCH, and DELETE requests without a browser.
  • Reuse authentication state between API calls and UI tests.
  • Combine API setup and teardown with UI tests in one file.
  • Run requests in parallel with Playwright's test runner.
  • Use built-in retries, timeouts, tracing, and reporting.

Step-by-step: API testing in Playwright

Prerequisites

  • Node.js v16 or later
  • Basic JavaScript or TypeScript knowledge
  • A code editor (VS Code recommended)
  • An API endpoint to test

Step 1: Install Playwright

Create a new project, or install the test runner in an existing project:

npm init playwright@latest
# or
npm install -D @playwright/test

Step 2: Understand the request fixture

The built-in fixture provides an APIRequestContext. No browser or page is needed.

import { test, expect } from '@playwright/test';

test('get list of users', async ({ request }) => {
  const response = await request.get(
    'https://jsonplaceholder.typicode.com/users'
  );
  expect(response.status()).toBe(200);
});

Step 3: Write your first API test

Create tests/api.spec.ts and assert both the response and its data:

const BASE_URL = 'https://jsonplaceholder.typicode.com';

test('GET /users returns a list', async ({ request }) => {
  const response = await request.get(`${BASE_URL}/users`);
  expect(response.ok()).toBeTruthy();

  const users = await response.json();
  expect(Array.isArray(users)).toBeTruthy();
  expect(users.length).toBeGreaterThan(0);
});

Run the test with npx playwright test.

Step 4: Handle HTTP methods

The request object exposes all common HTTP verbs:

// GET
await request.get(`${BASE_URL}/posts/1`);

// POST
await request.post(`${BASE_URL}/posts`, {
  data: { title: 'Playwright API Testing', body: 'Learning APIs', userId: 1 }
});

// PUT
await request.put(`${BASE_URL}/posts/1`, {
  data: { id: 1, title: 'Updated Title', body: 'Updated body', userId: 1 }
});

// DELETE
await request.delete(`${BASE_URL}/posts/1`);

Step 5: Validate responses with assertions

Validate status codes, headers, and body content together for expressive, useful failures.

const response = await request.post(`${BASE_URL}/posts`, {
  data: { title: 'foo', body: 'bar', userId: 1 },
});

expect(response.status()).toBe(201);
expect(response.headers()['content-type']).toContain('application/json');

const body = await response.json();
expect(body.title).toBe('foo');
expect(body).toHaveProperty('id');

Step 6: Handle authentication

Set default headers on a context so every request includes the required token:

const apiContext = await request.newContext({
  baseURL: 'https://api.example.com',
  extraHTTPHeaders: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
  },
});

const response = await apiContext.get('/protected-resource');
expect(response.status()).toBe(200);
await apiContext.dispose();
Security note: Keep tokens and credentials in environment variables or your CI secret store—not in test files.

Step 7: Use fixtures and custom contexts

For larger suites, create an authenticated context once and dispose of it after use:

type MyFixtures = { apiContext: APIRequestContext };

export const test = base.extend({
  apiContext: async ({}, use) => {
    const context = await request.newContext({
      baseURL: 'https://api.example.com',
      extraHTTPHeaders: {
        Authorization: `Bearer ${process.env.API_TOKEN}`,
      },
    });
    await use(context);
    await context.dispose();
  },
});

Step 8: Chain requests

Model real workflows by creating, updating, verifying, and deleting a resource:

const createRes = await request.post(`${BASE_URL}/posts`, {
  data: { title: 'New Post', body: 'Content', userId: 1 },
});
const { id } = await createRes.json();

const updateRes = await request.put(`${BASE_URL}/posts/${id}`, {
  data: { title: 'Updated Post' },
});
expect(updateRes.status()).toBe(200);

const getRes = await request.get(`${BASE_URL}/posts/${id}`);
expect(getRes.status()).toBe(200);

const deleteRes = await request.delete(`${BASE_URL}/posts/${id}`);
expect(deleteRes.status()).toBe(200);

Step 9: Test errors and negative cases

Do not test only the happy path. Check invalid input, missing authentication, and unknown resources:

test('returns 404 for a missing resource', async ({ request }) => {
  const response = await request.get(`${BASE_URL}/posts/999999`);
  expect(response.status()).toBe(404);
});

test('returns 401 without authentication', async ({ request }) => {
  const response = await request.get('https://api.example.com/protected');
  expect(response.status()).toBe(401);
});

Step 10: Generate and review reports

Playwright's HTML reporter works for API tests too:

npx playwright test
npx playwright show-report

Configure multiple reporters in playwright.config.ts:

export default {
  reporter: [['html'], ['junit', { outputFile: 'results.xml' }]],
};

Best practices

  • Isolate API and UI tests with separate project configurations when useful.
  • Use environment variables for URLs, tokens, and credentials.
  • Create reusable fixtures for authentication and setup/teardown.
  • Validate schemas with libraries such as zod or ajv.
  • Clean up records created during tests.
  • Run independent API tests in parallel in CI.
  • Use API calls to set up data quickly before UI assertions.

Common pitfalls to avoid

  • Forgetting dispose() on manually created request contexts.
  • Hardcoding tokens or secrets in test files.
  • Parsing a body without first checking response.ok().
  • Relying only on status codes instead of validating content.
  • Running tests against production instead of a dedicated test environment.

Conclusion

Playwright's built-in API capabilities provide an all-in-one way to validate both the UI and backend. Start with one GET request, then expand into CRUD flows, authentication, schema checks, and negative scenarios. You will quickly have a maintainable regression suite that catches issues before production.

Ready to get started?
Set up a Playwright project, choose one endpoint, and write your first automated test today.

FAQs

Do I need a browser to run API tests?No. APIRequestContext sends HTTP requests directly, making tests fast and lightweight.
Can I combine API and UI testing?Yes. Use API calls for quick data setup or authentication, then switch to browser-based testing in the same test file.
Does Playwright support GraphQL?Yes. Test GraphQL endpoints with request.post() and place the query or mutation in the JSON payload.
How do I handle flaky API tests?Use retries, isolate test data, and avoid depending on unstable external services.
Can Playwright validate JSON schemas?Integrate ajv or zod alongside Playwright assertions for deeper schema validation.

Tuesday, 29 September 2026

How AI Can Help Playwright Automation | A learner's guide

How AI Can Help Playwright Automation

A step-by-step guide for learners

How AI Can Help Playwright Automation

Use AI as a thoughtful partner to write, expand, maintain and debug robust browser tests, with Playwright at the centre.

Test automation has come a long way, and Playwright has quickly become one of the most popular frameworks for automating modern web applications. It is fast, reliable, and supports multiple browsers and languages out of the box. Yet learners and teams still face familiar challenges: fragile selectors, scripts to write from scratch, UI changes to accommodate, and flaky failures to debug.

This is where Artificial Intelligence (AI) can help. AI can reshape how QA engineers and developers write, maintain and scale Playwright suites, without replacing the judgement that makes a test valuable.

Why combine AI with Playwright automation?

Traditional test automation asks a tester to perform several repetitive yet important activities.

AI can assist with nearly every step, reducing repetitive effort and helping learners ramp up faster, while human review keeps each test grounded in product intent.

6 ways AI enhances Playwright automation

01

AI-assisted test script generation

AI coding assistants can turn a plain-English scenario, such as “log in with valid credentials and verify the dashboard loads”, into a working draft of Playwright code to refine.

02

Self-healing locators

When the DOM changes, AI-powered approaches can analyse page structure and suggest alternative locators. This may reduce maintenance overhead, but healed locators should always be reviewed.

03

Smart test case generation

Given a user story, application flow or relevant logs, AI can suggest edge cases and negative scenarios that are easy to overlook.

04

Visual regression testing with AI

AI-driven visual testing can distinguish meaningful visual differences from insignificant rendering variation, helping teams focus on real regressions.

05

Intelligent maintenance and debugging

AI can analyse failed runs alongside errors and recent changes, then suggest whether the likely cause is a product bug, flaky behaviour or an outdated selector.

06

Codegen + AI refinement

Playwright’s built-in Codegen records browser actions and generates code. An AI assistant can help clean up that starting point, add assertions, parameterise data and explain each step.

The 8-step guide: getting started

1

Set up your Playwright environment

  1. Install Node.js.
  2. Initialise a project with the following command.
  3. Run the sample tests to verify the installation.
npm init playwright@latest
2

Record a baseline test with Codegen

Run Codegen, perform a basic flow and save the generated code as your starting point.

npx playwright codegen https://your-app-url.com
3

Refine the script with an AI assistant

Provide the Codegen output and ask AI to add meaningful assertions, replace brittle selectors with getByRole or getByTestId, parameterise hardcoded data, and explain the code. Treat the result as a first draft.

4

Expand coverage with AI-suggested scenarios

Describe the user flow and ask for negative and edge cases. Convert only the relevant suggestions into new tests.

5

Implement robust locator strategies

Prefer Playwright’s resilient getByRole, getByLabel and getByText locators over brittle CSS or XPath selectors. If a self-healing framework is used, audit its changes regularly.

6

Add AI-powered visual testing

Optionally integrate a visual testing tool, capture baselines for key pages or components, and review flagged differences rather than accepting every change automatically.

7

Run tests and triage failures

Run the suite and share sanitised logs or stack traces with an AI assistant to help classify failures. Apply a proposed fix and re-run to confirm it.

npx playwright test
8

Continuously iterate

Repeat the Codegen and refinement cycle as features evolve. Ask AI to identify redundant tests, missing coverage or opportunities to simplify, but keep the final decisions yours.

Best practices

  • Review generated code: use generated code as a first draft, never as an unquestioned final product.
  • Validate assertions and logic: AI can misunderstand intent.
  • Audit self-healing: confirm healed locators still target the intended elements.
  • Keep sensitive data out of prompts: never share production credentials, personal data or confidential business logic with third-party tools.
  • Keep human judgement in the loop: test strategy and domain knowledge remain essential.

Limitations to keep in mind

  • Suggestions are only as good as the context provided.
  • Self-healing and visual AI can produce false positives or negatives.
  • Compatibility varies across JavaScript, TypeScript, Python, Java and .NET setups.
  • AI cannot replace foundational testing knowledge. Understanding what to test and why still matters.

Conclusion

AI can make Playwright automation more collaborative and efficient: generating scripts, broadening coverage, maintaining locators and accelerating failure triage. Start with Codegen, layer in AI refinement and iterate continuously. With careful validation, learners can build robust, maintainable suites faster while developing the testing skills that matter most.

Ready to begin? Set up a Playwright project, record your first Codegen script and bring an AI assistant along for the ride.
Learner’s guide to AI-assisted Playwright automation

Translate







Tweet