How to Write Test Cases for Filters And Sorting (With Examples)
How to Write Test Cases for Filters And Sorting (With Examples)
How to Write Test Cases for Filters And Sorting (With Examples)
Understanding Filters and Sorting in Applications
Filters and sorting are two of the most common interaction patterns in modern software. Users rely on them to narrow large data sets, locate specific records, and impose a meaningful order on results. Because these features touch data retrieval, UI state, and often backend services, defects in filtering or sorting can cascade into missed business opportunities, compliance issues, or poor user experience.
A filter typically presents a set of criteria—checkboxes, dropdowns, date pickers, free‑text search—that the user can enable or disable. When a criterion changes, the application must recompute the visible subset and reflect the change instantly (or after a short debounce). Sorting, on the other hand, lets the user choose one or more columns and a direction (ascending/descending) to reorder the same subset.
From a testing perspective, the challenge is twofold:
- Functional correctness – Does the output match the logical expression of the selected filters and the sort order?
- Performance and stability – Does the operation remain responsive under realistic data volumes, and does it handle malformed input without crashing or hanging?
The following sections break down how to translate these concerns into concrete, high‑signal test cases that can be executed manually, automated with scripts, or reinforced by autonomous exploration tools.
Anatomy of a Test Case for Filters and Sorting
A well‑structured test case contains six essential elements that make it reproducible, traceable, and easy to maintain.
| Element | Description | Example for a filter test |
|---|---|---|
| ID | Unique identifier (e.g., FT-001) | FT-001 |
| Title | Short, readable summary | “Verify that selecting ‘Active’ status shows only active users” |
| Preconditions | State that must exist before execution | “User is logged in; the user list page displays 150 records with mixed statuses” |
| Steps | Ordered actions the tester performs | 1. Click the Status filter dropdown. 2. Check the ‘Active’ checkbox. 3. Click Apply. |
| Expected Result | Observable outcome that determines pass/fail | “Only users whose status = Active are displayed; count matches backend query.” |
| Postconditions (optional) | System state after test, useful for chaining | “Filter panel shows ‘Active’ selected; no error messages.” |
When writing test cases, keep each step atomic and avoid bundling multiple assertions into a single step. This makes failure diagnosis straightforward and enables parallel execution in automated suites.
Positive Test Cases
Positive tests validate that the feature works as intended under normal conditions. They form the baseline confidence that the implementation satisfies the functional requirement.
#### FT‑001 – Single‑Value Filter
- Preconditions: Product catalog page loads 200 items with categories Electronics, Clothing, Home.
- Steps:
- Open the Category filter.
- Select “Electronics”.
- Press Apply.
- Expected Result: Only items whose category = Electronics are visible; the item count equals the number of Electronics items in the database.
#### FT‑002 – Multi‑Value Filter (AND Logic)
- Preconditions: Same as FT‑001.
- Steps:
- Select Category → Electronics.
- Select Price Range → $100‑$500.
- Apply.
- Expected Result: Items that satisfy both conditions are shown; no item outside the price range or outside Electronics appears.
#### FT‑003 – Multi‑Value Filter (OR Logic)
- Preconditions: Ticket list with Status (Open, In Progress, Closed) and Priority (Low, Medium, High).
- Steps:
- Enable “Show tickets with Priority = High OR Status = Closed”.
- Apply.
- Expected Result: The list contains every ticket that is either High priority or Closed, duplicates removed.
#### FT‑004 – Text Search Filter
- Preconditions: Customer directory with 500 records, names containing “Smith”, “Smyth”, “Smythe”.
- Steps:
- Enter “Sm” in the search box.
- Press Enter.
- Expected Result: All records whose name starts with “Sm” appear; fuzzy matching is not applied unless specified.
#### FT‑005 – Date Range Filter
- Preconditions: Order history page shows orders from Jan 1 2023 to Dec 31 2023.
- Steps:
- Set From date to 2023‑06‑01.
- Set To date to 2023‑08‑31.
- Apply.
- Expected Result: Only orders placed between June 1 and August 31, 2023 inclusive are displayed.
#### ST‑001 – Single‑Column Sort Ascending
- Preconditions: Product list unsorted, displaying Price column.
- Steps:
- Click the Price column header once.
- Expected Result: Items are ordered from lowest to highest price; visual indicator shows ascending arrow.
#### ST‑002 – Single‑Column Sort Descending
- Preconditions: Same as ST‑001.
- Steps:
- Click the Price column header twice (or click after ascending).
- Expected Result: Items ordered from highest to lowest price; descending arrow shown.
#### ST‑003 – Multi‑Column Sort (Primary + Secondary)
- Preconditions: Employee table with columns Department, Last Name, Salary.
- Steps:
- Shift‑click Department header (ascending).
- Click Last Name header (ascending).
- Expected Result: Rows grouped by Department A‑Z; within each department, sorted by Last Name A‑Z.
#### ST‑004 – Sort with Null Values
- Preconditions: Invoice list where some records have a null DueDate.
- Steps:
- Sort DueDate ascending.
- Expected Result: All null DueDate rows appear either at the top or bottom consistently (as defined by product spec); no exception is thrown.
#### ST‑005 – Sort Stability
- Preconditions: List of tasks with identical Priority values but different CreationTime.
- Steps:
- Sort by Priority ascending.
- Expected Result: Relative order of tasks with equal Priority remains unchanged (stable sort).
Negative Test Cases
Negative tests verify that the system behaves correctly when presented with invalid, unexpected, or malicious input. They guard against crashes, security bypasses, and confusing UI states.
#### FT‑N01 – Empty Filter Selection
- Preconditions: Filter panel with multiple checkboxes, none selected.
- Steps:
- Click Apply without selecting any option.
- Expected Result: Either all items are shown (no filtering) or an informative message states “Please select at least one criterion”.
#### FT‑N02 – Conflicting Date Range
- Preconditions: Date range filter with From and To fields.
- Steps:
- Set From date to 2024‑01‑01.
- Set To date to 2023‑12‑31 (earlier than From).
- Apply.
- Expected Result: Validation error displayed; no results are shown, and the UI prevents submission until dates are corrected.
#### FT‑N03 – Special Characters in Text Search
- Preconditions: Search box that feeds directly into a SQL LIKE clause (hypothetical vulnerable implementation).
- Steps:
- Enter
' OR '1'='1. - Submit.
- Expected Result: Input is treated as literal text; no SQL injection occurs; either no matches are found or a sanitization message appears.
#### FT‑N04 – Filter Value Beyond Data Type Limits
- Preconditions: Numeric filter for Age (integer).
- Steps:
- Enter 999999 (outside realistic human age).
- Apply.
- Expected Result: System either rejects the value with a range error or returns an empty set (if such ages do not exist). No crash.
#### FT‑N05 – Rapid Toggle (Debounce Failure)
- Preconditions: Filter with live‑update (no Apply button).
- Steps:
- Rapidly check and uncheck a checkbox 10 times within 200 ms.
- Expected Result: UI does not flicker excessively; final state reflects the last toggle; no JavaScript errors in console.
#### ST‑N01 – Sorting on Non‑Comparable Column
- Preconditions: Column contains mixed data types (e.g., numbers and strings).
- Steps:
- Click the column header to sort ascending.
- Expected Result: Either the column is not sortable (disabled header) or the system falls back to a deterministic rule (e.g., string conversion) without throwing an exception.
#### ST‑N02 – Sort with Extremely Large Dataset
- Preconditions: Table loads 1 million rows via virtual scrolling.
- Steps:
- Initiate a sort on any column.
- Expected Result: Sorting completes within an acceptable time frame (e.g., < 2 seconds) and does not cause memory overflow or browser freeze.
#### ST‑N03 – Sort Direction Toggle Loop
- Preconditions: Column currently sorted ascending.
- Steps:
- Click header three times quickly (asc → desc → asc).
- Expected Result: After each click, the indicator updates correctly; final state matches the expected sort direction; no extra server calls are made unnecessarily.
Boundary and Edge Cases
Boundary tests focus on the limits of input domains, while edge cases explore uncommon combinations that often surface only in production.
#### FT‑B01 – Minimum Selection (One Item)
- Preconditions: Filter with 50 possible values.
- Steps:
- Select the first item only.
- Apply.
- Expected Result: Result set matches the exact subset for that single value.
#### FT‑B02 – Maximum Selection (All Items)
- Preconditions: Same as FT‑B01.
- Steps:
- Select all 50 items.
- Apply.
- Expected Result: Either all items are shown (no effective filter) or a message indicates “Showing all”.
#### FT‑E01 – Cascading Dependent Filters
- Preconditions: Country → State → City dropdowns where State list depends on Country selection.
- Steps:
- Choose Country = Japan.
- Observe State list updates to show only Japanese prefectures.
- Select State = Tokyo.
- Observe City list updates accordingly.
- Expected Result: Each dependent filter reflects the correct scoped options; no stale options remain visible.
#### FT‑E02 – Reset After Filter
- Preconditions: Filter applied, results reduced.
- Steps:
- Click Clear/Reset button.
- Expected Result: All filter controls return to default state; full dataset is displayed again.
#### FT‑E03 – Persistent Filter Across Navigation
- Preconditions: User applies a filter, then navigates to a different page (e.g., product detail) and returns.
- Steps:
- Apply Category = Electronics.
- Click a product to open its detail page.
- Press Back to return to the list.
- Expected Result: The Electronics filter remains active and the list reflects the filtered set.
#### ST‑B01 – Sort on Empty Column
- Preconditions: Column exists but every cell is empty or null.
- **Steps: Click header to sort ascending.
- Expected Result: Order does not change (all rows equal); no error thrown.
#### ST‑E01 – Locale‑Specific Sorting
- Preconditions: List of names containing accented characters (e.g., “André”, “Áron”).
- Steps:
- Sort ascending with locale set to
fr-FR.
- Expected Result: Order follows French collation rules (e.g., “Áron” before “André”).
#### ST‑E02 – Reverse Sort After Pagination
- Preconditions: Table uses server‑side pagination (20 rows per page).
- Steps:
- Navigate to page 3.
- Apply descending sort on a column.
- Expected Result: The server receives the sort directive and returns the correctly ordered subset for page 3; the UI does not re‑sort client‑side only.
Test Data Strategies
Reliable filter and sort testing hinges on realistic, controllable data. The following approaches reduce flakiness and increase coverage.
#### Synthetic Data Generation
Use scripts or libraries (e.g., faker, Mockaroo) to create datasets with known distributions:
from faker import Faker
fake = Faker()
def generate_users(n=1000):
return [
{
"id": i,
"name": fake.name(),
"status": fake.random_element(["Active","Inactive","Suspended"]),
"age": fake.random_int(min=18, max=80),
"signup_date": fake.date_between(start_date="-5y", end_date="today")
}
for i in range(n)
]
Persist this set in a test database or load it into an in‑memory store (e.g., SQLite) before each test suite run.
#### Boundary Value Injection
For numeric filters, deliberately include min‑1, min, max, max+1 values to trigger boundary logic.
#### Null and Empty Injection
Insert NULL, empty strings, and whitespace‑only values into text and date fields to verify handling of missing data.
#### Data Seeding for Sorting
Create datasets where sorting outcomes are predictable:
- Ascending numeric: values
[1,2,3,…,100]. - Descending numeric: same list reversed.
- Stable sort test: duplicate keys with differing secondary attributes (e.g., same salary, different hire dates).
#### Data Refresh Strategy
If the application caches results, ensure each test either bypasses the cache (via query parameters or API headers) or explicitly invalidates it before verification.
Prioritization and Traceability
Not all test cases carry equal risk. Use a simple risk‑based matrix to order execution and allocate automation effort.
| Priority | Criteria | Example |
|---|---|---|
| P1 (Critical) | Failure leads to data corruption, security breach, or major workflow blockage. | FT‑N03 (SQL injection attempt) |
| P2 (High) | Causes visible incorrect output or significant performance degradation. | FT‑002 (multi‑value AND filter) |
| P3 (Medium) | Affects edge‑case usability but does not break core flows. | FT‑E01 (cascading dependent filters) |
| P4 (Low) | Cosmetic or rare scenarios; low impact if missed. | ST‑E02 (reverse sort after pagination) |
Link each test case ID to a requirement artifact (e.g., user story, specification clause) in a traceability matrix:
| Test ID | Requirement ID | Requirement Description |
|---|---|---|
| FT‑001 | REQ‑FIL‑01 | User can filter items by a single category. |
| FT‑N03 | REQ‑SEC‑02 | Input must be sanitized to prevent injection. |
| ST‑003 | REQ‑SRT‑04 | Multi‑column sort preserves grouping order. |
| ST‑N02 | REQ‑PERF‑01 | Sorting on 1M rows completes within 2 s. |
Having this traceability enables impact analysis when requirements change: simply locate affected test IDs and re‑execute or update them.
Manual vs Automated Execution
#### Manual Testing
Manual exploratory testing remains valuable for discovering UX friction, unexpected interaction patterns, and visual glitches. A tester can:
- Vary the speed of interactions (slow clicks vs rapid toggles) to catch debounce issues.
- Observe visual cues (sort icons, filter chips) for consistency across themes.
- Use accessibility tools (screen readers, contrast analyzers) to verify that filter/sort controls are perceivable and operable.
A concise manual test charter for filters/sorting might look like:
Charter: Verify filter and sort behavior on the Order History page.
- Start with default view (no filters, ascending date).
- Apply each filter singly and in combination; note result count.
- Toggle sort direction on each sortable column; confirm arrow and order.
- Attempt invalid inputs (e.g., end date before start date); confirm error messages.
- Navigate away and back; ensure filter state persists.
#### Automated Testing
Automation provides repeatability and scalability. Choose the layer that matches the risk:
- Unit tests for pure functions (e.g., a comparator or filter predicate).
- Integration/API tests that call the backend endpoint with various query strings and assert the returned payload.
- UI tests (Selenium, Playwright, Appium) that interact with the actual controls and validate the rendered DOM or native view.
Below is a Playwright snippet that verifies a multi‑value filter and a sort:
// test/filter-sort.spec.js
const { test, expect } = require('@playwright/test');
test.describe('Product listing filters and sort', () => {
test.beforeEach(async ({ page }) => {
await page.goto('https://example.com/products');
// wait for initial load
await page.waitForSelector('.product-item');
});
test('FT-002: AND filter Electronics + Price $100‑$500', async ({ page }) => {
await page.locator('#category-filter').selectOption('Electronics');
await page.locator('#price-min').fill('100');
await page.locator('#price-max').fill('500');
await page.locator('#apply-btn').click();
// ensure all shown items match criteria
const items = await page.$$eval('.product-item', els =>
els.map(el => ({
category: el.getAttribute('data-category'),
price: parseFloat(el.getAttribute('data-price'))
}))
);
expect(items.every(i => i.category === 'Electronics')).toBeTruthy();
expect(items.every(i => i.price >= 100 && i.price <= 500)).toBeTruthy();
});
test('ST-003: Multi‑column sort Department then Last Name', async ({ page }) => {
await page.locator('#dept-header').click(); // asc Dept
await page.locator('#lname-header').click(); // asc LastName
const rows = await page.$$eval('tbody tr', rows =>
rows.map(r => ({
dept: r.cells[0].innerText.trim(),
lname: r.cells[1].innerText.trim()
}))
);
// verify grouping
let prevDept = '';
for (const r of rows) {
expect(r.dept).toBeGreaterThanOrEqual(prevDept);
if (r.dept === prevDept) {
// within same dept, lname must be non‑decreasing
expect(r.lname).toBeGreaterThanOrEqual(prevLname);
}
prevDept = r.dept;
prevLname = r.lname;
}
});
});
Key points in the script:
- Atomic assertions: each test validates a single logical condition.
- Data‑driven selectors: rely on stable attributes (
data-category,data-price) rather than positional indexes. - Explicit waits: avoid flakiness by waiting for elements that indicate load completion.
#### Combining Manual and Automated with Autonomous Exploration
Autonomous QA platforms (like SUSA) can supplement scripted tests by continuously exercising the application with varied personas. For filters and sorting, an autonomous agent will:
- Generate random filter combinations (including impossible ones like selecting mutually exclusive categories).
- Vary interaction speed to stress debounce and state‑update logic.
- Simulate personas: an “impatient” user may rapidly toggle filters; an “elderly” user may use keyboard navigation exclusively; an “adversarial” user may attempt to inject scripts into search boxes.
- Detect regressions: if a new build breaks the sort stability for duplicate keys, the agent will flag a deviation from the baseline behavior captured in earlier runs.
The output from such a run includes a coverage map showing which filter/sort permutations were exercised, which crashed, and which produced unexpected UI states. Teams can then prioritize manual review or add targeted automated cases for the gaps identified.
Checklist for Filter and Sort Testing
Use this concise checklist before signing off a feature or before a release gate.
| ✅ Item | Description |
|---|---|
| Requirement Coverage | Every filter/sort requirement has at least one positive test case. |
| Negative & Security | All identified invalid inputs (empty, out‑of‑range, special chars, injection attempts) have a negative test. |
| Boundary Values | Min, max, min‑1, max+1 for numeric; earliest/latest date; first/last list item tested. |
| Edge Cases | Cascading dependencies, reset behavior, persistence across navigation, empty/null columns, locale‑specific sorting. |
| Performance | Sorting/filtering completes within SLA on realistic data volume (e.g., 100k rows). |
| Stability | No JavaScript errors, console warnings, or crash logs during rapid interaction. |
| Accessibility | All filter/sort controls are keyboard operable, have appropriate ARIA labels, and convey state changes to assistive tech. |
| State Persistence | Filter/sort selections survive page navigation, refresh, and session restore where specified. |
| Automation Readiness | Each test case can be mapped to an automated script (unit, API, or UI) with stable selectors. |
| Review & Traceability | Test IDs linked to requirements; any change in spec triggers a review of affected tests. |
Closing Takeaways
Writing effective test cases for filters and sorting is less about checking boxes and more about understanding how users manipulate data and where the system can falter. Start by decomposing the feature into its logical primitives—single‑value filters, multi‑value Boolean logic, text search, date ranges, and sortable columns—then enumerate the happy path, the error paths, and the limits of each primitive.
A well‑maintained test matrix, like the one presented above, gives you a reusable baseline that can be expanded as new filter types (e.g., tag‑based, range sliders) or sort options (custom comparators, locale‑aware collation) appear. Pair this matrix with risk‑based prioritization, traceability to requirements, and a blend of manual exploratory checks, automated scripts, and, where available, autonomous exploration to achieve continuous confidence.
When you treat filters and sorting as first‑class citizens in your test strategy, you catch the subtle bugs that only surface under realistic data loads or unusual user behavior—turning a potential production incident into a caught‑early, fixed‑before‑release win.
---
*Feel free to copy the tables, code snippets, and checklist into your test management tool or wiki. Adjust the data‑generation scripts to match your domain, and let the autonomous agent handle the combinatorial explosion while you focus on the high‑value, scenario‑specific cases.*
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