Skip to content

Testing Guide

This guide covers testing strategies for the Freeze Design webshop.

Test Pyramid

        ┌───────────┐
        │   E2E     │  ← Few, slow, high confidence
        ├───────────┤
        │Integration│  ← Medium number
        ├───────────┤
        │   Unit    │  ← Many, fast, focused
        └───────────┘

Backend Testing

Run Tests

cd backend
python manage.py test

With Coverage

coverage run manage.py test
coverage report
coverage html  # Open htmlcov/index.html

Test Structure

# tests/test_products.py
from django.test import TestCase
from rest_framework.test import APITestCase

class ProductAPITests(APITestCase):
    def setUp(self):
        self.product = Product.objects.create(
            name='Test Product',
            base_price=29.95
        )

    def test_list_products(self):
        response = self.client.get('/api/products/')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.data['results']), 1)

    def test_product_detail(self):
        response = self.client.get(f'/api/products/{self.product.slug}/')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.data['name'], 'Test Product')

Frontend Testing

Unit Tests (Jest)

cd frontend
npm run test
npm run test:coverage

Test Structure

// Component.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { QuantitySelector } from './QuantitySelector';

describe('QuantitySelector', () => {
  it('increments quantity when plus clicked', () => {
    const onChange = jest.fn();
    render(<QuantitySelector quantity={1} onQuantityChange={onChange} />);

    fireEvent.click(screen.getByLabelText('Verhoog aantal'));

    expect(onChange).toHaveBeenCalledWith(2);
  });

  it('disables decrement at minimum', () => {
    render(<QuantitySelector quantity={1} onQuantityChange={() => {}} min={1} />);

    expect(screen.getByLabelText('Verlaag aantal')).toBeDisabled();
  });
});

E2E Testing (Playwright)

Run Tests

cd frontend
npm run test:e2e
npm run test:e2e:ui  # Interactive mode

Test Structure

// e2e/checkout.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Checkout Flow', () => {
  test('complete order', async ({ page }) => {
    // Browse to product
    await page.goto('/products/classic-t-shirt');

    // Select options
    await page.click('[data-testid="color-swatch-1"]');
    await page.click('[data-testid="size-option-3"]');

    // Add to cart
    await page.click('[data-testid="add-to-cart"]');

    // Proceed to checkout
    await page.click('[data-testid="checkout-button"]');

    // Fill form
    await page.fill('[name="email"]', 'test@example.com');
    // ...

    // Submit order
    await page.click('[data-testid="submit-order"]');

    // Verify success
    await expect(page.locator('.order-confirmation')).toBeVisible();
  });
});

CI/CD Testing

Tests run automatically on every push. See .github/workflows/ci.yml.

Required Checks

  • Backend tests pass
  • Frontend tests pass
  • E2E tests pass
  • Linting passes
  • Type checking passes