Role: QA Manual Tester — API testing (portfolio project)
App under test: Fake Store API — a public sandbox REST API (products, categories, carts, users, auth), no real data or payments
I designed and executed a Postman collection covering the main resources of a REST API: auth, products, categories, carts and users. Every request asserts status code and response schema/business rules with pm.test, and every finding was confirmed live with curl before being written up — no bug got documented from a hunch.
Test Plan & Scope
In scope: Auth (login with valid/invalid credentials, token capture), Products (list, get by id valid/invalid, pagination, sorting, create), Categories (list, filter by valid/invalid category), Carts (list, get by id, add, delete) and Users (list, get by id).
Out of scope: persistence of writes (this sandbox echoes a plausible response but doesn't actually change server state — confirmed manually before writing the tests), performance/load, full CRUD on users, and the plaintext-password trait of GET /users (a known characteristic of this public sandbox, not a defect under test).
Environment: Postman + curl, public API (fakestoreapi.com), July 2026.
Test design methodology
Each request was built around a specific black-box technique instead of poking at the API at random:
Equivalence Partitioning: valid vs. invalid login credentials, valid vs. invalid category — one representative request per class instead of redundant variants.
Boundary Value Analysis: product id at the edge of the valid range (1–20, e.g. id 1) vs. clearly outside it (id 99999) — this is exactly what surfaced BUG008.
Parameter Interaction Testing: sort and limit tested individually first, then combined on the same request — the combination is what broke and revealed BUG009, something neither parameter's isolated test would have caught.
Requests (16)
| Folder | Request | Method & endpoint | Result |
|---|---|---|---|
| Auth | Login — valid credentials | POST /auth/login |
Pass |
| Auth | Login — invalid credentials | POST /auth/login |
Pass |
| Products | Get all products | GET /products |
Pass |
| Products | Get single product — valid id | GET /products/1 |
Pass |
| Products | Get single product — non-existent id | GET /products/99999 |
BUG008 |
| Products | Get products with limit | GET /products?limit=3 |
Pass |
| Products | Get products sorted+limited | GET /products?sort=desc&limit=5 |
BUG009 |
| Products | Create product (mock, non-persistent) | POST /products |
Pass |
| Categories | Get all categories | GET /products/categories |
Pass |
| Categories | Get products by category — valid | GET /products/category/electronics |
Pass |
| Categories | Get products by category — invalid | GET /products/category/not-a-real-category |
Pass |
| Carts | Get all carts | GET /carts |
Pass |
| Carts | Get single cart — valid id | GET /carts/1 |
Pass |
| Carts | Add product to cart | POST /carts |
Pass |
| Carts | Delete cart | DELETE /carts/1 |
Pass |
| Users | Get all users | GET /users |
Pass |
| Users | Get single user — valid id | GET /users/1 |
Pass |
↳ Import the collection yourself: FakeStoreAPI.postman_collection.json + environment on GitHub.
Bugs found (2)
Both confirmed live with curl before being written up as Postman requests with automated assertions — not guesses.
- Send
GET /products/99999(an id outside the valid range of 1–20)
- Send
GET /products?sort=descalone → confirm it correctly returns ids in descending order (20, 19, 18, ...) - Send
GET /products?sort=desc&limit=5→ compare
limit is applied before sort, so the "top 5 descending" the caller asked for never happens↳ Full detail (curl evidence, request/response bodies) in the GitHub repository.