Test Automation October 28, 2026 14 min read

Automated Web Testing: How to Automate Testing for Web Applications, Step by Step

Automated web testing isn't about buying a tool. It's about choosing the right checks, putting them at the right layer and running them on every change. Here's the full method, from picking your first three journeys to a working Playwright suite in CI, with every example in JavaScript.

Automated web testing means writing code that opens your site in a real browser, clicks and types like a user, and checks the result, then running that code on every change. This guide shows how to do it from zero: what to automate, how to structure the tests, a first Playwright suite in JavaScript, CI, and where AI helps.

It's a how-to, not a tool list. If you're still comparing products, the 8 best web testing tools post covers that. Every example below uses public practice sites, is written in JavaScript, and runs on Playwright 1.62.

Short version: pick your three most important user journeys, automate them in Playwright with role-based locators and web-first assertions, push most other checks down to API level, and run the suite in CI on every pull request. Grow from there.


What Is Automated Web Testing?

Automated web testing is the practice of using software to run repeatable checks against a website or web application, instead of a person clicking through it. A test script loads a page, performs user actions such as typing and clicking, and asserts that the page, the URL or an API response matches what's expected. The same tests then run on every code change.

It covers more than the browser. A healthy setup for automated testing of web applications mixes three kinds of checks: unit tests on the code, API tests on the back end, and a smaller set of end-to-end tests that drive the real UI.

What to Automate (and What to Keep Manual)

The fastest way to waste effort is to automate everything. Automate what is repeated, stable and costly to break. Keep humans on work that needs judgement.

AutomateKeep manual
Login, sign-up, checkout and other money or access pathsExploratory testing of new features
Regression checks you repeat every releaseVisual "does this feel right?" design reviews
Form validation rules and error messagesUsability sessions with real users
API contracts: status codes, response shapeOne-off checks for a feature that will change next week
The same flow across Chromium, Firefox and WebKitHard-to-script hardware (printers, card readers)
Smoke tests after every deploymentJudging copy, tone and content accuracy

A simple rule: if you've run the same manual check three times and expect to run it again, it's a candidate for automation.

The Test Pyramid for Web Applications

The test pyramid is a way to decide where each check should live. Lower layers are faster and more stable, so most checks belong there. The top layer is slower but proves the whole system works together.

LayerWhat it checksSpeedHow manyTypical tools
End-to-end (UI)Real user journeys in a browserSeconds per testFew: critical pathsPlaywright, Cypress, Selenium
API / integrationEndpoints, business rules, dataMilliseconds to secondsMorePlaywright request, Postman
UnitSingle functions and componentsMillisecondsMostJest, Vitest

Developers usually own the unit layer. Testers and SDETs get the most value from the API and end-to-end layers, which is also where Playwright works: it drives browsers and sends HTTP requests from the same test runner.


How to Start Automated Testing for Web Applications in 6 Steps

  1. Pick three critical journeys. Ask "what would hurt most if it broke on Friday night?" For most products that's login, the main purchase or sign-up flow, and one core feature. Write each as plain steps with an expected result.
  2. Choose a framework. For new projects, Playwright is a common default for automated testing web applications: free, cross-browser, with auto-waiting and built-in API testing. The which tool section links to full comparisons.
  3. Set up the project. Run npm init playwright@latest in a new folder, choose JavaScript, and let it create playwright.config.js and a tests/ folder. Full walkthrough: how to install Playwright.
  4. Write the first tests. One file per journey. Start with the happy path, then add the most likely failure (wrong password, empty cart).
  5. Run them in CI. Tests that only run on one laptop get forgotten. Add a pipeline on day one so every pull request runs the suite.
  6. Grow deliberately. Add a test each time a bug escapes, push detailed rule checks down to the API layer, and delete tests that no longer earn their keep.

Your First Web Automation Testing Suite in Playwright

Here's a small but real web automation testing suite: a config that runs every test in three browsers, a login test with a success and a failure case, and a second flow on a to-do app. Drop these files into the project from step 3.

playwright.config.js
// @ts-check
const { defineConfig, devices } = require('@playwright/test');

module.exports = defineConfig({
  testDir: './tests',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  reporter: [['html', { open: 'never' }], ['list']],
  use: {
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit', use: { ...devices['Desktop Safari'] } },
  ],
});

retries and forbidOnly only kick in on CI. trace: 'on-first-retry' records a full trace when a test fails and is retried, which you can open in the Trace Viewer.

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

test.describe('login', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('https://the-internet.herokuapp.com/login');
  });

  test('valid user reaches the secure area', async ({ page }) => {
    await page.getByLabel('Username').fill('tomsmith');
    await page.getByLabel('Password').fill('SuperSecretPassword!');
    await page.getByRole('button', { name: 'Login' }).click();

    await expect(page).toHaveURL(/\/secure$/);
    await expect(page.locator('#flash')).toContainText('You logged into a secure area!');
    await expect(page.getByRole('link', { name: 'Logout' })).toBeVisible();
  });

  test('wrong password shows an error and stays on login', async ({ page }) => {
    await page.getByLabel('Username').fill('tomsmith');
    await page.getByLabel('Password').fill('wrong-password');
    await page.getByRole('button', { name: 'Login' }).click();

    await expect(page.locator('#flash')).toContainText('Your password is invalid!');
    await expect(page).toHaveURL(/\/login$/);
  });
});

