Comparing Expected vs. Actual Output: A QA Tester's Guide
A test fails, or you're doing exploratory testing, and you have two lists of values: what the system was supposed to return, and what it actually returned. Eyeballing two long result sets side by side to spot what's missing or extra doesn't scale past a handful of rows, and pasting both into a spreadsheet just to run a formula is slower than it should be for a quick check.
Quick answer
Paste your expected output as List A and the actual output as List B into a set-based list comparison tool. A Only reveals expected records that never showed up in the actual output (missing records - often the bug). B Only reveals actual values that weren't expected (unexpected extras, duplicates, or leaked test data). The intersection is everything that matched correctly.
Compare expected vs. actual now. Free, no account needed.
Open Compare Two Lists →Reading the four results
- A Only (expected, not actual): records the test expected but that never appeared in the real output. This is usually the bug you're chasing - a missing record, a filter that's too aggressive, a query that silently dropped rows.
- B Only (actual, not expected): records that showed up but weren't supposed to. Look for duplicate processing, stale cached data, or test data leaking in from a previous run.
- Intersection: what matched correctly - useful to confirm the majority of the output is right before you dig into the mismatches.
- Union: the full combined set - handy as a sanity check on total row counts between the two.
Order usually doesn't matter (but sometimes it should)
A set-based comparison ignores the order records appear in - which is normally what you want, since most APIs and queries don't guarantee a specific row order unless you explicitly requested one. If the actual output has the same records as expected just in a different sequence, this comparison correctly reports no difference.
If order is itself part of what you're testing - a sort feature, a priority queue, a paginated feed - a set comparison will hide an order bug. Use the Text Diff tool instead: it compares line by line in sequence, so a record appearing in the wrong position shows up as a difference the same way a code diff would catch a reordered line.
Comparing API responses and JSON output
For a JSON response, you have two options depending on what you're checking. If you care about specific field values regardless of formatting, pull the relevant field out into a plain list (one value per line) and compare that - ignoring whitespace and key-ordering differences that don't actually matter. If you care about the exact response format too, including whitespace and field order, paste the raw JSON text into Text Diff instead.
Case sensitivity is a judgment call, not a default
Turn Case Sensitive on when casing itself could be the bug - a status field returned as "Active" instead of
the expected "active" is a real defect in most systems, not a formatting quirk. Only turn it off if the field is
genuinely case-insensitive by design and you don't want harmless casing differences to show up as
false mismatches.
Testing across environments or builds
If you're comparing output across staging, production, and a previous release rather than just expected-vs-actual, use Multi-List Compare with one list per environment. It shows what's consistent across every environment and what differs in just one or two - useful for isolating an environment-specific regression rather than a genuine code bug.
What this doesn't replace
This is a manual, spot-check workflow for debugging a failing test, triaging a bug report, or exploratory testing by hand - not a substitute for automated assertions in your test suite. Keep repeatable checks in code where they run on every build without a copy-paste step; reach for a browser comparison when you're investigating something by hand right now.
Need to match on a key column instead?
Column Compare matches rows by ID and flags rows where a value differs.