Promo Codes Testing Checklist (2026)
Promo Codes Testing Checklist (2026)
Promo Codes Testing Checklist (2026)
A promo code is a short alphanumeric token that unlocks a discount, free trial, gift, or other incentive when entered during checkout or account creation. Testing promo codes thoroughly prevents revenue leakage, protects brand trust, and avoids regulatory pitfalls. The checklist below groups 38 concrete items into seven functional areas plus a release‑readiness section. Each item includes a pass criterion, a real‑world example, and notes on how manual, automated, or autonomous exploration (e.g., with SUSA) can cover it.
---
Promo Codes Testing Checklist (2026) – Happy Path
Core redemption flow
| # | Test Item | Pass Criterion | Example | Automation Hint |
|---|---|---|---|---|
| 1 | Valid code entry on checkout page | Discount applied correctly, order total reflects new amount, confirmation shows code used | Code “SPRING20” gives 20 % off a $100 cart → $80 total | UI test enters code, asserts price change |
| 2 | Code applied before payment | Discount visible on cart summary before proceeding to payment | User sees “- $20” line item after code entry | Assert DOM element text before “Pay” button click |
| 3 | Code works on first‑time user | New account receives discount, no prior purchase required | Guest checkout with code “WELCOME10” → 10 % off | Create fresh test user, run flow |
| 4 | Code works for returning user | Existing logged‑in user can redeem without re‑authentication | Logged‑in user applies “LOYALTY15” → discount applied | Use session cookie or login API |
| 5 | Code works across devices | Same code yields identical discount on mobile web, native app, and desktop | Code “BLACKFRIDAY” works on iOS app, Android web, Chrome | Run matrix of device/OS combos |
| 6 | Code works with multiple items | Discount applies to cart total, not per‑item unless specified | Cart with 3 items ($30 each) → 10 % off total $90 → $81 | Assert total after code entry |
| 7 | Code works with shipping taxes | Discount calculated before tax/shipping or after, per business rule | If discount pre‑tax: $100 + $10 tax → 20 % off $100 = $80 + $10 tax = $90 | Verify tax line matches rule |
| 8 | Code works with gift cards | Gift‑card balance + promo discount both applied | $50 gift card + “SAVE5” → $5 off → final $45 charge | Check both balances updated |
| 9 | Code works with subscription plans | Recurring discount applied to first billing cycle | Code “FIRSTMONTHFREE” → $0 first month, then regular price | Verify subscription object shows discount flag |
| 10 | Code works with bundled offers | Bundle discount stacks or does not stack per policy | Bundle “BOXSET” 15 % off + code “EXTRA10” → either 23.5 % stacked or 15 % only | Validate against promo‑stacking rule |
Success messaging & receipt
| # | Test Item | Pass Criterion | Example | Automation Hint |
|---|---|---|---|---|
| 11 | Success toast/message appears | Non‑blocking toast with code name and discount amount displayed for ≥2 s | “SPRING20 applied – saved $20” | Wait for toast element, assert text |
| 12 | Order confirmation email includes code | Email body lists redeemed promo and discounted amount | “Promo: SPRING20 – Discount: $20.00” | Parse email fixture, assert substring |
| 13 | Order history shows promo usage | User’s order detail page shows promo code field populated | Order #12345 → Promo: WELCOME10 | API GET /orders/{id} assert promo field |
| 14 | Loyalty points adjusted (if applicable) | Points earned reflect discounted spend, not original | Spend $80 after 20 % off → earn 8 points (10 pts/$) | Check points balance after order |
| 15 | Referral credit not double‑counted | If promo and referral both apply, each credited once | Referral gives $5, promo gives 10 % → total correct | Verify both credits in ledger |
---
Promo Codes Testing Checklist (2026) – Error Handling
Invalid code detection
| # | Test Item | Pass Criterion | Example | Automation Hint |
|---|---|---|---|---|
| 16 | Non‑existent code | Error message “Invalid promo code” displayed, no discount applied | Enter “FAKE123” → toast: “Code not found” | Assert error element visible, price unchanged |
| 17 | Expired code | Message “This promo has expired” | Enter “SUMMER21” after 30 Sep 2021 → error | Set system date or use backend flag |
| 18 | Code used beyond usage limit | Message “This promo has reached its usage limit” | Code limited to 100 uses, 101st entry fails | Pre‑populate usage counter via API |
| 19 | Code not applicable to cart items | Message “Promo not valid for selected items” | Code for “Shoes only”, cart contains a shirt | Verify error, discount not applied |
| 20 | Code requires minimum spend | Message “Spend $50 to use this promo” | Cart $30 + code “SAVE10” → error | Test cart just below and just above threshold |
| 21 | Code restricted to user segment | Message “This promo is for new users only” | Existing user tries “NEWUSER20” → error | Attach user‑type flag, assert denial |
| 22 | Code case‑sensitivity handling | System treats code as case‑insensitive (or as defined) | If case‑insensitive, “spring20” works; if strict, fails | Try both variations |
| 23 | Code with special characters | Accepts hyphen, underscore, or rejects per spec | “SPRING-20” accepted; “SPRING@20” rejected if not allowed | Send varied strings, check response |
| 24 | Leading/trailing whitespace | System trims whitespace before validation | Enter “ SPRING20 ” → accepted | Send code with spaces, assert success |
| 25 | Code length limits | Rejects codes shorter than min length or longer than max | Min 5, max 12 → “ABCD” rejected, “ABCDEFGHIJKL” rejected | Boundary test with 4,5,12,13 chars |
| 26 | Duplicate submission prevention | Second submit of same code shows “already applied” not error | After first apply, clicking Apply again → toast “Code already used” | Click button twice, verify state |
| 27 | Network timeout fallback | UI shows retry option, does not apply discount twice | Simulate 5 s delay on /apply endpoint → show retry | Mock server delay, assert UI behavior |
| 28 | Server error (5xx) handling | Shows generic “Try again later”, does not consume code | Return 500 on apply → error toast, code still valid | Mock 500, verify code not marked used |
| 29 | Client‑side validation bypass | Even if JS disabled, server rejects invalid code | Disable JS, submit “BADCODE” → server error | Use curl or fetch without JS, assert 400 |
| 30 | Race condition under high load | Concurrent requests for same limited‑use code grant discount to only one user | 10 users submit same code simultaneously → only 1 succeeds | Use k6 or Locust to fire parallel requests, check counts |
---
Promo Codes Testing Checklist (2026) – Edge / Boundary Cases
Discount calculations
| # | Test Item | Pass Criterion | Example | Automation Hint |
|---|---|---|---|---|
| 31 | Percentage >100% | System rejects or caps at 100 % (per policy) | Code “FREE200” → error or free item | Try 150 % code, assert rejection or zero price |
| 32 | Fixed amount > cart total | Discount cannot make total negative; total set to $0 | Cart $5, code “TAKE10” → $0 total, not –$5 | Assert max(0, total‑discount) |
| 33 | Fractional cents handling | Rounding follows bankers’ rounding or defined rule | $49.99 with 33 % off → $33.4935 → $33.49 or $33.50 | Compute expected, assert exact cents |
| 34 | Multiple percentage stacks | If stacking allowed, apply sequentially not additively | 10 % then 10 % on $100 → $81, not $80 | Apply two codes, verify final |
| 35 | Tiered discount thresholds | Different % based on spend brackets | $0‑$49 → 5 %; $50‑$99 → 10 %; $100+ → 15 % | Test cart values at each boundary |
| 36 | Time‑zone sensitivity | Promo active based on UTC start/end, not local | Code active 00:00 UTC Jan 1 – 23:59 UTC Jan 31 | Set device TZ, verify activation/inactivation |
| 37 | Daylight‑saving shift | No double‑count or skip when clocks change | Promo runs 01:00‑03:00 local, DSB shift → still 2 h window | Simulate clock change, check active period |
| 38 | Leap year February 29 | Promo scheduled for Feb 29 works only on leap years | Code “LEAP2024” active Feb 29 2024, not 2025 | Set date to 2024‑02‑29, assert active; 2025‑02‑28 assert inactive |
Input & UI edge cases
| # | Test Item | Pass Criterion | Example | Automation Hint |
|---|---|---|---|---|
| 39 | Max length field | Input field accepts up to defined max, blocks extra | Field max 12 → typing 13th char blocked or trimmed | Send long string, assert length |
| 40 | Paste from clipboard | Pasted code validated same as typed | Paste “SPRING20” → works | Use clipboard API in test |
| 41 | Autocomplete suggestions | No suggestion reveals inactive or expired codes | Typing “SPR” shows only active codes | Observe dropdown, assert no expired |
| 42 | Right‑to‑left language layout | Field aligns correctly, cursor moves as expected | Arabic UI: code entry right‑aligned | Switch locale, inspect direction |
| 43 | Zoom level 200% | All elements readable, no overlap | Promo entry visible at 200% zoom | Set browser zoom, assert no overflow |
| 44 | Screen orientation change | State preserved on rotate | Enter code, rotate to landscape → code still shown | Rotate device/emulator, assert field value |
| 45 | Hardware keyboard vs on‑keyboard | Both produce same result | Desktop keyboard entry works, mobile OSK works | Test both input methods |
| 46 | Voice input transcription | Voice‑to‑text yields correct code | Say “spring two zero” → “SPRING20” | Use speech API, verify result |
| 47 | Barcode/QR code scan | Scanned code populates field and validates | Scan QR encoding “SPRING20” → field filled | Use camera mock, assert success |
| 48 | Copy‑protected field | Right‑click copy disabled if required | Attempt to copy code from tooltip → blocked | Try document.execCommand('copy'), expect failure |
| 49 | Invalid Unicode normalization | Different visual forms treated same | “SPRING20” with full‑width chars → accepted | Send full‑width variants, assert same outcome |
| 50 | Emoji injection | Emoji ignored or causes validation error | Enter “SPRING20😀” → rejected | Send emoji, assert error |
---
Promo Codes Testing Checklist (2026) – Accessibility
| # | Test Item | Pass Criterion | Example | Automation Hint |
|---|---|---|---|---|
| 51 | Label association | Each input has associated or aria-label | | axe-core asserts label present |
| 52 | Keyboard navigable | Tab moves focus to code field, Apply button, then next | Tab order: field → button → continue | Simulate Tab key, check focus order |
| 53 | Visible focus indicator | Field shows outline ≥2 px when focused | CSS outline: 2px solid #005fcc | Check computed style on focus |
| 54 | Error message ARIA live | Invalid code triggers aria-live="assertive" region | | Assert live region updates on error |
| 55 | Contrast ratio | Text and background meet WCAG AA (≥4.5:1) | Promo text #212529 on #fff → 7.5:1 | Use axe or manual contrast tool |
| 56 | Scalable text | Up to 200% text size does not break layout | Increase browser font size → field still usable | Set font-size: 200%, assert no overflow |
| 57 | Screen reader announces discount | After successful apply, reader says “Promo SPRING20 applied, saved $20” | Use NVDA or TalkBack to verify | Record utterance, assert phrase |
| 58 | Touch target size | Apply button ≥44 dp × 44 dp | Button dimensions 48 × 48 dp | Measure via UIAutomator or Espresso |
| 59 | Reduced motion respected | Animation disabled if prefers-reduced-motion | No fade/tooltip slide when setting enabled | Check CSS media query, assert no animation |
| 60 | High contrast mode | Colors invert or adapt correctly | In Windows HC mode, promo field uses system colors | Enable HC, assert readable contrast |
| 61 | Language switch preserves state | Changing language does not clear entered code | Enter code, switch to French → code still present | Change lang attribute, assert field value |
| 62 | Error announcement timing | Error announced within 400 ms of invalid entry | Live region triggers promptly | Measure time between input and screen reader output |
| 63 | Focus returned after modal | After promo‑info modal closes, focus returns to field | Close “How promo works” dialog → focus on field | Trigger modal, close, assert activeElement |
| 64 | No placeholder as sole label | Placeholder not used as only label (fails WCAG) | Field has both placeholder and visible label | Inspect DOM, fail if only placeholder |
| 65 | Accessible name for icon-only button | Apply button with icon has aria-label="Apply promo" | Icon button | Assert aria-label present |
| 66 | Skip link to promo field | Early skip link jumps directly to promo entry | Skip to promo | Activate link, assert focus on field |
| 67 | Responsive breakpoint accessibility | Layout does not hide promo field on small screens | @media (max-width:320px) field still visible | Resize viewport, assert field present |
| 68 | No autoplay audio on promo page | Page does not play sound automatically | No | Scan DOM for audio elements without user gesture |
| 69 | Error message announced in user language | If UI language is Spanish, error appears in Spanish | “Código no válido” | Change locale, assert translated message |
| 70 | Focus trap in modal | When promo‑info modal opens, tab does not escape | Tab cycles within modal until closed | Open modal, press Tab repeatedly, assert focus stays inside |
---
Promo Codes Testing Checklist (2026) – Security & Privacy
| # | Test Item | Pass Criterion | Example | Automation Hint |
|---|---|---|---|---|
| 71 | Code leakage in URL | Promo code never appears in query string or fragment | https://shop.example/cart?promo=SPRING20 → forbidden | Inspect network calls, assert no promo in URL |
| 72 | Code masked in logs | Backend logs replace promo with * | Log line: Applied promo: **** | Check log samples, assert masking |
| 73 | Rate limiting on apply endpoint | Max N requests per IP/minute to prevent brute force | 10 requests/min → 11th returns 429 | Use curl loop, assert 429 after limit |
| 74 | JWT/session binding | Promo apply requires valid authenticated session | Anonymous POST to /apply returns 401 | Send request without cookie, assert 401 |
| 75 | Code entropy check | System rejects predictable sequences (e.g., “111111”) | “111111” → error “code too weak” | Try weak patterns, assert rejection |
| 76 | No SQL injection via promo field | Input sanitized, injection attempt fails | ' OR 1=1-- → error, no DB error | Send payload, assert no 500, DB unchanged |
| 77 | No XSS via promo display | Rendered code escaped, no script execution | rendered as text | Inject script, assert not executed in DOM |
| 78 | CSP blocks inline script | Content‑Security‑Policy prevents inline JS from promo UI | script-src 'self' blocks attempts | Verify CSP header, try to inject |
| 79 | Rate limit per code per user | Same user cannot apply same code more than allowed limit | User tries apply 5 times → after 1st, further attempts blocked | Loop apply, assert 403/429 after first |
| 80 | Audit log capture | Each apply/create/delete logged with user ID, timestamp, IP | Log entry: user_id=42, promo=SPRING20, action=apply | Query audit table, assert fields |
| 81 | GDPR right to erasure | Deleting user account removes associated promo usage records | After delete, query shows no promo usage for that user | Delete user, assert no rows in promo_usage |
| 82 | Data minimization | Only necessary promo metadata stored (code, discount, validity) | No storage of full cart contents with promo | Inspect DB schema, assert minimal columns |
| 83 | Secure transmission | All promo‑related API calls use HTTPS with TLS 1.2+ | https://api.example/promo/apply TLS 1.3 | Use Wireshark or sslyze to confirm |
| 84 | Code expiration enforcement server-side | Even if client tampers with date, server rejects expired | Set client date to past, send expired code → server 400 | Mock client time, assert server rejection |
| 85 | Promo code regeneration after breach | If a code is leaked, system can invalidate and issue new | Admin revokes “LEAKED123”, issues “LEAKED123v2” | Call revoke API, verify old code fails, new works |
| 86 | No promo code in error messages | Error does not reveal whether code exists or not | Generic “Invalid promo” not “Code SPRING20 not found” | Test with valid vs invalid, compare messages |
| 87 | Rate limit exemption for internal tools | Internal admin tools have higher limits, but still logged | Admin can bulk‑load 1000 codes/min | Test with admin token, assert allowed, logged |
| 88 | Promo code cannot be guessed via sequential enumeration | Predictable pattern (e.g., SPRING01‑SPRING99) not all valid | Only some in range active, others invalid | Brute‑force range, assert only expected succeed |
| 89 | Secure random generation | Codes generated using CSPRNG, not simple rand() | Distribution uniform over 62^8 space | Sample 10k codes, chi‑square test for uniformity |
| 90 | Expiration stored as UTC timestamp | Avoids ambiguity across time zones | DB column expires_at TIMESTAMP WITH TIME ZONE | Verify column type, assert UTC storage |
---
Promo Codes Testing Checklist (2026) – Performance
| # | Test Item | Pass Criterion | Example | Automation Hint |
|---|---|---|---|---|
| 91 | Apply latency < 300 ms (p95) | 95 % of promo apply calls return within 300 ms under normal load | Measure with k6, assert p95 ≤300ms | Run load test, extract percentile |
| 92 | Throughput ≥ 500 applies/sec | System sustains at least 500 successful apply requests per second | Load test with 500 VUs, 2 sec ramp | Check requests/sec metric |
| 93 | Cache hit ratio ≥ 80 % for valid codes | Frequently used codes served from Redis/Memcached | After warm‑up, 8 out of 10 reads hit cache | Inspect cache stats, assert ratio |
| 94 | No memory leak during repeated applies | Heap growth < 5 MB after 100k apply cycles | Run loop, monitor process memory | Use pmem or valgrind, assert bound |
| 95 | Database lock contention minimal | Average lock wait time < 10 ms under 200 VU | Check DB pg_locks or innodb_lock_wait | Query pg_stat_activity, assert low wait |
| 96 | Async discount calculation non‑blocking | UI does not freeze while calculating complex tiered discount | Measure main thread JS idle time | Use Chrome DevTools Performance, assert < 50ms block |
| 97 | Bulk promo upload endpoint ≤ 2 s per 1k codes | Admin can upload 1k codes in ≤2 seconds | POST /promo/bulk with 1k JSON objects | Time request, assert ≤2000ms |
| 98 | Graceful degradation under high latency | If promo service slow, UI shows “Applying…” spinner, not blank | Simulate 2 s delay, assert spinner visible | Mock latency, assert UI state |
| 99 | Rate limit headers present | Response includes X-RateLimit-Limit, X-RateLimit-Remaining | Header: X-RateLimit-Limit: 60 | Check response headers |
| 100 | Payload size ≤ 2 KB for apply request | JSON body small to save bandwidth | { "promo": "SPRING20" } ≈ 22 bytes | Measure request size, assert < 2048 |
| 101 | Promo validation does not trigger full cart recompute unnecessarily | Only affected line items recalculated | If promo applies to shipping only, cart, say, items with tag “electronics”, only those items recomputed | Instrument backend, assert limited recompute calls |
| 102 | Discount calculation uses fixed‑point arithmetic | Avoid floating‑point rounding errors in high volume | Use Decimal or integer cents | Inspect codebase for float usage, assert absent |
| 103 | Promo service scales horizontally | Adding another instance does not change latency | Deploy 2 vs 3 replicas, compare p95 latency | Run same load on different replica counts |
| 104 | HTTP/2 or QUIC used for promo calls | Multiplexing reduces connection overhead | Observe protocol in Chrome devtools Network | Assert h2 or h3 in protocol column |
| 105 | Promo-related third‑party calls (e.g., fraud check) have timeout ≤ 500 ms | Prevents hanging UI | Set stub to delay 600 ms → UI shows timeout fallback | Mock external service, assert fallback shown |
| 106 | Load test with mixed valid/invalid codes mimics real traffic | 80 % valid, 20 % invalid reflects production ratio | Run test with 80/20 mix, ensure error handling does not degrade valid path | Mix request types, assert valid latency unaffected |
| 107 | Auto‑scale trigger based on promo apply latency | Scale‑out if p95 latency > 250 ms for 2 min | Set CloudWatch alarm, verify new instance added | Simulate latency spike, observe autoscaling event |
| 108 | Promo API idempotent | Retrying same request with same idempotency key yields same result, no double discount | Send same request twice with Idempotency-Key: abc → second returns 200 with same discount, no extra deduction | Use idempotency header, assert balance unchanged after retry |
| 109 | Discount application does not cause database deadlock under concurrency | No deadlock errors when 100 users try to apply same limited‑use code | Run concurrent script, check DB logs for deadlock | Assert zero deadlock occurrences |
| 110 | Promo usage analytics pipeline keeps up with peak | Events flushed to Kafka/Warehouse within 2 s of apply | Measure lag from apply event to consumption | Assert lag < 2000ms |
---
Promo Codes Testing Checklist (2026) – Release Readiness
| # | Test Item | Pass Criterion | Example | Automation Hint |
|---|---|---|---|---|
| 111 | Feature flag toggle | Promo system can be disabled via flag without breaking checkout | Flip flag promo_enabled=false → checkout works, promo UI hidden | Toggle flag, assert promo fields absent |
| 112 | Rollback script validated | DB migration to add promo tables includes down‑script that removes them safely | Run migrate up, then down → schema same as pre‑mig | Execute migration scripts in test DB |
| 113 | Canary release monitoring | 5 % traffic routed to new promo version, error rate < 0.1 % | Deploy canary, watch SLO dashboard | Assert error rate stays below threshold |
| 114 | A/B test framework integration | Promo variations can be toggled per experiment ID | Experiment promo_discount_ab serves 10 % vs 15 % | Check experiment service returns correct variant |
| 115 | Documentation updated | Release notes include new promo fields, validation rules, and deprecations | Changelog entry: “Added max_uses_per_user field” | Search docs for keyword, assert present |
| 116 | Training for support team | Support has FAQ covering common promo issues (expired, usage limit) | FAQ article “Why is my promo not accepted?” exists | Verify internal knowledge base contains article |
| 117 | Monitoring alerts configured | Alert on promo apply failure rate > 2 % or latency > 400 ms | Prometheus rule: rate(promo_apply_errors[5m]) > 0.02 | Check alertmanager config, assert rule present |
| 118 | Load test sign‑off | Performance test results signed off by performance engineer | Document: “Promo apply p95 latency 210 ms @ 800 VU” | Locate sign‑off artifact, assert present |
| 119 | Security review completed | No open high‑severity findings in promo code handling | SAST/DAST report shows 0 critical | Retrieve report, assert severity count |
| 120 | Accessibility audit passed | Axe score ≥ 90 % on promo page | Run axe-cli, assert score ≥ 90 | Execute audit, capture score |
| 121 | Feature toggle for promo‑experiments | Ability to turn off experimental promo types without redeploy | Flag promo_exp_enabled=false hides beta UI | Toggle flag, assert experimental variants hidden |
| 122 | Deprecation notice for old promo format | If migrating from legacy alphanumeric to UUID‑based codes, notice shown | Banner: “Old promo format will be disabled 2026‑07‑01” | Check UI for banner when legacy code present |
| 123 | Rollback test in staging | Full end‑to‑end rollback of promo feature does not leave orphan data | Deploy rollback, run smoke test → no promo tables, no promo usage rows | Execute rollback, query DB for leftover rows |
| 124 | Customer‑facing communication prepared | Email/template ready to announce new promo types to users | Draft email: “Introducing SPRING20 – 20 % off sitewide” | Locate template, assert placeholders filled |
| 125 | Support runbook for promo incidents | Runbook includes steps to investigate promo‑apply failures, clear cache, check DB locks | Runbook doc ID: RUN-PROMO-01 | Verify runbook exists, contains required sections |
| 126 | Logging correlation ID present | Each promo request carries a trace ID linking frontend, backend, analytics | Header X-Trace-ID: a1b2c3d4 | Inspect request/response headers, assert ID present |
| 127 | Backwards compatibility for older clients | Clients on API v1 still able to apply promos via legacy endpoint | /v1/promo/apply returns same shape as /v2/promo/apply | Call v1 endpoint, assert response fields match v2 |
| 128 | Database indexes on promo columns adequate | Index on (code, active) ensures fast lookups | Explain query shows index usage | Run EXPLAIN on select, assert index used |
| 129 | Promo service health endpoint returns 200 with JSON {status:"OK"} | /health/promo responds quickly | GET /health/promo → {status:"OK"} in < 50 ms | Call endpoint, assert body and latency |
| 130 | Feature flag for promo‑specific experiments (e.g., stacked discounts) | Ability to enable/disable stacking per experiment without code change | Flag promo_allow_stacking=true/false | Toggle flag, assert stacking behavior changes |
---
How Autonomous Exploration Covers Most of This Checklist in One Pass
SUSA (SUSATest) is an autonomous QA agent that, given an APK or a web URL, explores the application like a combination of curious, impatient, novice, power‑user, and adversarial personas. It automatically generates UI interactions, API calls, and validation checks without hand‑written test scripts. When pointed at an e‑commerce flow that includes promo code entry, SUSA can satisfy a large subset of the checklist above:
| Checklist Area | Items Covered by SUSA (examples) | How SUSA Achieves It |
|---|---|---|
| Happy Path | 1‑10, 11‑15 (code entry, discount verification, messaging, email, loyalty) | SUSA’s “curious” persona tries every visible input, submits forms, reads toast messages, extracts order totals from the DOM, and can even sniff outbound emails via a test mailbox to validate confirmation content. |
| Error Handling | 16‑30 (invalid, expired, usage‑limit, segment restrictions, whitespace, duplicate submission, network faults) | The “adversarial” persona deliberately submits malformed data, expired codes (by manipulating system clock via environment variable), and repeats actions. SUSA also injects latency using network throttling plugins to provoke time‑outs and retries. |
| Edge/Boundary | 31‑38 (percentage caps, rounding, time‑zone, leap year, stacking) | By varying cart totals, applying multiple codes, and adjusting device time‑zone settings, SUSA’s “power‑user” persona explores edge arithmetic and temporal boundaries. |
| Accessibility | 51‑70 (labels, focus, ARIA live, contrast, screen‑reader announcements, touch targets) | SUSA runs axe‑core in the background on each page load, captures contrast failures, and uses accessibility APIs (e.g., UIAutomator on Android, AccessibilityTree on Chrome) to verify focus order, live region updates, and touch target sizes. |
| Security/Privacy | 71‑90 (URL leakage, logging masking, rate limits, injection, CSP, audit logs) | SUSA’s “novice” and “impatient” personas attempt common injection strings, inspect network logs for promos in URLs, and check response headers for security flags. It also hits the apply endpoint in a loop to trigger rate‑limit responses and validates that error messages do not leak existence info. |
| Performance | 91‑110 (latency, throughput, cache hit, memory leaks, scaling, idempotency) | By continuously driving the promo apply endpoint with varying load patterns (using its built‑in load‑generator), SUSA measures response times, tracks cache‑hit ratios via internal metrics, and watches for memory growth via process introspection. It also checks idempotency by resending the same request with a supplied idempotency key. |
| Release Readiness | 111‑130 (feature flags, migration scripts, canary monitoring, documentation, alerts) | While SUSA does not write release notes, it can verify that a feature flag truly hides/shows the promo UI, that migration scripts are reversible (by applying then rolling back in a test DB), and that health endpoints return expected payloads. It can also confirm that alerts fire when it deliberately induces error spikes. |
What SUSA does not replace
- Manual exploratory testing for subtle UX nuances (e.g., wording
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