Sat Mar 08 - Written by: Samridha
Advanced Software Testing
Explore risk-based testing, structure-based testing, analytical techniques, and dynamic analysis for software quality improvement.
Advanced Software Testing Book
Risk-Based Testing
Risk-based testing is a test strategy that prioritizes test cases based on the likelihood and impact of potential failures.
- More focus should be given to areas with high risk.
- Resources should be appropriately allocated.
Where Does Risk Come From?
- Complex features
- Frequently used features
- Past defect history
How to Assess Risk?
- Based on likelihood and impact
- Create a Likelihood-Impact Matrix
- Risk Matrix:
Likelihood → | Low Impact | Medium Impact | High Impact |
---|---|---|---|
Low | Low | Low | Medium |
Medium | Low | Medium | High |
High | Medium | High | Critical |
Testing Strategy Based on Risk Level
- High Risk → Extensive testing (functional, edge cases, performance, security).
- Medium Risk → Moderate testing (positive and negative test cases).
- Low Risk → Minimal testing (smoke and sanity checks).
Pragmatic Risk-Based Testing
- Use scoring:
- Low = 1
- Medium = 2
- High = 3
- Risk Score = Impact Score × Likelihood Score
How to Determine Likelihood Score?
- Recent code changes
- History of defects
- Code complexity (Git changes)
- Usage frequency
- Integration with third-party tools
- Security vulnerabilities
Tools for Risk Assessment
- SonarQube, Pylint
Structure-Based Testing
Structure-based testing is a white-box testing strategy where test cases are defined based on the internal structure of the code rather than just relying on external behavior.
Why Structure-Based Testing?
- Helps uncover defects not found in black-box testing.
- Identifies dead code (unused or unreachable code).
- Detects missing conditions and logical errors.
- Ensures better test coverage.
Types of Structure-Based Testing
- Statement Coverage – Ensures all statements in the code are executed.
- Branch Coverage – Ensures all decision branches are executed.
- Path Coverage – Ensures all execution paths are tested.
- Use flow graphs to determine possible paths.
- Design test cases for each path.
- Cyclomatic Complexity – Measures the number of independent paths in a program.
- Loop Coverage – Ensures loops are tested with:
- 0 iterations (loop not executed)
- 1 iteration (loop executed once)
- Multiple iterations
Tools for Code Coverage Measurement
- SonarQube, Pylint
Automation Strategy
- Automate all unit test cases.
Selecting the Right Structure-Based Coverage
System Complexity | Recommended Coverage |
---|---|
Simple System | Statement Coverage is sufficient |
Complex System | Path Coverage is required |
Analytical Techniques
Analytical techniques involve analyzing code to improve quality and detect defects early.
Static Analysis
In static analysis, code is examined without executing it. It helps identify issues related to structure, control flow, and data flow.
1. Control Flow Analysis
- Uses control flow graphs to identify:
- Unreachable code
- Infinite loops
- Paths that are not tested
2. Data Flow Analysis
- Tracks variable value changes throughout the program.
- Helps detect:
- Uninitialized variables
- Unused variables
- Incorrect assignments
3. Call Graph Analysis
- Constructs a graph of function calls within the program.
- Helps detect:
- Excessive dependencies
- Low modularity
- Used in integration testing
Dynamic Analysis
Dynamic analysis involves executing the program to detect runtime issues such as crashes, memory leaks, and pointer-related errors.
1. Memory Leaks
- Occurs when memory is allocated but not freed.
- Leads to:
- Performance degradation
- Crashes due to high memory consumption
2. Wild Pointers
- A wild pointer is an uninitialized pointer.
- Can cause segmentation faults and crashes.