Testing in the Software Development Lifecycle

Mastering Software Testing - ISTQB Foundation Level

Chapter 2: Testing in the Software Development Lifecycle

Introduction

Testing isn't a separate phase that happens at the end - it's integrated throughout the entire software development lifecycle (SDLC). This chapter explores when and how to test at each stage.

Software Development Models

Waterfall Model

Sequential approach where each phase must be completed before the next begins.

flowchart TD
    A[Requirements] --> B[Design]
    B --> C[Implementation]
    C --> D[Testing]
    D --> E[Deployment]
    E --> F[Maintenance]
    
    style A fill:#667eea
    style B fill:#764ba2
    style C fill:#f093fb
    style D fill:#ff6b6b
    style E fill:#ffd93d
    style F fill:#6bcf7f

Testing in Waterfall:

  • Testing phase comes after development
  • Limited feedback loops
  • Difficult to make changes
  • High cost of late defect detection

V-Model (Verification and Validation)

Extends waterfall by adding corresponding test levels for each development phase.

graph LR
    A[Requirements] -.->|validates| H[Acceptance Testing]
    B[System Design] -.->|validates| G[System Testing]
    C[Architectural Design] -.->|validates| F[Integration Testing]
    D[Module Design] -.->|validates| E[Unit Testing]
    
    A --> B --> C --> D
    D --> E --> F --> G --> H
    
    style A fill:#667eea
    style B fill:#667eea
    style C fill:#667eea
    style D fill:#667eea
    style E fill:#f093fb
    style F fill:#f093fb
    style G fill:#f093fb
    style H fill:#f093fb

Advantages:

  • Testing planned early
  • Clear traceability
  • Each level has corresponding tests

##Agile & Scrum

Iterative development with continuous testing.

flowchart LR
    A[Product Backlog] --> B[Sprint Planning]
    B --> C[Sprint 2-4 weeks]
    C --> D[Daily Standup]
    D --> C
    C --> E[Sprint Review]
    E --> F[Sprint Retrospective]
    F --> G{More Sprints?}
    G -->|Yes| A
    G -->|No| H[Release]
    
    style A fill:#667eea
    style C fill:#764ba2
    style E fill:#f093fb
    style H fill:#6bcf7f

Testing in Agile:

  • Continuous testing
  • Test-Driven Development (TDD)
  • Automated testing crucial
  • Testers are part of the team

Test Levels

1. Unit Testing

Testing individual components in isolation.

# Example: Unit test for a function
def calculate_discount(price, discount_percent):
    """Calculate discounted price"""
    if discount_percent < 0 or discount_percent > 100:
        raise ValueError("Invalid discount percentage")
    return price * (1 - discount_percent / 100)

# Unit test
def test_calculate_discount():
    assert calculate_discount(100, 10) == 90
    assert calculate_discount(100, 0) == 100
    
    with pytest.raises(ValueError):
        calculate_discount(100, -5)

Focus: Functions, methods, classes Who: Developers Tools: JUnit, pytest, NUnit

2. Integration Testing

Testing interactions between components.

graph TB
    subgraph Integration Testing
        A[User Service] -->|calls| B[Database]
        A -->|calls| C[Email Service]
        D[Payment Service] -->|calls| B
        D -->|calls| E[Bank API]
    end
    
    style A fill:#667eea
    style D fill:#667eea
    style B fill:#764ba2
    style C fill:#764ba2
    style E fill:#764ba2

Focus: Module interactions, APIs, databases Who: Developers & Testers Approaches:

  • Big Bang: Integrate all at once
  • Top-Down: Start from main module
  • Bottom-Up: Start from lowest modules
  • Sandwich: Combination approach

3. System Testing

Testing the complete integrated system.

Types of System Tests:

  • Functional: Feature verification
  • Performance: Speed, scalability
  • Security: Vulnerability testing
  • Usability: User experience
  • Compatibility: Different platforms

Example Test Scenarios:

### Test Scenario: E-commerce Checkout Flow

1. User browses products
2. Adds items to cart
3. Applies discount code
4. Enters shipping information
5. Selects payment method
6. Confirms order
7. Receives confirmation email

Expected: Complete purchase successfully

4. Acceptance Testing

Validation that system meets business requirements.

Types:

  • User Acceptance Testing (UAT): Real users test
  • Operational Acceptance Testing (OAT): Operations team verifies
  • Regulatory Testing: Compliance verification

Test Types

Functional Testing

Verifies WHAT the system does.

def test_login_functionality():
    """Test login feature"""
    # Test valid credentials
    result = login("user@example.com", "Password123")
    assert result.success == True
    assert result.user_id is not None
    
    # Test invalid credentials
    result = login("user@example.com", "wrong_password")
    assert result.success == False
    assert result.error == "Invalid credentials"

Non-Functional Testing

Verifies HOW WELL the system performs.

