0% found this document useful (0 votes)
6 views3 pages

19 Software Testing

The document outlines the importance of software testing, emphasizing the need to catch bugs early in development to reduce costs. It introduces the testing pyramid, detailing unit, integration, and end-to-end tests, and discusses various testing strategies, tools, and best practices, including the use of pytest and CI/CD integration. Additionally, it covers test doubles, code coverage, and testing in JavaScript with Vitest/Jest.

Uploaded by

romanovskijv508
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views3 pages

19 Software Testing

The document outlines the importance of software testing, emphasizing the need to catch bugs early in development to reduce costs. It introduces the testing pyramid, detailing unit, integration, and end-to-end tests, and discusses various testing strategies, tools, and best practices, including the use of pytest and CI/CD integration. Additionally, it covers test doubles, code coverage, and testing in JavaScript with Vitest/Jest.

Uploaded by

romanovskijv508
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Software Testing

Strategies, types, and tools for quality assurance

IT & Tech Reports | Class IM24A | 2026

1. Why Test?
Software testing verifies that a system behaves as expected, catches regressions, and builds
confidence for deployment. The cost of fixing a bug increases exponentially the later it is found: a bug
found in production can cost 100x more to fix than one caught during development.

2. The Testing Pyramid


The testing pyramid describes the ideal proportion of test types — more unit tests at the base, fewer
expensive E2E tests at the top:

• Unit Tests (base) — test individual functions/classes in isolation; fast, cheap, many

• Integration Tests (middle) — test how components interact (service + DB, API + auth)

• End-to-End Tests (top) — simulate a real user through the full stack; slow, fragile, few

3. Unit Testing with pytest (Python)


import pytest

from [Link] import add, divide

def test_add_positive_numbers():

assert add(2, 3) == 5

def test_add_negative():

assert add(-1, 1) == 0

def test_divide_by_zero():

with [Link](ZeroDivisionError):

divide(10, 0)

@[Link]("a,b,expected", [(1,2,3),(0,0,0),(-1,-1,-2)])

def test_add_parametrised(a, b, expected):

assert add(a, b) == expected

4. Test Doubles
Type Description When to use

Dummy Placeholder passed but never used Filling required parameters


Type Description When to use

Stub Returns predefined responses Controlling indirect inputs

Mock Verifies specific calls were made Testing interactions/side effects

Spy Records calls to a real object Partial verification

Fake Simplified working implementation In-memory DB, fake email service

from [Link] import Mock, patch

def test_send_email():

email_service = Mock()

user_service = UserService(email_service)

user_service.register("ivan@[Link]")

email_service.send_welcome.assert_called_once_with("ivan@[Link]")

5. Test Coverage
Code coverage measures what percentage of your code is executed during tests. 80% is a common
target. Use pytest --cov=myapp to generate a report.

Coverage Type What it measures

Line coverage Which lines of code were executed

Branch coverage Which if/else branches were taken (more thorough)

Function coverage Which functions/methods were called

Mutation testing Whether tests detect artificial bugs (highest confidence)

6. Testing in JavaScript with Vitest / Jest


import { describe, it, expect, vi } from "vitest";

import { formatDate } from "./utils";

describe("formatDate", () => {

it("formats a date as [Link]", () => {

expect(formatDate(new Date("2026-03-15"))).toBe("15.03.2026");

});

it("throws on invalid input", () => {

expect(() => formatDate(null)).toThrow("Invalid date");

});

});

7. CI/CD Integration
Tests should run automatically on every push via a CI pipeline (GitHub Actions, GitLab CI):

# .github/workflows/[Link]

on: [push, pull_request]

jobs:

test:

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v4

- uses: actions/setup-python@v5

with: { python-version: "3.12" }

- run: pip install -e ".[dev]"

- run: pytest --cov=myapp --cov-report=xml

8. Testing Best Practices


• Write tests before or alongside the code (TDD: Red-Green-Refactor)

• Each test should verify exactly one behaviour — keep them small and focused

• Use descriptive names: test_user_cannot_login_with_wrong_password

• Tests must be deterministic — no random data, no time-dependent logic without mocking

• Never test implementation details — test behaviour and public interfaces only

• Keep tests fast: mock I/O, databases, and external services in unit tests

You might also like