Quality Assurance vs. Quality Control
Quality management in IT projects has two complementary approaches: Quality Assurance (QA) focuses on the process (preventing defects), while Quality Control (QC) focuses on the product (finding defects).
| Aspect | Quality Assurance (QA) | Quality Control (QC) |
|---|---|---|
| Focus | Process-oriented | Product-oriented |
| Goal | Prevent defects | Detect defects |
| When | Throughout the project | During and after development |
| Activities | Code reviews, standards, CI/CD, DoD | Testing, inspections, bug triage |
| Example | Enforce linting rules in CI | Manual exploratory testing |
The Testing Pyramid
Test Types (Bottom to Top)
- Unit Tests (70%): Test individual functions/components in isolation. Fast, cheap, many. Target: >80% code coverage.
- Integration Tests (20%): Test interactions between modules, APIs, and services. Medium speed and cost.
- End-to-End Tests (5%): Test complete user workflows through the entire system. Slow, expensive, few. Focus on critical paths.
- Manual/Exploratory Tests (5%): Human testers explore edge cases, UX issues, and scenarios automation misses. Cannot be fully automated.
Definition of Done Checklist
// Definition of Done Configuration
interface DefinitionOfDone {
level: 'story' | 'sprint' | 'release';
criteria: DoDCriterion[];
}
interface DoDCriterion {
category: string;
requirement: string;
automated: boolean; // Can be verified automatically?
gate: 'blocking' | 'recommended';
}
const storyDoD: DefinitionOfDone = {
level: 'story',
criteria: [
// Code Quality
{ category: 'Code', requirement: 'Code follows team style guide (enforced by linter)', automated: true, gate: 'blocking' },
{ category: 'Code', requirement: 'No TypeScript errors or warnings', automated: true, gate: 'blocking' },
{ category: 'Code', requirement: 'No console.log statements in production code', automated: true, gate: 'blocking' },
{ category: 'Code', requirement: 'Code reviewed and approved by >= 1 peer', automated: true, gate: 'blocking' },
// Testing
{ category: 'Testing', requirement: 'Unit tests written for new code (>= 80% coverage)', automated: true, gate: 'blocking' },
{ category: 'Testing', requirement: 'Integration tests for API endpoints', automated: true, gate: 'blocking' },
{ category: 'Testing', requirement: 'E2E test for user-facing critical paths', automated: true, gate: 'recommended' },
{ category: 'Testing', requirement: 'All tests pass in CI', automated: true, gate: 'blocking' },
// Functionality
{ category: 'Functionality', requirement: 'All acceptance criteria met', automated: false, gate: 'blocking' },
{ category: 'Functionality', requirement: 'Feature works in all supported browsers', automated: false, gate: 'blocking' },
{ category: 'Functionality', requirement: 'Responsive on mobile, tablet, desktop', automated: false, gate: 'blocking' },
// Non-Functional
{ category: 'Performance', requirement: 'No performance regressions (Lighthouse >= 90)', automated: true, gate: 'recommended' },
{ category: 'Accessibility', requirement: 'WCAG 2.1 AA compliance', automated: true, gate: 'blocking' },
{ category: 'Security', requirement: 'No new security vulnerabilities (OWASP top 10)', automated: true, gate: 'blocking' },
// Documentation
{ category: 'Docs', requirement: 'API documentation updated (if API changed)', automated: false, gate: 'recommended' },
{ category: 'Docs', requirement: 'Feature flag documented (if applicable)', automated: false, gate: 'recommended' },
// Deployment
{ category: 'Deployment', requirement: 'Feature deployed to staging and verified', automated: false, gate: 'blocking' },
{ category: 'Deployment', requirement: 'Monitoring/alerts configured for new services', automated: false, gate: 'recommended' },
]
};
// Quality Gate in CI/CD Pipeline
interface QualityGate {
name: string;
stage: 'build' | 'test' | 'analysis' | 'deploy';
checks: {
name: string;
tool: string;
threshold: string;
blocking: boolean;
}[];
}
const ciQualityGates: QualityGate[] = [
{
name: 'Build Gate',
stage: 'build',
checks: [
{ name: 'TypeScript compilation', tool: 'tsc', threshold: '0 errors', blocking: true },
{ name: 'Lint check', tool: 'ESLint', threshold: '0 errors', blocking: true },
{ name: 'Format check', tool: 'Prettier', threshold: 'All files formatted', blocking: true },
]
},
{
name: 'Test Gate',
stage: 'test',
checks: [
{ name: 'Unit tests', tool: 'Jest', threshold: '100% pass rate', blocking: true },
{ name: 'Code coverage', tool: 'Istanbul', threshold: '>= 80% on new code', blocking: true },
{ name: 'Integration tests', tool: 'Jest + Testcontainers', threshold: '100% pass rate', blocking: true },
{ name: 'E2E tests', tool: 'Playwright', threshold: '100% pass rate on critical paths', blocking: true },
]
},
{
name: 'Analysis Gate',
stage: 'analysis',
checks: [
{ name: 'Security scan', tool: 'Snyk / Trivy', threshold: '0 high/critical vulnerabilities', blocking: true },
{ name: 'Code quality', tool: 'SonarQube', threshold: 'A rating', blocking: false },
{ name: 'Bundle size', tool: 'size-limit', threshold: '< 200KB increase', blocking: false },
{ name: 'Lighthouse', tool: 'Lighthouse CI', threshold: '>= 90 performance', blocking: false },
]
}
];
Cost of Quality
Finding Bugs Early Is Cheaper
- Requirements Phase: $1 to fix (catching the wrong requirement)
- Design Phase: $5 to fix (wrong architecture decision)
- Development Phase: $10 to fix (code review catches the bug)
- Testing Phase: $50 to fix (QA finds the bug)
- Production: $100-$1000 to fix (customer impact, incident response, hotfix, rollback)
Investing in quality assurance (prevention) is always cheaper than relying on quality control (detection). Code reviews, linting, and automated tests are not overhead — they are cost savings.
Code Review as a Quality Gate
- Require Reviews: No code merges without at least one approval. Configure this as a branch protection rule.
- Review Checklist: Does it meet acceptance criteria? Are there tests? Are edge cases handled? Is it readable?
- Time-Box Reviews: Reviews should happen within 24 hours. Stale PRs create merge conflicts and block the team.
- Review for Learning: Reviews are not just bug-finding — they spread knowledge and raise the whole team's skills.