SE Notes
Systematic verification and validation of the software system.
The testing phase systematically evaluates the software system to verify it meets its specifications and validate it satisfies user needs. Testing is not simply "trying the software to see if it works"—it is a disciplined engineering activity with specific objectives, techniques, coverage criteria, and documentation requirements. Its purpose is twofold: verification (did we build the system right—does it conform to specifications?) and validation (did we build the right system—does it satisfy the actual user needs?). Testing cannot prove a system is defect-free, but it can demonstrate that specific defects exist and that the system behaves correctly for tested scenarios.
Why Testing Is Critical
The cost of defects increases exponentially the later they are discovered. A requirement error caught during analysis costs perhaps $100 to fix. The same error discovered during testing costs $1,000-$5,000. If it reaches production, it might cost $10,000-$100,000 in emergency fixes, data recovery, lost revenue, and reputation damage. The testing phase is the last systematic opportunity to catch defects before they reach users.
Consider the Therac-25 radiation therapy machine, where software defects caused patient deaths because race conditions in the control software were not adequately tested. Or the Ariane 5 rocket that self-destructed 37 seconds after launch because an integer overflow in reused software was never tested in the new context. These disasters underscore that testing is not optional—it is a professional responsibility.
Testing Levels
Testing proceeds through progressive levels of scope:
Unit Testing verifies individual modules in isolation. Each function, method, or class is tested independently using controlled inputs and expected outputs. Unit tests are fast, numerous, and automated:
# Unit test for a password validator
def test_password_minimum_length():
assert validate_password("Ab1!xyz") == False # 7 chars, needs 8
def test_password_requires_uppercase():
assert validate_password("abcdefg1!") == False # no uppercase
def test_password_valid():
assert validate_password("SecureP@ss1") == True # meets all criteriaIntegration Testing verifies that modules work correctly together. Individual modules might pass unit tests perfectly but fail when combined due to interface mismatches, data format differences, or incorrect assumptions about calling sequences. Integration approaches include:
- Top-down: Start with high-level modules, add lower modules progressively
- Bottom-up: Start with low-level modules, add higher modules progressively
- Big-bang: Combine all modules at once (risky but sometimes necessary)
System Testing evaluates the complete integrated system against its requirements specification. This includes:
- Functional testing: Does each requirement work correctly?
- Performance testing: Does the system meet speed and capacity requirements?
- Security testing: Can the system resist attacks?
- Usability testing: Can users accomplish tasks efficiently?
- Reliability testing: Does the system operate correctly over extended periods?
Acceptance Testing involves actual users verifying the system meets their needs in realistic scenarios. User Acceptance Testing (UAT) is the final validation before deployment.
Testing Techniques
Black-Box Testing designs tests based on requirements without knowledge of internal code structure. Techniques include:
- Equivalence partitioning: Divide inputs into classes that should behave similarly
- Boundary value analysis: Test at the edges of input ranges
- Decision table testing: Cover all combinations of conditions and actions
White-Box Testing designs tests based on internal code structure. Techniques include:
- Statement coverage: Every line of code executes at least once
- Branch coverage: Every decision point takes both true and false paths
- Path coverage: Every possible execution path is tested
Grey-Box Testing combines both approaches—using some knowledge of internal structure to design more effective black-box tests.
Real-World Example: Flight Booking System Testing
A new airline booking system undergoes systematic testing:
Unit Testing (4 weeks): 2,500 unit tests cover individual components—fare calculation, seat availability, date validation, passenger information processing. Tests run in 3 minutes, executed on every code commit.
Integration Testing (3 weeks): Verify the booking engine correctly communicates with the payment gateway, the seat inventory system, and the email notification service. Test that partial failures are handled gracefully (payment succeeds but email fails—order should still be confirmed).
System Testing (4 weeks):
- Performance: System handles 10,000 concurrent searches and 500 simultaneous bookings without degradation
- Security: Penetration testing reveals no vulnerabilities in payment flow
- Functionality: All 847 documented requirements are verified
- Compatibility: System works across Chrome, Firefox, Safari, and mobile browsers
Acceptance Testing (2 weeks): Airline customer service staff process sample bookings, modifications, and cancellations using realistic scenarios. Travel agents test the B2B interface. Frequent flyers test the loyalty program integration.
Test Documentation
Test Plan defines the testing strategy: what will be tested, what techniques will be used, what resources are needed, and what the schedule is.
Test Cases specify individual tests: preconditions, input data, expected results, and actual results. Each test case traces to a requirement to ensure complete coverage.
Test Report summarizes testing outcomes: tests executed, passed, failed, blocked, and the defects discovered with their severity and status.
Defect Management
Discovered defects are logged with severity (critical, major, minor, cosmetic), priority (immediate, next release, backlog), steps to reproduce, expected behavior, actual behavior, and screenshots or logs. Defects flow through a lifecycle: New → Assigned → Fixed → Verified → Closed. Metrics track defect discovery rate, fix rate, and escape rate to assess quality trends.
Testing Challenges
Exhaustive testing is impossible: Even a simple form with 10 fields, each accepting 100 values, has 100^10 possible combinations. Testing must be strategic rather than exhaustive. Time pressure often compresses testing, tempting teams to skip edge cases. Test environment differences from production can mask defects or create false positives. Changing requirements invalidate existing tests, requiring continuous test maintenance. Effective testing balances thoroughness against practical constraints through risk-based prioritization.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Testing Phase.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Software Engineering topic.
Search Terms
software-engineering, software engineering, software, engineering, development, life, cycle, testing
Related Software Engineering Topics