Performance Testing Example:

import time

def test_response_time():
    """Test API response time"""
    start_time = time.time()
    response = api.get_user(user_id=123)
    end_time = time.time()
    
    response_time = end_time - start_time
    assert response_time < 1.0  # Must respond within 1 second

Regression Testing

Ensures new changes don't break existing functionality.

flowchart LR
    A[New Feature Added] --> B[Run Regression Tests]
    B --> C{All Tests Pass?}
    C -->|Yes| D[Deploy]
    C -->|No| E[Fix Issues]
    E --> B
    
    style A fill:#667eea
    style B fill:#764ba2
    style D fill:#6bcf7f
    style E fill:#ff6b6b

Maintenance Testing

Testing after software is deployed.

Triggers for Maintenance Testing:

  • Bug fixes
  • Enhancements
  • Environment changes
  • Data migration

Impact Analysis:

# Before changing a function, analyze impact
def analyze_function_usage(function_name):
    """Find all places where function is used"""
    # This helps determine test scope
    usages = search_codebase(function_name)
    return [
        "Module A: payment processing",
        "Module B: reporting",
        "Module C: admin dashboard"
    ]
    # All these need regression testing!

Testing in DevOps

Continuous Integration and Continuous Deployment (CI/CD).

flowchart LR
    A[Developer Commits] --> B[Build]
    B --> C[Unit Tests]
    C --> D[Integration Tests]
    D --> E{Tests Pass?}
    E -->|Yes| F[Deploy to Staging]
    E -->|No| G[Notify Developer]
    F --> H[System Tests]
    H --> I{Tests Pass?}
    I -->|Yes| J[Deploy to Production]
    I -->|No| G
    
    style A fill:#667eea
    style F fill:#764ba2
    style J fill:#6bcf7f
    style G fill:#ff6b6b

Key Practices:

  • Automated test execution
  • Fast feedback loops
  • Test at every stage
  • Monitor production

Shift-Left Testing

Move testing earlier in the lifecycle.

Traditional:

Requirements → Design → Development → [Testing Here] → Release

Shift-Left:

[Testing] Requirements → [Testing] Design → [Testing] Development → [Testing] Release

Benefits:

  • Find defects earlier
  • Lower cost of fixes
  • Better quality
  • Faster delivery

Test-Driven Development (TDD)

Write tests before code!

# 1. Write test first (it fails)
def test_add_user():
    user = User("john@example.com")
    assert user.email == "john@example.com"
    assert user.is_active == True

# 2. Write minimum code to pass
class User:
    def __init__(self, email):
        self.email = email
        self.is_active = True

# 3. Refactor (improve code while tests still pass)
class User:
    def __init__(self, email):
        self._validate_email(email)
        self.email = email
        self.is_active = True
    
    def _validate_email(self, email):
        if '@' not in email:
            raise ValueError("Invalid email")

TDD Cycle:

flowchart LR
    A[Write Test] --> B[Run Test Fails]
    B --> C[Write Code]
    C --> D[Run Test Passes]
    D --> E[Refactor]
    E --> A
    
    style A fill:#667eea
    style B fill:#ff6b6b
    style D fill:#6bcf7f
    style E fill:#764ba2

Practical Examples

Example 1: Testing in Agile Sprint

**Sprint Goal**: Implement user profile feature

Week 1:
- Day 1: Write acceptance criteria & tests
- Day 2-3: Develop feature with unit tests
- Day 4: Integration testing
- Day 5: Sprint review & demo

Test Activities:
- TDD for all new code
- Automated regression suite runs nightly
- Manual exploratory testing daily
- Performance test at sprint end

Example 2: CI/CD Pipeline

# .github/workflows/test.yml
name: Test Pipeline

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Run Unit Tests
        run: pytest tests/unit
        
      - name: Run Integration Tests
        run: pytest tests/integration
        
      - name: Generate Coverage Report
        run: pytest --cov=src --cov-report=xml
        
      - name: Check Coverage Threshold
        run: |
          if coverage < 80%; then
            exit 1
          fi

Key Takeaways

  1. āœ… Testing happens throughout the SDLC, not just at the end
  2. āœ… Different development models require different testing approaches
  3. āœ… Four test levels: Unit, Integration, System, Acceptance
  4. āœ… Test both functional AND non-functional requirements
  5. āœ… Shift testing left to find defects earlier
  6. āœ… Automate testing in CI/CD pipelines
  7. āœ… TDD improves code quality

Review Questions

  1. What is the V-Model and how does it improve on Waterfall?
  2. Explain the difference between unit and integration testing
  3. What is shift-left testing and why is it beneficial?
  4. How does testing differ in Agile vs. Waterfall?
  5. Describe the TDD cycle

Next Chapter

Chapter 3 explores Static Testing - finding defects without executing code through reviews and analysis!

Complete Lab 2 to practice testing at different levels in a real application!