The second journey uses the Playwright TodoMVC demo: add two items, complete one, and check the counter and the "Completed" filter.

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

test('user can add, complete and filter todos', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc/');
  const newTodo = page.getByPlaceholder('What needs to be done?');

  await newTodo.fill('Write login test');
  await newTodo.press('Enter');
  await newTodo.fill('Add tests to CI');
  await newTodo.press('Enter');

  const items = page.getByTestId('todo-item');
  await expect(items).toHaveCount(2);

  await items.filter({ hasText: 'Write login test' }).getByRole('checkbox').check();
  await expect(page.getByTestId('todo-count')).toHaveText('1 item left');

  await page.getByRole('link', { name: 'Completed' }).click();
  await expect(items).toHaveText(['Write login test']);
});

Run the suite in one browser while you're writing it, then in all three:

Terminal
npx playwright test --project=chromium
Output
Running 3 tests using 3 workers

  ✓  1 [chromium] › tests/login.spec.js:8:3 › login › valid user reaches the secure area
  ✓  2 [chromium] › tests/login.spec.js:18:3 › login › wrong password shows an error and stays on login
  ✓  3 [chromium] › tests/todo.spec.js:3:1 › user can add, complete and filter todos

  3 passed

Drop --project=chromium to run every test in Chromium, Firefox and WebKit. npx playwright show-report opens the HTML report. For twenty more ready-made flows, see Playwright script examples.

That's the easy part. Three tests are simple. A suite of hundreds that stays green, runs fast and still makes sense a year later is the skill teams hire for. See the two-step plan to learn it properly →


Making Automated Web App Testing Reliable

Flaky tests, the ones that pass and fail without code changes, are what kill most automated web app testing efforts. Nobody trusts a red build that's "probably just flaky". Four habits prevent most of it.

1. Use user-facing locators

Prefer getByRole, getByLabel, getByPlaceholder and getByTestId over CSS classes or XPath. They match what users see, so they survive redesigns. The tests above use them everywhere except #flash, which is a stable ID. More in the Playwright locators guide.

2. Use web-first assertions, never fixed sleeps

await expect(locator).toHaveText(...) keeps retrying until the condition is true or the timeout runs out (5 seconds by default). page.waitForTimeout(3000) just waits and hopes. Replace every hard wait with an assertion on the thing you're waiting for; see Playwright wait strategies.

3. Control your test data

A test that depends on whatever is in a shared database will break when someone edits that data. Create the data you need through an API in the test, use unique values, or replace the back-end response entirely with page.route():

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

test('page shows the mocked test data', async ({ page }) => {
  // Replace the real API response with fixed test data
  await page.route('*/**/api/v1/fruits', async (route) => {
    await route.fulfill({ json: [{ name: 'Test Fruit', id: 101 }] });
  });

  await page.goto('https://demo.playwright.dev/api-mocking');
  await expect(page.getByText('Test Fruit')).toBeVisible();
});

The page now always shows the same fruit, regardless of what the real API returns. Use mocking for UI behaviour tests, and keep a few un-mocked tests to prove the real integration works.

4. Keep every test isolated

Playwright gives each test a fresh browser context: new cookies, new storage, no leftovers. Don't undo that by making test B depend on something test A created. Each test should set up its own state (in beforeEach or inside the test) so tests can run in any order and in parallel. If many tests need a logged-in user, log in once in a setup project and reuse the saved storageState.


Automated Testing of Web Services (APIs)

Most rules in a web app live in its back end, so automated testing of web services catches many bugs faster than UI tests can. Playwright's built-in request fixture sends HTTP calls without opening a browser:

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

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

test('GET a post returns the expected JSON', async ({ request }) => {
  const response = await request.get(`${API}/posts/1`);
  expect(response.ok()).toBeTruthy();

  const post = await response.json();
  expect(post).toMatchObject({ id: 1, userId: 1 });
  expect(typeof post.title).toBe('string');
});

test('POST creates a post', async ({ request }) => {
  const response = await request.post(`${API}/posts`, {
    data: { title: 'Automated web testing', body: 'Hello', userId: 7 },
  });
  expect(response.status()).toBe(201);
  expect(await response.json()).toMatchObject({ title: 'Automated web testing', userId: 7 });
});

These tests run in a fraction of the time a browser test takes, so they're the right place for detailed checks: every validation rule, every error code, every role's permissions. For REST basics, auth, schema checks and mocking, read the API testing tutorial and the Playwright API testing guide.

Running Web Automation Tests in CI

Commit this file as .github/workflows/playwright.yml and GitHub runs the whole suite on every push and pull request to main, then uploads the HTML report as an artifact.

