Getting Started with Browser Testing
k6 browser tests allow you to simulate real user interactions with web applications, such as clicking buttons, filling out forms, and verifying page content. This helps you test not only backend performance, but also frontend reliability and user experience.Prerequisites
Before you begin, you’ll need:- Basic knowledge of JavaScript or TypeScript
- A code editor (Visual Studio Code or JetBrains)
- A Chromium-based browser (such as Google Chrome) installed locally
- k6 installed on your machine
Basic Structure
Every k6 browser script follows a common structure with these core components:This is where the test logic resides. For browser scripts, it must be written as an
async function to handle browser actions.Import k6 modules to extend functionality. Note that k6 uses its own JavaScript runtime, not Node.js.
Configure test execution, including the number of virtual users, duration, and performance thresholds.
Key Concepts
Browser Type Configuration
A browser script must setoptions.browser.type in the options object:
Asynchronous Operations
Browser interactions (like navigation and clicks) are asynchronous, so your test must useasync/await:
Locators
The Locator API finds and interacts with elements on a page:Write Your First Browser Test
Let’s create a browser test that loads a page, clicks a button, takes a screenshot, and verifies content.import http from 'k6/http';
import exec from 'k6/execution';
import { browser } from 'k6/browser';
import { sleep, check, fail } from 'k6';
export const options = {
scenarios: {
ui: {
executor: 'shared-iterations',
vus: 1,
iterations: 1,
options: {
browser: {
type: 'chromium',
},
},
},
},
};
const BASE_URL = __ENV.BASE_URL || 'https://quickpizza.grafana.com';
export function setup() {
const res = http.get(BASE_URL);
if (res.status !== 200) {
exec.test.abort(
`Got unexpected status code ${res.status} when trying to setup. Exiting.`
);
}
}
export default async function () {
let checkData;
const page = await browser.newPage();
try {
await page.goto(BASE_URL);
checkData = await page.locator('h1').textContent();
check(page, {
header: checkData === 'Looking to break out of your pizza routine?',
});
await page.locator('//button[. = "Pizza, Please!"]').click();
await page.waitForTimeout(500);
await page.screenshot({ path: 'screenshot.png' });
checkData = await page.locator('div#recommendations').textContent();
check(page, {
recommendation: checkData !== '',
});
} catch (error) {
fail(`Browser iteration failed: ${error.message}`);
} finally {
await page.close();
}
sleep(1);
}
Complete Example
Here’s the full script:Run Your Test
Execute your browser test with:Understanding the Output
After the test completes, you’ll see metrics like:- Checks - Assertion results
- HTTP metrics - Request duration and failures
- Browser metrics - Data sent/received, request duration
- Web Vitals - FCP, LCP, CLS, FID, INP, TTFB
Extending Your Test
Once you’re comfortable with the basics, extend your browser test by:- Simulating complex user flows (multiple pages, form submissions)
- Adding more checks and assertions to validate UI elements
- Creating hybrid performance tests combining frontend and backend testing
Next Steps
How to Write Tests
Learn advanced browser testing patterns
Best Practices
Optimize your tests for reliability and maintainability