A feature that works correctly can still fail its users. Pages that take ten seconds to load, forms that are impossible to navigate with a keyboard, and applications that expose passwords in plain text are all functional — and all unacceptable. Non-functional testing evaluates the quality attributes that determine whether software is not just correct, but usable, secure, performant, and reliable under real-world conditions.
Major Non-Functional Testing Types
Non-functional testing covers a broad spectrum of quality attributes. While a QA engineer may not specialise in all of them, understanding each type is essential for building comprehensive test plans and identifying when a specialist is needed.
# Major non-functional testing types with goals and metrics
NON_FUNCTIONAL_TYPES = [
{
"type": "Performance Testing",
"question": "How fast and stable is the system under expected and peak load?",
"sub_types": [
"Load testing — behaviour under expected user volume",
"Stress testing — behaviour beyond maximum capacity",
"Endurance testing — stability over extended time periods",
"Spike testing — response to sudden traffic surges",
],
"key_metrics": ["Response time (p50, p95, p99)", "Throughput (req/sec)", "Error rate"],
"tools": "JMeter, k6, Gatling, Locust",
},
{
"type": "Security Testing",
"question": "Is the system protected against common attacks and data breaches?",
"sub_types": [
"Vulnerability scanning — automated detection of known weaknesses",
"Penetration testing — simulated attacks by ethical hackers",
"Authentication/authorisation testing — access control verification",
"Data protection testing — encryption, masking, secure storage",
],
"key_metrics": ["OWASP Top 10 compliance", "Open vulnerabilities count", "Time to patch"],
"tools": "OWASP ZAP, Burp Suite, SonarQube, Snyk",
},
{
"type": "Usability Testing",
"question": "Can real users accomplish their goals efficiently and without frustration?",
"sub_types": [
"Task-based testing — users attempt specific workflows",
"Heuristic evaluation — experts assess against design principles",
"A/B testing — comparing two design variants for user preference",
],
"key_metrics": ["Task completion rate", "Time on task", "Error rate", "Satisfaction score"],
"tools": "UserTesting, Hotjar, manual observation sessions",
},
{
"type": "Accessibility Testing (a11y)",
"question": "Can users with disabilities use the application effectively?",
"sub_types": [
"Screen reader compatibility (NVDA, VoiceOver, JAWS)",
"Keyboard-only navigation",
"Colour contrast compliance (WCAG AA/AAA)",
"ARIA attribute validation",
],
"key_metrics": ["WCAG 2.1 conformance level", "Automated a11y violations count"],
"tools": "axe DevTools, Lighthouse, WAVE, Pa11y",
},
{
"type": "Compatibility Testing",
"question": "Does the application work across different environments?",
"sub_types": [
"Cross-browser testing (Chrome, Firefox, Safari, Edge)",
"Cross-device testing (desktop, tablet, mobile)",
"OS compatibility (Windows, macOS, Linux, iOS, Android)",
"Screen resolution and responsive design testing",
],
"key_metrics": ["Defects per browser/device", "Layout breakpoints verified"],
"tools": "BrowserStack, LambdaTest, Sauce Labs, Chrome DevTools",
},
]
for nft in NON_FUNCTIONAL_TYPES:
print(f"\n{'='*55}")
print(f" {nft['type']}")
print(f"{'='*55}")
print(f" Question: {nft['question']}")
print(f" Metrics: {', '.join(nft['key_metrics'])}")
print(f" Tools: {nft['tools']}")
print(f" Sub-types:")
for st in nft['sub_types']:
print(f" - {st}")
Common Mistakes
Mistake 1 — Assuming the development framework handles security automatically
❌ Wrong: “We use React and Django, so XSS and CSRF are handled by the framework. No security testing needed.”
✅ Correct: “Frameworks provide security defaults, but misconfiguration, custom code, and third-party dependencies can introduce vulnerabilities. Security testing verifies that the implementation is actually secure, not just that the framework offers protection.”
Mistake 2 — Testing performance only with a single user
❌ Wrong: “I loaded the page and it took 1.5 seconds — performance is fine.”
✅ Correct: “Performance testing must simulate realistic concurrent user loads. A page that loads in 1.5 seconds for one user might take 15 seconds under 1,000 concurrent users. Use tools like JMeter or k6 to generate load and measure response times at expected and peak traffic levels.”