Web app testing

Web Application Testing: A Practical Checklist

Key takeaways

  • Test your critical flows first, and get them stable before you expand coverage.

    Sign-up, login, checkout and your app's main action come before edge cases, then keep going until everything a user can do has a test.

  • Test every form with bad input as well as good input.

    Wrong formats, empty fields, double clicks and server errors should each get a clear message and lose nothing the user typed.

  • Run your critical flows in Chromium, Firefox and WebKit, at desktop and phone sizes.

    Many layout and input bugs show up in only one engine or one screen size.

  • Check a new feature by hand first, then automate its test once the behavior settles.

    Exploratory and usability testing stay with people, and every check you'd run again goes into the automated suite.

  • Run the whole suite in parallel on every pull request or deploy, and add a test for every bug that escapes.

    Parallel runs keep a growing suite fast enough to run on every change.

It's release day. The new pricing page looks right in Chrome on the designer's laptop. Then a customer on an iPhone taps "Upgrade," and nothing happens, because a cookie banner is sitting on top of the button.

Web app testing checks that a web application works for the people using it: its key flows complete, its forms accept good input and reject bad input, logins and sessions hold, and it works in every browser and screen size your users have. It also covers accessibility, performance, security basics, visual changes and the APIs behind the interface. And it runs again on every release, since any change can break something that used to work.

What is web app testing?

Web app testing is the practice of checking that a web application does what its users need, in the browsers and on the devices they use, before and after each release. "Web app testing" and "web application testing" mean the same thing.

A web app is harder to test than a static website. Users sign in, save data, pay, invite teammates and come back later, so tests have to follow state across pages, sessions and services. End-to-end tests do that checking by driving a real browser through a user's flow, with unit and API tests underneath.

What should a web app testing checklist cover?

A complete web app testing checklist covers 11 areas:

  1. Functional flows: the journeys users came to your app to complete.
  2. Forms and validation: good input accepted, bad input rejected, nothing lost.
  3. Authentication and sessions: the right people get in and stay in for the right amount of time.
  4. Cross-browser: the same flows in Chromium, Firefox and WebKit.
  5. Responsive and mobile web: phone and tablet sizes, touch and mobile browsers.
  6. Accessibility: keyboard, screen reader and contrast checks.
  7. Performance: page speed for real users, and behavior under load.
  8. Security basics: access control, input handling, cookies and secrets.
  9. Visual regression: screens that still look the way they should.
  10. APIs, data and integrations: the services behind the interface.
  11. Regression on every release: everything that worked last release still works.

1. Functional flows

Test every flow a user came to your app to complete, from the first click to the result they expected. Functional testing of these flows is the base of the whole checklist, because if sign-up or checkout breaks, little else on this list matters.

  • Sign-up and onboarding: a new user can create an account, verify their email and land in the product.
  • Your app's main action: a user can create the project, order, document or booking your product exists for, then find it again.
  • Checkout and billing: adding to a cart, paying with test cards, applying discounts, and upgrading and canceling a plan.
  • Search, filters and sorting: results match the query, filters combine correctly and an empty result shows a helpful message.
  • Navigation: menus, links and the back button go where they should, with no 404s or dead ends.
  • Emails and texts the flow depends on: verification emails, password resets, invites and receipts arrive, and their links work.
  • Multi-user flows: an invite, a share or a comment reaches the other user, with the right permissions.

2. Forms and validation

