Browse the Knowledge Hub56 resources
Test cases
Data integrity test cases, because a constraint in code is not a constraint
Twenty eight cases covering uniqueness under concurrency, orphaned rows and cascade rules, transaction rollback, lost updates and counter races, negative balances, deadlock retries, numeric and timestamp types, migration and backfill safety, soft delete leaks, tenant scoping, replica lag and verified restores.
All 28 test cases, ready to copy
Free to use and adapt, no sign-up. Download as CSV or Markdown, or copy it straight into your own tooling.
Last updated
28 worked examples
Enforce uniqueness at the database rather than in code
TypeBoundaryPriorityHigh- Test data
- Two concurrent inserts of the same logically unique value
- Expected result
- One succeeds and one fails on a constraint. A check followed by an insert in application code lets both through under concurrency.
Apply the intended case and whitespace rule to uniqueness
TypeNegativePriorityHigh- Test data
- The same email differing only in case, and one with trailing whitespace
- Expected result
- Treated as duplicates if that is the intent, enforced by the constraint definition rather than by a normalisation step the application might skip.
Prevent orphaned rows through foreign keys
TypeNegativePriorityHigh- Test data
- Insert a child row referencing a missing parent, then delete a parent with children present
- Expected result
- Both refused or handled by a declared cascade rule. Referential integrity maintained only by application code degrades with every new code path.
Verify the delete behaviour on every relationship
TypeStatePriorityHigh- Test data
- Delete a parent under each configured rule: cascade, restrict and set null
- Expected result
- Each behaves as documented, and no cascade deletes further than intended, which is how an unrelated audit history disappears with one record.
Reject data that violates a business constraint
TypeNegativePriorityHigh- Test data
- A negative quantity, an end date before a start date, and a status value outside the permitted set
- Expected result
- Refused by a database constraint as well as by validation, so a direct write, a migration or an admin tool cannot introduce invalid rows.
Roll back completely when a transaction fails
TypeStatePriorityHigh- Test data
- A multi table write forced to fail on the last statement
- Expected result
- No partial state remains. A half applied change is worse than a clean failure because nothing reports it and the data looks plausible.
Keep a write and its side effects consistent
TypeStatePriorityHigh- Test data
- A commit followed by a failing message publish or cache invalidation
- Expected result
- Either both happen or the inconsistency is detected and repaired, rather than a committed row that no downstream consumer ever hears about.
Prevent lost updates on concurrent writes
TypeBoundaryPriorityHigh- Test data
- Two users editing different fields of the same record and saving simultaneously
- Expected result
- Both changes survive, or the later write is refused with a conflict. A read modify write cycle silently discards the first change.
Increment a counter correctly under concurrency
TypeBoundaryPriorityHigh- Test data
- One hundred concurrent increments of the same counter
- Expected result
- Final value is exactly one hundred higher. A value read into the application and written back loses increments in proportion to concurrency.
Prevent a balance or stock level going negative
TypeBoundaryPriorityHigh- Test data
- Concurrent decrements that individually fit within the available amount but together exceed it
- Expected result
- One succeeds and one is refused, enforced by a conditional update or a constraint rather than by an application check.
Handle a deadlock without losing the request
TypeStatePriorityHigh- Test data
- Two transactions acquiring the same rows in opposite order
- Expected result
- One is chosen as the victim, the failure is retried safely, and the retry does not apply the same change twice.
Behave correctly under the configured isolation level
TypeBoundaryPriorityHigh- Test data
- A read repeated inside one transaction while another commits a change to those rows
- Expected result
- Behaviour matches the documented isolation level, and any logic that assumes a stronger guarantee than is configured is identified.
Store numeric values in an appropriate type
TypeNegativePriorityHigh- Test data
- A monetary total summed across many rows, and a value at the maximum for its column type
- Expected result
- Money is stored as an exact decimal or integer minor units rather than a floating point type, and an overflow is refused rather than silently wrapping.
Store timestamps with an unambiguous timezone
TypeBoundaryPriorityHigh- Test data
- A record written from two server timezones, and one at a daylight saving transition
- Expected result
- Timestamps are stored with an offset or in a single documented timezone, and a calendar date is stored as a date rather than converted through an instant.
Preserve character encoding and collation
TypeNegativePriorityHigh- Test data
- Accented characters, emoji, right to left text and a value at the maximum column length
- Expected result
- Stored and returned byte identical with no truncation or substitution, and sorting follows the intended collation rather than a byte order.
Handle null distinctly from empty and zero
TypeBoundaryPriorityHigh- Test data
- A null, an empty string and a zero in the same column, then filter, sort and aggregate over them
- Expected result
- Each is distinguishable, aggregates treat null as documented, and a filter for not equal to a value does not silently exclude null rows.
Run a migration forwards without data loss
TypeStatePriorityHigh- Test data
- A migration adding a column, narrowing a type and renaming a field, against production scale data
- Expected result
- Data is preserved and transformed correctly, and rows that cannot be transformed are reported rather than dropped or silently defaulted.
Roll a migration back safely
TypeStatePriorityHigh- Test data
- Apply a migration, write new data, then roll back
- Expected result
- Rollback is possible or is documented as irreversible before deployment, and the consequences for data written in the meantime are stated.
Keep a migration safe against a running application
TypeBoundaryPriorityHigh- Test data
- A migration executed while the previous application version is still serving traffic
- Expected result
- Old and new code both work against the intermediate schema, and the migration does not hold a lock long enough to cause an outage.
Make a data backfill safely rerunnable
TypeStatePriorityHigh- Test data
- Interrupt a backfill partway, then run it again
- Expected result
- Rerunning completes the remainder without reprocessing or double applying rows already handled, and progress is recorded durably.
Enforce soft delete consistently
TypeSecurityPriorityHigh- Test data
- A soft deleted record requested through search, a report, an export and a direct identifier lookup
- Expected result
- Excluded from all four and from any uniqueness check that should ignore it, since a filter applied in one query and forgotten in another resurrects the record.
Scope every query by tenant
TypeSecurityPriorityHigh- Test data
- Requests for records belonging to another tenant through the interface, a report and an export
- Expected result
- Refused everywhere, enforced by a mechanism that cannot be forgotten in a new query rather than by remembering to add a condition each time.
Restore from backup within the stated objectives
TypeStatePriorityHigh- Test data
- A restore into a clean environment, timed and verified
- Expected result
- Restore completes within the recovery time objective with data loss inside the recovery point objective, verified by an actual restore rather than by the backup job reporting success.
Recover a single record or table without a full restore
TypeStatePriorityMedium- Test data
- An accidental delete or update of one table
- Expected result
- A documented path exists to recover that data alone, since a full restore to fix one table means discarding every change since the backup.
Read consistently from a replica
TypeBoundaryPriorityHigh- Test data
- A write followed immediately by a read routed to a replica under replication lag
- Expected result
- The user sees their own write, through read after write consistency or by routing that read to the primary rather than showing stale data.
Verify indexes support the real query patterns
TypePerformancePriorityHigh- Test data
- Execution plans for the most frequent and slowest queries against production volume data
- Expected result
- No unexpected full scan on a large table, and no unused index adding write cost, evaluated at real volume rather than on a seeded sample.
Mask or exclude personal data in non production copies
TypeSecurityPriorityHigh- Test data
- A refreshed test database taken from production
- Expected result
- Personal data is masked or synthetic while preserving referential integrity and realistic distribution, and no unmasked copy remains reachable.
Reconcile aggregates against the underlying rows
TypeStatePriorityHigh- Test data
- A stored total, a cached count and a reporting figure compared against a direct calculation
- Expected result
- All agree exactly. A denormalised total maintained by application code drifts, and nothing detects it until somebody adds the rows up by hand.
What goes in each field
ID
RequiredStable identifier, prefixed by module.
Test case
RequiredWhat is being verified, in one line.
Type
Functional, negative, boundary, security, state, performance, accessibility or compatibility. Use it to check coverage is spread rather than clustered on the happy path.
Priority
Risk based, weighted by whether the damage is silent and permanent. Anything that allows duplicate or orphaned rows, loses a committed write, or corrupts a numeric total is High.
Test data
The specific values, including the invalid and boundary ones.
Expected result
RequiredThe precise observable outcome, including message text where the wording itself is the requirement.
Insert the same row twice at once
Data defects are the quietest failures in software: nothing errors, the rows look plausible, and the damage is permanent. These four conditions expose them.
Fire two identical inserts simultaneously
A check followed by an insert in application code lets both through. Only a constraint at the database refuses the second, and the difference only shows under concurrency.
Increment one counter a hundred times at once
The final value should be exactly a hundred higher. A value read into the application and written back loses increments in direct proportion to concurrency.
Fail the last statement in a transaction
Then look for partial state. A half applied change is worse than a clean failure, because nothing reports it and the resulting data is entirely believable.
Add the rows up by hand
Compare a stored total, a cached count and a reporting figure against a direct calculation. Denormalised totals maintained in code drift, and nothing notices.
Why data defects are permanent
The single idea running through this set is that a rule enforced only in application code is not enforced. Uniqueness checked by selecting before inserting will admit duplicates the moment two requests arrive together. Referential integrity maintained by remembering to delete children first will produce orphans as soon as a new code path forgets. A status column constrained only by validation will accept anything a migration, an admin tool or a direct write chooses to put there. Each of these is testable in one case, and each produces damage that is silent at the time and permanent afterwards, because there is no error to alert anyone and the resulting rows look entirely reasonable.
Concurrency is where the gap between intent and enforcement becomes visible. A read modify write cycle loses updates, drops counter increments and permits balances to go negative, and none of it appears in sequential testing because sequential testing never creates the overlap. The correct forms are a conditional update, an atomic increment or a constraint, and the test is to fire the operations simultaneously and then check the arithmetic rather than checking that no error was returned. Deadlocks belong in the same group: they will happen, so the requirement is that the losing transaction is retried safely and that the retry does not apply the same change twice.
Migrations are the highest risk routine activity in most systems. They need testing forwards against production scale data, they need a rollback path or an explicit acknowledgement that there is none, and they need to be safe while the previous application version is still serving traffic, which means old and new code must both work against the intermediate schema. Backfills need to be rerunnable, because they get interrupted, and a backfill that reprocesses rows on the second run is as damaging as one that skips them.
Finally, two operational cases that get assumed rather than verified. Soft delete is a filter, and a filter applied in the main query and forgotten in a report, an export or a uniqueness check brings the record back, which is a data exposure rather than a bug. And a backup is not a backup until it has been restored: a backup job reporting success proves that a file was written, not that the data in it can be recovered inside the recovery time objective. Timing an actual restore into a clean environment is the only version of that test which means anything.
Suggest an improvementTesting a data platform or migration?
QAble tests data integrity end to end, including constraint enforcement under concurrency, migration safety at production volume, ETL validation and verified restores.
Data validation and ETL testing servicesMore test case sets
View allTest cases for a login page
Test cases25 cases across functional, negative, boundary, security, session and accessibility paths, including account enumeration and lockout.Test cases for a registration form
Test cases28 cases covering validation, duplicate accounts, email verification, password rules and the enumeration leak most signup forms ship with.Test cases for search functionality
Test cases28 cases across relevance, partial and fuzzy matching, filters, pagination, empty states, injection attempts and performance under load.Test cases for a shopping cart
Test cases27 cases on quantity limits, price recalculation, stock changes, coupon stacking, guest to account merge and cart persistence.Test cases for checkout and payment
Test cases30 cases including 3D Secure, declines, timeouts, duplicate charges, idempotency, refunds and partial captures.Test cases for file upload
Test cases28 cases on size and type limits, spoofed content types, malicious filenames, progress, resume, virus scanning and storage limits.Test cases for forgot password
Test cases26 cases on reset token expiry, single use enforcement, session invalidation and the enumeration and rate limit gaps that are routine here.Test cases for OTP verification
Test cases26 cases on expiry, resend throttling, attempt limits, code reuse, delivery failure and the brute force window teams forget to close.Test cases for user roles and permissions
Test cases26 cases on horizontal and vertical privilege checks, direct object access, role changes mid-session and permission inheritance.Test cases for form validation
Test cases27 rules-based cases on required fields, length and numeric boundaries, client and server parity, hidden field tampering and error accessibility.Test cases for a date picker
Test cases26 cases on timezone shifts, ambiguous day and month order, impossible dates, min and max limits, leap years and keyboard operation.Test cases for pagination
Test cases24 cases on ordering stability, records changing mid-session, page size caps, deep offset cost, permission-filtered totals and state restore.Test cases for push notifications
Test cases26 cases on app states, deep link routing, token release on sign out, lock screen privacy, preferences, provider failures and platform differences.Test cases for reports and data export
Test cases25 cases on permission filtering in the file, spreadsheet formula injection, encoding, typed numbers and dates, row limits and audit logging.Test cases for a chatbot
Test cases28 cases on paraphrased intents, context, fallback loops, human handoff, policy grounding, prompt injection and data scoping.Test cases for net banking transactions
Test cases28 cases on duplicate debits from a retried request, concurrent transfers against one balance, daily limits across channels, beneficiary cooling periods, second factor binding and reconciliation.Test cases for wallet and UPI payments
Test cases28 cases on payments that time out with no response, idempotency on retry, racing balances, caps across devices, collect request fraud, mandates and refunds.Test cases for insurance claim submission
Test cases28 cases on coverage at the date of loss, waiting periods, deductibles and sub limits, exclusions and riders, duplicate claims and settlement reconciliation.Test cases for patient records in an EHR
Test cases28 cases on duplicate detection and merge, wrong patient entry, units of measure, allergy and interaction alerting, break glass access and audit of reads.Test cases for CRM lead management
Test cases28 cases on duplicate leads under concurrency, routing and the unrouted fallback, round robin races, territory visibility, conversion and bulk import.Test cases for an ERP purchase order
Test cases28 cases on approval thresholds, amendments that must reset approval, budget commitment races, over receipt tolerance, three-way match and duplicate invoices.Test cases for OTT video playback
Test cases28 cases on bitrate recovery after a dip, DRM renewal mid stream, concurrent stream limits and leaked slots, resume conflicts, ad cue points and offline expiry.Test cases for game level progression
Test cases28 cases on save corruption during a crash write, cloud save conflicts, offline queue replay, unlock gating, currency exploits and purchase restore.Test cases for a REST API
Test cases28 cases on status code correctness, cross tenant resource access, mass assignment, idempotent retries, cursor pagination, rate limits and contract drift.Test cases for SSO and social login
Test cases28 cases on linking an account on an unverified email, state and code replay, redirect allow lists, token signature and issuer, deprovisioning and session rotation.Test cases for subscription and billing
Test cases28 cases on mid cycle proration, duplicate and out of order webhooks, renewal double charges, dunning and grace, trials, coupons, metered usage and tax.Test cases for data tables, filters and sorting
Test cases28 cases on unstable sorts across pages, filters that must reset pagination, selection surviving a filter change, bulk action scope and export fidelity.Test cases for session timeout and concurrent login
Test cases28 cases on tokens that survive sign out, refresh token reuse, idle against absolute lifetime, multi tab expiry, session limits and remote revocation.Test cases for a multi step form wizard
Test cases28 cases on values lost to back navigation, refresh and session expiry, step skipping, server side revalidation, duplicate submission and conditional branches.Test cases for email verification
Test cases28 cases on token reuse and expiry, invalidating earlier links, account enumeration, header injection, safe address change and mail scanner prefetching.Test cases for dashboards and analytics widgets
Test cases28 cases on reconciling against source rows, widgets that disagree, timezone aggregation, zero baselines, no data shown as zero and permission leaks in aggregates.Test cases for booking and reservation
Test cases28 cases on concurrent bookings for the last slot, inventory holds that leak, payment without a booking, cancellation boundaries and channel sync.Test cases for mobile app install and update
Test cases28 cases on migration chains across skipped versions, crashes during post upgrade migration, forced update lockouts, deep links and clean reinstall.Test cases for accessibility (WCAG 2.2 AA)
Test cases28 cases on keyboard only completion, focus management, live region announcements, contrast, reflow at 320 pixels, target size and screen reader verification.Test cases for performance and load
Test cases28 cases on spikes with no ramp, recovery after peak, soak and leak detection, pool exhaustion, cold caches, retry storms and data correctness under load.Test cases for the OWASP Top 10
Test cases28 cases on broken access control, mass assignment, injection across every input surface, credential stuffing, session invalidation, SSRF and exposed secrets.Test cases for cross browser compatibility
Test cases28 cases on storage that throws in private mode, blocked third party cookies, engine date parsing, mobile viewport units, in app browsers and ad blockers.Test cases for localisation and multi language support
Test cases28 cases on text expansion, concatenated sentences, plural rules, locale date parsing, decimal separators, right to left layout, collation and encoding.Want your data integrity proven, not assumed?
QAble covers constraints, concurrency and migration paths with ISTQB-certified engineers. Start with a free QA audit of your data layer.