QA Workflow Best Practices
Set up a QA workflow that catches bugs before production. Includes testing strategies, approval gates, and automation.
QA Workflow Best Practices
Why QA Matters
A single production bug can:
- Cost your company money (customer refunds, emergency fixes)
- Damage reputation (customers lose trust)
- Sink features (users won't adopt if it's broken)
- Distract engineering (firefighting instead of building)
QA's job: Catch bugs in development, not in production.
Recommended Workflow Architecture
5-Stage QA Workflow
Backlog → Development → QA Review → Staging → Production
Stage 1: Backlog
- Clear requirements and acceptance criteria
- "Definition of Done" includes testing
- QA involved in requirements discussion
Stage 2: Development
- Developer writes feature + unit tests
- Code runs through automated checks (linting, type checking, build)
- Pull request reviewed by peer + automated tests
- PR doesn't merge until all automated checks pass
Stage 3: QA Review (Manual + Exploratory)
- QA environment deployed with latest dev code
- QA tester manually tests per acceptance criteria
- QA performs exploratory testing (edge cases, user flows)
- Testing checklist:
- ✓ Feature works as specified
- ✓ No regression in existing features
- ✓ Error messages are clear
- ✓ Mobile-friendly (if applicable)
- ✓ Accessibility (keyboard nav, screen reader)
- ✓ Performance (< 2s load, 60fps interactions)
Stage 4: Staging (Pre-Production)
- Staging environment = production setup (same infrastructure, data, scale)
- Final smoke tests in production-like environment
- PMs/stakeholders do acceptance sign-off
- Staging checklist:
- ✓ Feature works in production-like environment
- ✓ No performance degradation
- ✓ Integrations working (payments, APIs, etc.)
Stage 5: Production
- Gradual rollout (1% users → 10% → 100%) for high-risk features
- Monitoring for errors and performance issues
- Kill switch ready (feature flag to disable immediately)
Building Your QA Environment
Use Feature Flags (Feature Toggles)
// Development: Feature on for internal team
if featureFlags['new_booking_system'] and user.isInternal:
showNewBookingUI()
// QA: On for QA team
if featureFlags['new_booking_system'] and (user.isQA or user.isInternal):
showNewBookingUI()
// Staged Release: On for 10% of users
if featureFlags['new_booking_system'] and random() < 0.1:
showNewBookingUI()
// Full Release: On for everyone
if featureFlags['new_booking_system']:
showNewBookingUI()
Benefits:
- Deploy without shipping — code live but feature hidden
- Instant rollback — flip flag, feature gone
- Canary releases — roll out to small % first
- A/B testing — compare old vs new
Automated Testing Strategy
Test Pyramid
▲
/ \
/ \ E2E Tests (few)
/ \ "Book a room, confirm email"
/________\
\ /
\ / Integration Tests (more)
\ / "Database + API + UI work together"
\ /
\/_______________
Unit Tests (many)
"Calculation logic correct"
Ratios:
- Unit Tests: 70% — Fast, focused, find bugs quickly
- Integration Tests: 20% — Catch real-world issues
- E2E Tests: 10% — Catch user flows; expensive, slow
What to Automate
✅ DO automate:
- API functionality (unit + integration tests)
- Critical user flows (E2E: login → purchase → confirmation)
- Calculations and business logic
- Regressions (bugs that keep coming back)
❌ DON'T automate:
- Design/visual ("Does button look good?") — humans better
- One-off tests for old features
- Tests you'll never run again
QA Approval Gates
Definition of Ready
Before a card enters development, it must have:
- Clear requirements written
- Acceptance criteria defined
- User stories have "as a [user], I want [feature], so [benefit]"
- QA has reviewed requirements and asked questions
- Designs reviewed and approved
- Dependencies identified
Definition of Done
Before a card exits development (enters QA), it must have:
- Code written and self-reviewed
- Unit tests written (>80% coverage)
- All automated tests passing
- Code reviewed by at least 1 peer
- No linting errors
- Accessible (passes WCAG checks)
- Documented (comments where complex)
Definition of Accepted (Post-QA)
Before a card ships, it must have:
- Manual QA passed on QA environment
- Exploratory testing done (edge cases, error flows)
- No regressions in existing features
- Performance acceptable (load time, memory)
- Staging tests passed (if risk is high)
- Product owner sign-off
QA Metrics to Track
| Metric | What It Means | Target |
|---|---|---|
| Bugs Found in QA | Quality of development | High (catch before prod) |
| Bugs Found in Production | QA effectiveness | Low (< 5% of total bugs) |
| Time in QA | QA cycle time | 1-2 days |
| Test Coverage | % of code tested | > 80% |
| Mean Time to Fix | How fast bugs get fixed | < 1 hour for critical |
Common QA Failures
❌ QA as a gatekeeper — Creates adversarial relationship with development
❌ No automated tests — QA does the same tests manually every sprint (burnout)
❌ QA involved only at the end — Requirements misunderstood, lots of rework
❌ Shipping without QA sign-off — Production bugs happen, trust breaks
❌ No regression testing — Every bug that's fixed once gets fixed again
Tools & Setup
Local Development
- Docker for consistent environment
- Database seeding (realistic test data)
- API mocking for external services
Testing
- Unit: Jest, Vitest, Pytest
- Integration: Cypress, Playwright, Selenium
- Performance: Lighthouse, WebPageTest
CI/CD
- GitHub Actions, GitLab CI, Jenkins
- Run all tests on every PR
- Block merging if tests fail
Monitoring
- Sentry (error tracking)
- DataDog (performance monitoring)
- Google Analytics (user behavior)
Getting Started This Week
- Document your "Definition of Done" — share with team
- Add one automated test — pick critical user flow
- Set up CI/CD — make tests run automatically
- Schedule QA review — establish process with your QA person
- Start tracking — bugs found in QA vs. production
The goal: Ship with confidence.