Every form should accept valid input, reject invalid input with a clear message, and keep what the user typed. Forms are where user input enters your system, so test what the browser checks and what the server checks.

  • Required fields: leaving one empty shows an error next to that field.
  • Formats: emails, phone numbers, dates, postal codes and currencies in the formats your users actually type.
  • Limits: minimum and maximum lengths and values, plus one character past each limit.
  • Special characters: apostrophes (O'Brien), accents, emoji and pasted text with extra spaces.
  • Error states: the message says what's wrong and how to fix it, and the rest of the form keeps its values.
  • Double submits: clicking twice or pressing Enter twice creates exactly one record.
  • Server-side validation: the API rejects bad data even when the browser's checks are bypassed.
  • File uploads: allowed types and sizes go through, and the wrong file gets a clear error.
  • Autofill and password managers: saved details land in the right fields.

Here are two of those checks as Playwright tests, run for this post against a small sign-up form on Playwright 1.63 in Chromium. Each follows Arrange-Act-Assert, setting up the page, doing one thing and checking the result.

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

test('sign-up rejects a bad email and keeps what the user typed', async ({ page }) => {
  // Arrange
  await page.goto('/signup');
  await page.getByLabel('Name').fill('Ada Lovelace');
  await page.getByLabel('Email').fill('ada.example.com');

  // Act
  await page.getByRole('button', { name: 'Create account' }).click();

  // Assert
  await expect(page.getByRole('alert')).toHaveText('Enter a valid email address');
  await expect(page.getByLabel('Name')).toHaveValue('Ada Lovelace');
});

test('double-clicking submit sends one sign-up request', async ({ page }) => {
  // Arrange
  let signups = 0;
  page.on('request', (req) => {
    if (req.method() === 'POST' && req.url().endsWith('/api/signup')) signups++;
  });
  await page.goto('/signup');
  await page.getByLabel('Name').fill('Ada Lovelace');
  await page.getByLabel('Email').fill(`ada+${Date.now()}@example.com`);

  // Act
  await page.getByRole('button', { name: 'Create account' }).dblclick();

  // Assert
  await expect(page.getByText('Check your inbox')).toBeVisible();
  expect(signups).toBe(1);
});

Both tests passed on all 10 repeat runs. With the form's double-submit guard taken out, the second test failed, counting 2 sign-up requests where it expected 1.

3. Authentication and sessions

Authentication tests check that the right people get in, everyone else stays out, and a session ends when it should.

  • Valid and invalid credentials: a wrong password shows an error that doesn't reveal whether the account exists.
  • Lockout and rate limits: repeated failed logins slow down or lock the account, as designed.
  • Password reset: the link arrives, works once and expires.
  • SSO, social login and MFA: every sign-in method your users have, including one-time codes.
  • Session timeout: an idle session expires, and signing in again returns the user to the page they were on.
  • Logout: signing out ends the session, and the back button doesn't show private pages.
  • Roles and permissions: each role sees only what it should, and changing an ID in the URL doesn't open another user's data.
  • Multiple tabs and devices: signing out in one tab signs out the others, if that's how your app is meant to work.

4. Cross-browser

Run your critical flows in each browser engine your users have: Chromium (Chrome and Edge), Firefox and WebKit (Safari). Your analytics show which browsers and versions matter, and cross-browser testing covers when to automate it and how.

  • Layout: grids, flexbox, fonts and scrolling render the same way in each engine.
  • Inputs: date pickers, file uploads, dropdowns and autofill behave in each browser.
  • Cookies and storage: logins and embedded content keep working where the browser blocks third-party cookies, as Safari does by default.
  • Older versions: the oldest versions you support, if your users include companies that update slowly.

5. Responsive and mobile web

Test your critical flows at phone and tablet sizes, in mobile browsers, with touch input. A layout that looks fine on a laptop can hide buttons, overflow tables or put inputs under the on-screen keyboard on a phone.

  • Breakpoints: each layout your CSS defines, plus the widths in between.
  • Touch: tap targets are big enough, and nothing depends on hover.
  • On-screen keyboard: it doesn't cover the field being typed in or the submit button.
  • Overlays: cookie banners, chat widgets and sticky headers don't sit on top of buttons.
  • Orientation: rotating the phone keeps the user's place and data.
  • Slow networks: pages load and forms submit on a throttled mobile connection.

Browser emulation, such as Playwright's device profiles, gives a test a phone's screen size, touch input and user agent, and it's fast enough to run on every release. Run the same flows in WebKit as well, since every browser on an iPhone uses Safari's engine, which renders some layouts and inputs differently from Chrome.

6. Accessibility

Accessibility testing checks that people with disabilities can use your app, usually against WCAG 2.2 level AA. Automated scanners such as axe catch common problems like missing labels and low contrast on every run. Keyboard and screen reader checks still need a person.

  • Keyboard: every control is reachable with Tab, in a sensible order, with a visible focus outline.
  • Labels: every form field has a label a screen reader announces.
  • Images: meaningful images have alt text, and decorative ones are hidden from screen readers.
  • Contrast: normal text meets WCAG's 4.5:1 contrast ratio for level AA.
  • Errors: form errors are announced, and they don't rely on color alone.
  • Structure: headings, landmarks and page titles describe the page.
  • Dialogs: focus moves into a modal when it opens and returns when it closes.

7. Performance

Measure how fast pages load and respond for real users, and how the app holds up at peak traffic. Google's Core Web Vitals are the usual yardstick: Largest Contentful Paint for loading, Interaction to Next Paint for responsiveness and Cumulative Layout Shift for visual stability. Google rates a page "good" when, for at least 75% of visits, LCP is 2.5 seconds or less, INP is 200 milliseconds or less and CLS is 0.1 or less. QA Wolf's guide to web performance metrics explains each one.

  • Page load: key pages meet your Core Web Vitals targets on a mid-range phone and a throttled connection.
  • Interactions: buttons, filters and search respond quickly, and show a loading state when they can't.
  • API response times: the endpoints behind your critical flows stay within your targets.
  • Load: a load test with a tool such as k6, JMeter or Gatling shows where response times and errors climb as users ramp up.
  • Page weight: images are compressed and sized, and JavaScript bundles stay within a budget.
  • Every release: a performance check runs on each deploy, so a heavy new script gets caught before users feel it.

8. Security basics

Security basics belong on every web app checklist, even though deep security testing is a specialist's job. The OWASP Top 10, a widely used list of the most critical web application security risks, is the usual starting point.

  • HTTPS everywhere: every page and API call uses HTTPS, and plain HTTP redirects to it.
  • Access control on the server: every API endpoint checks who's asking, so a hidden button is never the only protection.
  • Injection: script tags and SQL fragments typed into a form field are stored and shown as plain text.
  • Cookies: session cookies are set with the Secure, HttpOnly and SameSite attributes.
  • Cross-site requests: requests that change data need a token or a same-site cookie, so another site can't send them for a signed-in user.
  • Secrets: no API keys or credentials in front-end code, URLs or error messages.
  • Dependencies: a scanner flags libraries with known vulnerabilities.

Functional tests can cover the access-control rules: sign in as one user and try to open another user's record. Scanners such as ZAP and Burp Suite find common vulnerabilities, and apps that handle sensitive data need penetration testing by security specialists.

9. Visual regression

Visual regression testing compares screenshots of pages and components against approved baselines, and fails when they change by more than you allow. It catches bugs functional tests walk past, like a button that still works but can't be seen.

  • Key screens: pricing, checkout, dashboards and anything with strict design requirements.
  • Breakpoints and browsers: the same screen at each width and in each engine you support.
  • Charts and canvas: graphics a locator can't read.
  • Dynamic content: timestamps, avatars and live data are masked so they don't fail the comparison.
  • Baseline reviews: every new baseline gets reviewed like a code change.

10. APIs, data and integrations

Test the services behind the interface as well as the screens: the APIs your front end calls, the data they save and the third-party services they depend on. Integration testing covers how those pieces work together.

  • API contracts: endpoints return the right status codes, fields and error responses.
  • Data: what a user saves is what they see after a reload, on another device and in exports.
  • Third parties: payments, email, maps, analytics and single sign-on work in their test or sandbox modes.
  • Failure states: when a third party is slow or down, the app shows a useful message and keeps the user's data.
  • Webhooks and background jobs: events arrive, retries work, and a duplicate event never charges or emails twice.
  • Test data: each test creates its own data and cleans it up, so tests can run in parallel without colliding.

11. Regression on every release

Regression testing re-runs your tests after every change to catch what the change broke. Run a fast smoke test first to confirm the build is up, then the full regression suite.

  • On every pull request or deploy: a suite that runs once a week finds bugs a week late.
  • In parallel: tests run at the same time, so a growing suite still finishes before the next merge.
  • A test for every escaped bug: when a bug reaches production, add a test so it can't come back unnoticed.
  • Every failure investigated: before the next run, someone works out whether each failure is a bug, a broken test or a flake.
  • No ignored flaky tests: a test that fails at random gets fixed, or the team stops trusting the suite.

Which web app tests should you automate first?

Automate the flows your business depends on first, get those tests stable, then keep going until everything a user can do has a test. QA Wolf's advice is to go broad before going deep, making a team's first 100 tests a survey of the app's major customer-facing flows and saving the edge cases of any one feature for later.

Rank flows by risk. The same post scores each flow on six factors:

  • User activity: the flows your customers use most, from analytics or logs.
  • Revenue: anything that stops the business making money if it breaks, such as checkout, subscriptions and billing.
  • Dependencies: flows that rely on other systems, where an upstream change can break them.
  • Security and compliance: access control and anything that handles sensitive data.
  • Recency: features that shipped recently, since new code breaks more often than old code.
  • Complexity: one or two tests through the core path of a complex feature, with deep coverage saved until you know where the risk is.

Flows that score high on two or three factors go first. Check a new feature by hand while it still changes every day, then automate its test once the behavior settles. Exploratory and usability testing stay with people, since they depend on human judgment.

How do you run web app tests on every release?

Automate them in a browser testing framework, run them in CI on every pull request or deploy, and make sure someone investigates every failure and fixes tests when the app changes. Teams do that in one of two ways:

  • Build it in-house: write tests in an open-source framework such as Playwright, and run them on CI runners or a browser grid. You own the code, the infrastructure and the upkeep.
  • Hand it to QA Wolf: QA Wolf's web application testing tool uses AI agents to write the tests as Playwright code you own, run them in parallel and keep them working as the app changes.

Either way, the suite needs browsers to run in. A suite that runs one test at a time gets slower with every test you add. In parallel, with each test in its own clean browser, it takes about as long as its slowest test. QA Wolf's web testing infrastructure runs suites that way, starting every test at the same time in a fresh container.

Plan for upkeep from the start. Before AI agents took on the work, QA Wolf measured how long each step took its QA engineers across 3.5 million tests. Creating a test took about 95 minutes, once. Then, every time the app changed, investigating a failure took about 17 minutes and fixing a broken test 45. AI agents are faster at each step now, but investigation and maintenance still add up to more work than creating tests, because they keep coming back.

How does QA Wolf test web apps?

QA Wolf's AI agents plan, build, run and maintain your end-to-end tests in Playwright, and investigate every failure before it reaches your team. When an agent needs an answer, such as whether a change was intended, it asks you. On QA Wolf's full service, the agents send those questions to QA Wolf's engineers instead. From QA Wolf's docs:

The plan. An agent explores your app and outlines the end-to-end flows to test, organized by feature, in Arrange-Act-Assert steps. It can also work from your existing test plans, or watch while you click through a flow yourself. The agents write the tests as Playwright code, starting with your highest-priority flows and then the most complex ones.

The checks on this list. QA Wolf tests are Playwright code, with built-in help for the harder items:

  • Emails and texts: tests send, receive and check emails and SMS messages, such as verification links and login codes.
  • MFA: tests generate one-time codes from an authenticator secret.
  • Multi-user flows: tests pass data between users, sessions and devices.
  • Browsers: tests run in headed Chrome, Firefox and WebKit browsers.
  • Accessibility: axe-core runs inside a test and can fail the run on critical or serious WCAG violations.
  • Performance: a Lighthouse audit inside a test asserts on Core Web Vitals and a performance score.
  • Visual regression: screenshots are compared against baselines, and an intended change gets promoted to the new baseline in the QA Wolf editor.

The runs. Every test and every retry runs in a fresh container with a new browser, so nothing carries over between runs. Each run keeps its video, Playwright trace, console and network requests. Tests run on a schedule or on every pull request, against its preview deploy.

The failures. A failing test is retried, then QA Wolf's AI investigates while the rest of the suite is still running, sorting each failure into a product bug, an out-of-date test or a flake. Out-of-date tests are fixed and re-run, and real bugs reach your team with a recording, logs and steps, in Slack or Teams and Jira or Linear. The tests are Playwright code you own and can change at any time.

The test environment. Before testing starts, QA Wolf asks each customer to prepare their test environment with its guide to preparing test environments. Its list is worth following whoever runs your tests:

  • A dedicated test environment: a staging or test environment that isn't shared with demos, manual QA or feature-branch checks.
  • Data that can't collide: unique login credentials for each run, and generated data prefixed with a run ID or timestamp.
  • Test users on demand: an API or script that creates and cleans up test users.
  • Steady feature flags: a dedicated feature flag configuration for testing, kept in a consistent state.
  • Email that tests can use: plus addressing (user+test123@example.com) works, and email and texts arrive within a minute.
  • No deploys mid-run: no deploys to the test environment while a run is in progress, or a preview environment for each run.

Drata is a perfect example. It went from overnight deploys to multiple deploys a day, and QA Wolf grew its regression suite from about 100 test cases to more than 400. Start now and ask the agent to map your web app and build tests for this checklist, or talk to sales.

The bottom line

A web app testing checklist covers the flows users came for, the forms and logins they go through, every browser and screen size they use, and the accessibility, performance, security, visual and API checks around them. Test the critical flows first and get them stable, check new features by hand before automating them, and keep going until everything a user can do has a test. Then run the whole suite in parallel on every pull request or deploy, so every release gets the full checklist.

Frequently asked questions

  • What is web app testing?

    Web app testing is checking that a web application works for the people using it, from its key flows and forms to logins, sessions and every browser and screen size its users have. It also covers accessibility, performance, security basics, visual changes and the APIs behind the interface. Most teams automate the checks as end-to-end tests and run them on every release.

  • How do you test a web application?

    List the user flows that matter most, such as sign-up, login, checkout and your app's main action, and write each one as a test with steps and an expected result. Then work through a checklist of forms, sessions, browsers, screen sizes, accessibility, performance, security and integrations. Check new features by hand first, automate their tests once they settle and run the suite on every pull request or deploy.

  • How do you automate web application testing?

    Write tests in a browser automation framework such as Playwright, starting with your critical flows and getting them stable before you expand to everything a user can do. Run the tests in CI on every pull request or deploy, in parallel so the suite finishes quickly, and plan for someone to investigate every failure and update tests when the app changes. QA Wolf's AI agents do that work for you, as Playwright code you own.

  • What is the best tool for web application testing?

    Playwright is the best framework for web application tests, an open-source library from Microsoft that drives Chromium, Firefox and WebKit from one API. QA Wolf is the best way to have those Playwright tests written, run and maintained for you. On the same 1,567 evals across web, iOS and Android apps, QA Wolf's agent passed 93%, against 78% for Claude Code and 74% for Codex, and the tests it writes are Playwright code you own.

  • How do you do security testing for a web application?

    Start with the OWASP Top 10, a widely used list of the most critical web application security risks, and check access control, input handling, sessions and cookies against it. Scanners such as ZAP and Burp Suite find common vulnerabilities, and functional tests can confirm that one user can't open another user's data. Apps that handle sensitive data also need penetration testing by security specialists.

  • How do you test the performance of a web application?

    Measure page speed with Google's Core Web Vitals (Largest Contentful Paint, Interaction to Next Paint and Cumulative Layout Shift), using Lighthouse in the lab and real-user monitoring in production. Load test with a tool such as k6, JMeter or Gatling, adding simulated users until response times or error rates pass the limits you set. Run a performance check on every release so a slow new feature gets caught before users feel it.

  • How do you test a web app on mobile?

    Run your critical flows at phone and tablet screen sizes with browser emulation, such as Playwright's device profiles, which sets a phone's screen size, touch input and user agent and is fast enough for every release. Run them in WebKit as well, since every browser on an iPhone uses Safari's engine. Look for buttons hidden under banners, menus that need hover and fields the on-screen keyboard covers.

More from the blog

All posts