Skip to content

Testing Guide

How to test the WebGPU Particle Fluid Simulation codebase.

Test Framework

The project uses Vitest for unit testing and fast-check for property-based testing.

Running Tests

bash
# Run all tests
npm test

# Watch mode (TDD)
npm run test:watch

# With coverage report
npm run test:coverage

# Interactive UI
npm run test:ui

Test Structure

Tests are colocated with source files:

src/core/
├── buffers.ts
├── buffers.test.ts
├── color.ts
├── color.test.ts
├── physics.ts
├── physics.test.ts
└── quality.ts
    └── quality.test.ts

Property-Based Testing

The project uses fast-check for property-based tests:

Example: Particle Bounds

typescript
import * as fc from 'fast-check';
import { initializeParticles } from './buffers';

test('particles are initialized within canvas bounds', () => {
  fc.assert(
    fc.property(
      fc.record({
        width: fc.integer({ min: 100, max: 2000 }),
        height: fc.integer({ min: 100, max: 2000 }),
      }),
      fc.integer({ min: 100, max: 10000 }),
      (canvasSize, count) => {
        const particles = initializeParticles(canvasSize, count);
        // All particles should be within bounds
        for (let i = 0; i < count; i++) {
          const x = particles[i * 4];
          const y = particles[i * 4 + 1];
          expect(x).toBeGreaterThanOrEqual(0);
          expect(x).toBeLessThan(canvasSize.width);
          expect(y).toBeGreaterThanOrEqual(0);
          expect(y).toBeLessThan(canvasSize.height);
        }
      }
    )
  );
});

Test Categories

Physics Tests

PropertyValidates
Particle boundsAll particles within canvas
Physics integrationPosition/velocity updates match formula
Boundary bounceCorrect reflection with damping
Velocity clampingSpeed ≤ MAX_SPEED

Color Tests

PropertyValidates
RGB rangeAll components in [0, 1]
Speed mappingFaster = more purple

Quality Tests

PropertyValidates
Scale limitsOutput within valid range
Tier classificationCorrect tier assignment

Test Configuration

vitest.config.ts:

typescript
export default defineConfig({
  test: {
    environment: 'happy-dom',
    coverage: {
      provider: 'v8',
      reporter: ['text', 'html'],
    },
  },
});

Writing New Tests

Unit Test Pattern

typescript
import { describe, it, expect } from 'vitest';

describe('ModuleName', () => {
  it('should do something', () => {
    // Arrange
    const input = 'test';

    // Act
    const result = doSomething(input);

    // Assert
    expect(result).toBe(expected);
  });
});

Property Test Pattern

typescript
import * as fc from 'fast-check';

test('property description', () => {
  fc.assert(
    fc.property(
      fc.integer(), // arbitrary input
      (value) => {
        // Property that should always hold
        expect(function(value)).toBe(true);
      }
    ),
    { numRuns: 100 }
  );
});

Coverage Goals

CategoryTarget
Statements80%+
Branches75%+
Functions85%+
Lines80%+

Run coverage to see current status:

bash
npm run test:coverage

Built with VitePress