.github/workflows/playwright.yml
name: Playwright Tests
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
jobs:
  test:
    timeout-minutes: 30
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: lts/*
      - name: Install dependencies
        run: npm ci
      - name: Install Playwright browsers
        run: npx playwright install --with-deps
      - name: Run Playwright tests
        run: npx playwright test
      - uses: actions/upload-artifact@v4
        if: ${{ !cancelled() }}
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30

Once the suite grows, tag a fast @smoke subset for pull requests and run everything nightly, or shard the run across machines. The full setup, including caching and sharding, is in Playwright with GitHub Actions.

Where AI Fits: Claude and the Playwright MCP Server

AI doesn't replace the steps above, but it speeds up the slowest one: writing the first draft of a test. With the Playwright MCP Server, an assistant like Claude can open a real browser, walk through your app, read the page's accessibility tree and write a Playwright test for the flow you describe.

  • Good uses: drafting tests from a written scenario, suggesting better locators, explaining a failing trace, generating many data-driven variations.
  • Your job: review every draft. Check that the assertions test the behaviour that matters, that there are no hard waits, and that data is isolated. AI-written tests that only assert "the page loaded" give false confidence.

Treat AI as a fast junior teammate: helpful drafts, human review before merge.

Common Automated Web Testing Mistakes

  • Automating through the UI what should be an API test. Fifty browser tests for form validation rules belong at API level.
  • Fixed sleeps. waitForTimeout makes tests both slow and flaky.
  • Brittle selectors. Long CSS chains and XPath break on every redesign.
  • Shared accounts and data. Two tests editing the same user will collide when run in parallel.
  • Tests that assert nothing useful. A test that clicks through a flow without checking the outcome can't fail when it should.
  • No CI. A suite nobody runs is a suite that silently rots.
  • Ignoring flaky tests. Fix or quarantine them quickly; see the flaky test fix guide.

Which Tool Should You Use?

This guide uses Playwright because it covers browser and API tests in one free framework, but the method (pick journeys, layer your tests, run in CI) works with any tool. To choose, start with automated web testing software: 8 best tools for browser-focused options, automated testing software compared for the wider market including low-code tools, and web application testing software for the best tool per test type (performance, security, accessibility). If you're automating tasks rather than tests, see web automation tools.

Need the process side, such as test plans, checklists and manual test cases? Read how to test a web application. For the UI layer in depth, see web UI testing and the Playwright end-to-end testing guide.

Ready to automate your web testing for real?

Learn Playwright in JavaScript: framework design, API tests, CI/CD and AI test writing with Claude. Then prove it with the practice tests.

See the plan →

Frequently Asked Questions

What is automated web testing?

Automated web testing uses software to run repeatable checks against a website or web app. A test script opens pages in a real browser or calls the API, performs user actions, and asserts that the result is correct. The same tests then run automatically on every code change, usually in CI.

How do I start automated testing for a web application?

Pick the three most important user journeys, choose a framework such as Playwright, set up a project with npm init playwright@latest, write a test for each journey's happy path and main failure case, and run the suite in CI on every pull request. Then add tests as bugs escape.

What should not be automated in web testing?

Exploratory testing, usability judgement, design reviews and one-off checks for features that are still changing are better done by people. Automate stable, repeated checks: critical journeys, regression tests, validation rules, API contracts and cross-browser runs.

Is Playwright good for automated web testing?

Yes. Playwright is free and open source, drives Chromium, Firefox and WebKit with one API, waits for elements automatically, includes an API testing client, and records traces for debugging. It supports JavaScript, TypeScript, Python, Java and .NET.

What is automated testing of web services?

It means testing a web app's back-end APIs directly with code: sending HTTP requests and checking status codes, response bodies and business rules. These tests are faster and more stable than browser tests. Playwright's request fixture, Postman and REST Assured are common tools.

Can AI write automated web tests?

AI assistants like Claude, connected to a browser through the Playwright MCP Server, can explore a page and draft Playwright tests from a plain-English scenario. The drafts still need human review for meaningful assertions, stable locators and isolated test data before they're merged.


Asim Noaman - Playwright and Claude AI course instructor

Asim Noaman

Senior QA Automation Engineer & AI Testing Specialist

With years of hands-on experience building test automation frameworks for production applications, Asim specializes in combining traditional QA methodologies with cutting-edge AI tools. He has helped teams adopt Playwright and AI-driven testing workflows to ship faster with fewer bugs.

Udemy Instructor Published course author
Playwright + AI Expert Specialized in AI-powered QA
Production Experience Enterprise-grade frameworks
Connect on LinkedIn

Automated Web Testing Course

Anyone Can Write Three Tests. Teams Hire People Who Can Build the Suite.

The free tools are already here. What's scarce is someone who can turn a handful of scripts into a reliable framework that runs in CI. The Playwright + Claude AI course teaches that in JavaScript, with AI helping you write and fix tests.

  • Build a Playwright framework from an empty folder to CI
  • UI and API tests in one project, with reliable locators and test data
  • Use Claude AI and the Playwright MCP Server to draft and debug tests
  • 4.5★ on Udemy, 510+ students, 30-day money-back guarantee
See the 2-Step Plan →

Ready now? Enroll on Udemy · Already know Playwright? Take the practice tests