How to Test Form Validation: A Complete Guide
How to Test Form Validation: A Complete Guide
How to Test Form Validation: A Complete Guide
Form validation is a gatekeeper between user intent and system integrity. When a form accepts malformed data, downstream processes can corrupt databases, trigger security flaws, or frustrate users who encounter confusing error messages. Conversely, overly strict validation blocks legitimate input, abandons conversions, and damages trust. Testing form validation therefore sits at the intersection of functional correctness, user experience, and risk mitigation. This guide walks you through a complete, platform‑agnostic approach: why validation matters, how to construct a test matrix that covers happy paths, error paths, edge cases, accessibility, and security, how to execute those tests manually and automatically, what production‑only pitfalls to watch for, and how autonomous, persona‑driven exploration can surface bugs that scripted tests miss. By the end you will have a concrete checklist you can apply to any web, mobile, or desktop form.
How to Test Form Validation: A Complete Guide – Why It Matters
Forms are the primary conduit for data entry in almost every application. A login screen, a checkout flow, a profile update, or a support ticket all rely on validation to ensure that the data entering the system matches expected formats, ranges, and business rules. When validation fails, the consequences cascade:
- Data corruption – Invalid values (e.g., letters in a numeric ID field) can break foreign‑key constraints, cause calculation errors, or corrupt reports.
- Security exposure – Missing or weak validation opens doors to injection attacks (SQLi, XSS, command injection), buffer overflows, or bypasses of business logic.
- User frustration – Vague or misleading error messages force users to guess what went wrong, increasing abandonment rates.
- Compliance risk – Regulations such as GDPR, PCI‑DSS, or WCAG often require specific validation behaviors (e.g., masking passwords, announcing errors to screen readers).
Testing validation early catches these issues before they reach production, reduces bug‑fix cost, and provides confidence that the form behaves correctly under real‑world conditions. Moreover, a well‑tested validation layer serves as living documentation: test cases explicitly state what inputs are accepted or rejected, making future changes safer.
How to Test Form Validation: A Complete Guide – Core Principles of Form Validation
Before designing tests, understand the validation layers that typically exist:
- Client‑side (UI) validation – Implemented with HTML5 attributes, JavaScript frameworks, or native mobile controls. Provides immediate feedback but can be bypassed.
- Server‑side validation – Runs on the API or backend, enforces business rules, and is the ultimate authority. Must never rely solely on client checks.
- Hybrid validation – Some checks (e.g., password strength) may start client‑side for UX and finish server‑side for certainty.
Effective testing treats each layer separately and then verifies that they agree. A test matrix should therefore include:
- Atomic field tests – Isolate a single input, vary its value, and observe the validation response.
- Cross‑field tests – Validate relationships (e.g., “password” and “confirm password” must match).
- State‑dependent tests – Validation that changes based on other UI toggles (e.g., a “country” dropdown that enables a “state” field only for certain countries).
- Integration tests – Full‑form submission that exercises the validation pipeline end‑to‑end.
With these principles in mind, we can build a comprehensive test matrix.
How to Test Form Validation: A Complete Guide – Building a Comprehensive Test Matrix
A test matrix organizes validation scenarios by dimension (what is being tested) and by outcome (expected pass/fail). Below is a master matrix that you can adapt to any form. Each row represents a test category; columns indicate the typical test techniques and example data points.
| Validation Dimension | Happy‑Path Tests | Error‑Path Tests | Edge‑Case Tests | Accessibility Checks | Security Checks |
|---|---|---|---|---|---|
| Required fields | Submit with all required fields filled correctly → success | Leave one required field blank → inline error, field focus | Submit with whitespace‑only value → trimmed and treated as empty | Error message announced by screen reader, associated via aria-describedby | Ensure no SQL injection via blank field (e.g., ' OR 1=1--) |
| Data type | Email user@example.com → accepted | user@ → rejected with “invalid email” | Email with Unicode local part 用户@例子.cn → accepted if spec allows | Error message readable at 200% zoom, sufficient contrast | Test for email header injection (%0AContent-Type:) |
| Length & limits | Password 12 chars within 8‑20 range → accepted | Password 7 chars → rejected | Password exactly 20 chars → accepted; 21 chars → rejected | Length counter announced live for screen‑reader users | Attempt buffer overflow by pasting 10 KB string into a 20‑char limit field |
| Range & format | Age 25 (numeric, 0‑150) → accepted | Age -5 → rejected | Age 150 → accepted; 151 → rejected | Numeric input announced as spinbox, step size communicated | Try injecting ; DROP TABLE users; into numeric field (should be rejected as non‑numeric) |
| Pattern / regex | Phone +1-555-123-4567 matches ^\+?\d{1,3}[-\s]?\d{1,4}[-\s]?\d{1,4}[-\s]?\d{1,9}$ → accepted | Phone abc-def-ghi → rejected | Phone with extra spaces +1 555 123-4567 → accepted if pattern tolerates spaces | Error message linked via aria-invalid=true | Test for regex denial‑of‑service (ReDoS) via crafted input that causes catastrophic backtracking |
| Cross‑field | Password Secret123!, Confirm Secret123! → matched → success | Password Secret123!, Confirm different → mismatch error | Password empty, Confirm empty → both required errors shown | Focus moves to first failing field; error announced | Attempt to bypass by submitting same value in both fields but with hidden Unicode characters (e.g., zero‑width joiner) |
| Dependent fields | Country USA → State field enabled, CA accepted | Country USA → State left blank → error | Country Canada → Province field enabled, ON accepted; ZZ rejected | When Country changes, screen reader announces new field state | Try injecting into State field when Country is set to a value that hides the field via CSS (should still be sanitized server‑side) |
| File upload | PDF 200 KB, MIME application/pdf → accepted | Executable .exe → rejected | Zero‑byte file → rejected (if min size set) | File name announced, progress bar accessible | Attempt to upload a file with double extension image.jpg.php; verify server checks content‑type and extension |
| CAPTCHA / bot checks | Correct CAPTCHA solved → form proceeds | Incorrect CAPTCHA → error, refresh offered | Audio CAPTCHA solved via screen reader → accepted | Ensure CAPTCHA widget is operable via keyboard, provides accessible alternative | Try to automate CAPTCHA bypass using OCR; verify server‑side rate limiting blocks repeated failures |
How to use the matrix
- For each form, list its fields and map them to the rows that apply.
- Populate the columns with concrete test data (valid, invalid, boundary).
- Assign each test case a unique ID for traceability in test management tools.
- Mark whether the test is automated, manual, or both.
The matrix guarantees that you do not overlook any validation dimension and provides a reusable template for future forms.
How to Test Form Validation: A Complete Guide – Manual Testing Techniques
Manual testing remains indispensable for exploratory work, usability assessment, and catching issues that automated scripts ignore (e.g., visual layout of error messages, screen‑reader announcements). Below are proven techniques.
Exploratory Testing with Personas
Adopt distinct user personas to stress‑test validation from different angles:
| Persona | Behavior Focus | Typical Findings |
|---|---|---|
| Curious | Tries every combination, clicks help icons, hovers over fields | Tooltips that reveal validation rules, hidden fields that become visible |
| Impatient | Submits form repeatedly, ignores inline validation, relies on submit‑only feedback | Missing inline validation, delayed server errors causing confusion |
| Novice | Prefers default values, avoids special characters, struggles with complex masks | Overly complex input masks, lack of placeholder guidance |
| Adversarial | Attempts SQLi, XSS, buffer overflow, file‑type tricks | Server‑side validation gaps, client‑side bypasses |
| Elderly | Uses larger fonts, relies on keyboard navigation, may have tremors | Touch targets too small, error messages disappearing too fast |
| Accessibility | Uses screen reader, high‑contrast mode, voice control | Missing aria-describedby, focus not moving to first error, color‑only cues |
| Power user | Pastes large blocks, uses autocomplete, exploits keyboard shortcuts | Performance degradation on large paste, autocomplete suggesting invalid values |
| International | Enters locale‑specific formats (e.g., commas as decimal separator) | Validation that assumes US number format, date parsing failures |
During a session, note any deviation from expected validation behavior, capture screenshots or video, and log the persona that discovered the issue. This approach often surfaces validation logic that is tightly coupled to UI state (e.g., a field that becomes required only after a checkbox is checked) and that unit tests might miss if they only test the field in isolation.
Checklist‑Driven Manual Tests
For regression or sanity checks, use a lightweight checklist derived from the test matrix. Example checklist for a registration form:
- Required fields – Leave each required field blank individually; verify inline error appears and focus shifts.
- Email format – Test valid, missing
@, missing domain, multiple@, leading/trailing spaces. - Password strength – Enforce minimum length, require at least one digit, one uppercase, one special char; test each rule in isolation.
- Confirm password – Match, mismatch, both empty.
- Phone number – Accept international format, reject letters, enforce max length.
- Date of birth – Calendar picker yields valid date; manual entry rejects future dates, invalid month/day combos.
- Terms checkbox – Must be checked; verify error when unchecked.
- Submit disabled while invalid – Ensure button stays disabled until all fields pass client‑side validation.
- Server error handling – Disable JavaScript, submit with invalid data; verify server returns 400 with clear message.
- Accessibility – Navigate with Tab, ensure each error is announced; switch to high contrast, ensure error text meets 4.5:1 contrast.
Run the checklist after each UI change; any failure triggers a deeper investigation.
Tools for Manual Validation
- Browser dev tools – Use the Elements panel to inspect
aria-invalid,pattern, and validation messages. Use the Console to triggercheckValidity()on form elements. - Mobile emulators – Android Studio emulator or Xcode Simulator to test native input masks and keyboard behavior.
- Accessibility auditors – axe-core, Lighthouse, or VoiceOver/iOS Accessibility Inspector to verify that validation messages are perceivable.
- Proxy tools – Burp Suite or OWASP ZAP to intercept and tamper with HTTP requests, confirming server‑side validation.
- Manual test charters – Write short exploratory sessions (e.g., “Try to submit the form with only special characters in every field for 5 minutes”) and record findings.
These techniques ensure that validation is not only functionally correct but also usable and perceivable by all users.
How to Test Form Validation: A Complete Guide – Automated Testing Strategies
Automation provides repeatability, regression safety, and the ability to run thousands of validation permutations quickly. The key is to test at the right layer: unit, API, and UI.
Unit‑Level Validation Tests
If validation logic resides in pure functions (e.g., isValidEmail(email)), unit tests are fast and deterministic. Example using Jest:
// utils/validation.js
export const isEmail = (str) => {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(str);
};
// utils/validation.test.js
import { isEmail } from './validation';
describe('email validation', () => {
test('accepts valid emails', () => {
expect(isEmail('foo@bar.com')).toBe(true);
expect(isEmail('user.name+tag@sub.domain.co.uk')).toBe(true);
});
test('rejects invalid emails', () => {
expect(isEmail('plainaddress')).toBe(false);
expect(isEmail('@missing-local.com')).toBe(false);
expect(isEmail('missing@domain.')).toBe(false);
expect(isEmail('spaces @here.com')).toBe(false);
});
test('handles edge cases', () => {
expect(isEmail('')).toBe(false);
expect(isEmail('a@b.co')).toBe(true); // minimal valid
expect(isEmail('very.long.local-part@very.long.domain.name')).toBe(true);
});
});
Run these tests on every commit; they guard against regressions in the validation core.
UI‑Level Automated Tests (Selenium, Playwright, Appium)
UI tests simulate real user interaction and verify that client‑side feedback and server responses align. Below is a Playwright script for a login form:
// tests/login.spec.js
const { test, expect } = require('@playwright/test');
test.describe('Login form validation', () => {
test.beforeEach(async ({ page }) => {
await page.goto('https://example.com/login');
});
test('shows inline error for empty fields', async () => {
await page.click('button[type="submit"]');
await expect(page.locator('#email-input')).toHaveAttribute('aria-invalid', 'true');
await expect(page.locator('#email-error')).toHaveText(/Email is required/);
await expect(page.locator('#password-input')).toHaveAttribute('aria-invalid', 'true');
await expect(page.locator('#password-error')).toHaveText(/Password is required/);
});
test('rejects malformed email', async () => {
await page.fill('#email-input', 'notanemail');
await page.fill('#password-input', 'ValidPass1!');
await page.click('button[type="submit"]');
await expect(page.locator('#email-error')).toHaveText(/Enter a valid email/);
await expect(page.locator('#password-error')).not.toBeVisible();
});
test('accepts valid credentials and navigates', async () => {
await page.fill('#email-input', 'user@example.com');
await page.fill('#password-input', 'Secure$123');
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/^https:\/\/example\.com\/dashboard/);
});
test('error message is announced by screen reader (using axe)', async () => {
await page.fill('#email-input', 'bad');
await page.click('button[type="submit"]');
const axeResults = await page.evaluate(async () => {
return await axe.run(); // assumes axe-core injected
});
expect(axeResults.violations).toHaveLength(0);
});
});
Key points:
- Use
aria-invalidand associated error elements to assert validation state. - Verify that the submit button is disabled until the form passes client‑side checks (if applicable).
- Run the test in multiple browsers (Chromium, Firefox, WebKit) to catch browser‑specific quirks.
- For mobile, replace Playwright with Appium and interact with native text fields and pickers.
API‑Level Contract Tests
When the form submits to a REST or GraphQL endpoint, test the contract directly. This bypasses the UI and isolates server validation. Example using Pact (consumer‑driven contract) or plain HTTP client:
# Using curl to test a registration endpoint
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"email":"","password":"123"}' \
-i
Expected response:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{"errors":[{"field":"email","message":"Email is required"},{"field":"password","message":"Password must be at least 8 characters"}]}
Automate this with a script that iterates over a matrix of payloads:
# test_api_validation.py
import requests, itertools
BASE = "https://api.example.com/users"
cases = [
({"email": "valid@example.com", "password": "Abcdefg1!"}, 201),
({"email": "", "password": "Abcdefg1!"}, 400),
({"email": "invalid", "password": "Abcdefg1!"}, 400),
({"email": "valid@example.com", "password": "short"}, 400),
({"email": "valid@example.com", "password": "A"*101}, 400), # too long
]
for payload, expected in cases:
resp = requests.post(BASE, json=payload)
assert resp.status_code == expected, f"Failed on {payload}: got {resp.status_code}"
Running this in CI catches contract drifts early.
Data‑Driven and Parameterized Approaches
Most test frameworks support data providers. Use them to avoid writing repetitive test functions. Example with TestNG:
@DataProvider(name = "emailCases")
public Object[][] emailData() {
return new Object[][]{
{"user@domain.com", true},
{"user@domain", false},
{"user@domain.", false},
{"user@@domain.com", false},
{"", false},
{" ", false},
};
}
@Test(dataProvider = "emailCases")
public void testEmailValidation(String input, boolean expected) {
boolean result = Validator.isEmail(input);
Assert.assertEquals(result, expected, "Validation failed for: " + input);
}
Parameterized tests scale to hundreds of boundary values (e.g., length 0‑255 for a VARCHAR field) with minimal code.
Integrating Automation Layers
A robust validation test suite runs all three layers in a pipeline:
- Unit tests on every commit (fast feedback).
- API contract tests after build, before UI tests (ensures backend contract).
- UI tests on a staging environment nightly or on pull‑request validation (covers end‑to‑end).
Use test reporting tools (Allure, JUnit HTML) to aggregate results and highlight which layer failed.
How to Test Form Validation: A Complete Guide – Production‑Only Edge Cases
Some validation bugs only manifest when the software runs under real‑world load, with real browsers, extensions, or network quirks. Anticipating these reduces post‑release incidents.
Race Conditions and Async Submission
If the form disables the submit button after the first click but re‑enables it on a failed validation response, a rapid double‑click can cause two submissions. Test by simulating a fast double click:
// Playwright
await page.click('button[type="submit"]');
await page.click('button[type="submit"]', { delay: 50 }); // 50ms between clicks
await expect(page.locator('.submit-success')).toHaveCount(1);
Server‑side should enforce idempotency (e.g., using a nonce token) or reject duplicate requests.
Third‑Party Widget Interference
Widgets like date pickers, autocomplete libraries, or payment iframes can override native validation events. For example, a jQuery UI datepicker may set the input value via .val() without triggering input events, causing custom validation handlers to miss the change. Test by:
- Selecting a date via the widget, then programmatically invoking the validation function and asserting the state.
- Checking that the widget’s
onSelectoronChangecallback calls your validation logic.
Locale and Input Method Edge Cases
Users may input text via IME (Input Method Editor) for Chinese, Japanese, Korean, or via voice dictation. These methods can produce composition events where the intermediate state is not a final string. Validation that runs on keyup may see incomplete composition and incorrectly reject valid input. Test by:
- Using an IME to compose a character sequence (e.g., typing “p y” to get “ぴ”).
- Ensuring validation only fires on
compositionendor after the committed value appears.
Browser Extension and Ad‑Blocker Effects
Extensions that modify DOM (e.g., password managers autofilling fields, ad blockers removing elements) can inadvertently invalidate assumptions. A password manager might pre‑fill a field with a value that contains spaces; if your trim logic runs before the autofill, the spaces remain and cause failure. Test by:
- Installing common extensions (LastPass, Bitwarden, uBlock Origin) in a test profile.
- Running the form flow and observing whether autofilled values trigger false positives or mask real errors.
Network Latency and Partial Page Loads
If validation depends on an asynchronous call (e.g., remote username availability check), a slow network can leave the field in an indeterminate state. Simulate throttling:
// Playwright context
const context = await browser.newContext({
viewport: { width: 1280, height: 800 },
offline: false,
});
await context.route('**/api/username-check', route => {
return route.fulfill({ status: 200, body: JSON.stringify({available:true}), delay: 2000 });
});
Then attempt to submit before the response arrives; the UI should either block submission or show a loading indicator, not a false success.
Concurrent Form Instances
Single‑page applications may allow opening multiple modals with the same form (e.g., multiple “add address” dialogs). State leakage between instances can cause validation to read values from the wrong dialog. Open two modals, fill different data, submit each, and verify that each submission uses only its own fields’ values.
By incorporating these production‑focused scenarios into your test plan—either as automated stress tests or as periodic exploratory sessions—you reduce the chance that a validation bug survives to release.
How to Test Form Validation: A Complete Guide – Leveraging Autonomous, Persona‑Driven Exploration
Scripted tests excel at checking known paths, but they can miss unexpected interaction patterns. Autonomous exploration tools that drive the application without pre‑written steps can uncover hidden validation flaws by exercising the UI as real users would, guided by behavior models.
How SUSA Explores Forms Without Scripts
SUSA (the autonomous QA platform) begins by crawling the application: it loads the page or screen, discovers all interactive elements (inputs, buttons, selects), and builds a state graph. For each form, it generates input actions based on a library of heuristics (e.g., try empty, try max length, try special characters, try paste from clipboard). It then executes those actions while monitoring for:
- JavaScript errors or uncaught promises.
- Changes in DOM attributes like
aria-invalidoraria-describedby. - Network responses indicating validation failures (4xx) or successes (2xx).
- Accessibility tree updates (e.g., new error announcements).
Because SUSA does not rely on a predetermined script, it can try combinations that a tester might overlook, such as filling a field, clearing it via the browser’s “clear” button, then pasting a large string, all while observing validation state changes in real time.
Persona Profiles and What They Reveal
SUSA’s exploration is guided by configurable persona profiles, each weighting actions differently:
| Persona | Action Bias | What It Uncovers |
|---|---|---|
| Curious | High frequency of edge‑value inputs, rapid field toggling | Hidden validation triggers that only appear after multiple state changes |
| Impatient | Rapid successive submits, minimal waiting for async calls | Race conditions, delayed error display, premature enabling of submit |
| Novice | Preference for defaults, avoidance of special chars, reliance on placeholders | Overly complex masks, missing guidance, placeholder text that interferes with validation |
| Adversarial | Injection patterns, fuzzing, oversized payloads | Server‑side validation bypasses, WAF misconfigurations, client‑side sanitization gaps |
| Elderly | Larger touch targets, reliance on keyboard navigation, slower input speed | Touch‑target size issues, timeout‑based validation that fires too fast |
| Accessibility | Screen‑reader navigation, high‑contrast mode, voice input simulation | Missing aria-describedby, focus not moving to first error, color‑only cues |
| Power User | Clipboard paste, autocomplete exploitation, keyboard shortcuts | Performance degradation on large paste, autocomplete suggesting invalid values |
| International | Locale‑specific formats, IME composition, right‑to‑left language switching | Date/number parsing errors, IME composition mishandling, RTL layout breaking validation messages |
When SUSA runs, it logs each action, the resulting validation state, and any anomalies. The output is a set of reproducible steps (e.g., “fill email with test@, clear via backspace ×5, paste a.repeat(5000)`, observe server 413”) that can be exported as a Playwright or Appium script for regression.
Integrating Autonomous Findings into CI
To make autonomous exploration part of your delivery pipeline:
- Schedule a nightly run against a staging build.
- Export the discovered failure steps as JSON artifacts.
- Convert JSON to executable tests using a small adapter (e.g., a Node script that reads the JSON and generates Playwright test files).
- Fail the build if any new high‑severity issue (crash, security bypass, WCAG AA violation) appears.
Because Susa’s engine learns from prior runs—remembering which paths led to dead ends or crashes—it reduces redundant exploration over time, focusing on novel interactions. This complements scripted suites: unit and API tests guard the deterministic core, while autonomous exploration surfaces the unpredictable, user‑driven edge cases that often escape manual test plans.
How to Test Form Validation: A Complete Guide – Actionable Checklist and Takeaways
Having covered theory, techniques, and tools, here is a concise, ready‑to‑use checklist you can apply before any release. Follow it in order; each item should yield a clear PASS/FAIL outcome.
Pre‑Release Validation Checklist
| # | Check | How to Verify | PASS Criteria |
|---|---|---|---|
| 1 | All required fields show inline error when empty | Tab through form, leave each blank, submit | Error message appears, field receives aria-invalid=true, focus moves to first empty field |
| 2 | Email field accepts valid formats and rejects invalid | Use matrix of valid/invalid strings | Valid → success or next step; Invalid → specific error, not generic “invalid input” |
| 3 | Password strength rules are enforced individually | Test each rule (length, digit, upper, lower, special) in isolation | Violating a single rule yields error referencing that rule |
| 4 | Confirm password matches password field | Match, mismatch, both empty | Only matched → success; mismatch → error on confirm field |
| 5 | Phone number respects international format and max length | Test with +1-555-123-4567, +44 7911 123456, +91-9876543210, letters | Correct formats accepted; others rejected with clear hint |
| 6 | Date of birth prevents future dates and invalid combos | Use calendar picker and manual entry | Future date → error; 31‑Feb → error; valid past date → success |
| 7 | Terms checkbox must be checked | Submit unchecked, then checked | Unchecked → error; checked → proceeds |
| 8 | Submit button disabled while any client‑validation fails | Observe button state while filling incorrectly | Button remains disabled until all client checks pass |
| 9 | Server returns 400 with field‑specific messages for invalid payloads | Disable JS, submit malformed JSON | Response body contains JSON errors mapping each field to a message |
| 10 | Error messages are perceivable by assistive tech | Run axe-core, test with VoiceOver/NVDA | No WCAG AA violations; each error announced, sufficient contrast |
| 11 | No ReDoS or buffer overflow via extreme inputs | Paste 10 KB string into a 20‑char limit, test regex with crafted payload | Input truncated or rejected; no hang or crash |
| 12 | Autocomplete and password manager do not break validation | Enable common extensions, autofill, submit | Autofilled values treated like manual entry; validation behaves consistently |
| 13 | IME composition does not trigger premature validation | Type with Japanese IME, observe validation only on commit | Validation waits for compositionend |
| 14 | Duplicate submission prevented under rapid clicks | Double‑click submit with 50 ms interval | Only one request sent; server responds with idempotency token or error |
| 15 | Modal form instances do not leak state | Open two modals, fill different data, submit each | Each submission uses only its own field values |
| 16 | Accessible error announcement on dynamic validation | Trigger inline error via input event, listen with screen reader | Error announced immediately after field loses focus or on blur |
| 17 | Visual contrast of error text meets 4.5:1 | Use color contrast analyzer on error messages | All error text ≥ 4.5:1 against background |
| 18 | Help text or placeholder does not mask validation errors | Fill field, cause error, check that placeholder disappears or is overridden | Error visible, not hidden behind placeholder |
| 19 | Submission succeeds with all valid data and leads to expected state | Fill form with correct data, submit | Success toast/redirect, database reflects correct entry |
| 20 | Performance under load does not degrade validation | Run 50 concurrent submissions via artillery or k6 | Average response time < 2 s, no 5xx errors |
If any check fails, treat it as a blocker until resolved. Automate as many items as possible (e.g., 1‑9 via API tests, 10‑18 via UI + axe, 19‑20 via load scripts) and keep the manual steps for exploratory sessions.
Post‑Release Monitoring Tips
- **
Test Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free