3
08 TestPlan
Patrick Plate edited this page 2026-06-19 16:43:56 +02:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

08 — Test Plan

Project: CannaManage — B2B SaaS for German Cannabis Social Clubs Version: 14.0 (Sprint 14) Date: 2026-06-19 Status: Active — 500+ automated tests passing, JaCoCo 80% coverage gate


1. Test Strategy Overview

1.1 Testing Pyramid

            ┌───────────────────┐
            │  E2E / System     │   5% — Playwright (browser automation)
            │     Tests         │
            ├───────────────────┤
            │  Integration      │  25% — Spring Boot Test + Testcontainers
            │     Tests         │
            ├───────────────────┤
            │  Frontend Unit    │  20% — Vitest + MSW (React components)
            │     Tests         │
            ├───────────────────┤
            │  Backend Unit     │  50% — JUnit 5 + Mockito
            │     Tests         │
            └───────────────────┘

The compliance-critical path (ComplianceService) requires 100% line coverage — no exceptions. Every quota rule is a legal obligation under CanG §§1922.

1.2 Tools and Frameworks

Layer Tool Purpose
Backend Unit JUnit 5 (junit-jupiter) Test runner
Backend Unit Mockito 5 Mock dependencies
Backend Unit AssertJ Fluent assertions
Backend Integration Spring Boot Test (@SpringBootTest) Full application context
Backend Integration Testcontainers (PostgreSQL 16) Real DB in Docker
Backend Integration MockMvc / RestAssured HTTP layer testing
Backend Coverage JaCoCo Line/branch coverage — 80% gate
Frontend Unit Vitest Fast ESM-native test runner
Frontend Unit MSW (Mock Service Worker) API mocking at network level
Frontend Unit Testing Library Component rendering + queries
Frontend E2E Playwright Browser automation, multi-browser
Frontend E2E Playwright Test Test runner with fixtures + assertions
System Tests Playwright + SQL seed Full-stack with seeded database

1.3 CI Pipeline Test Flow

graph LR
    Push["git push"] --> CI["Gitea Actions"]
    CI --> Backend["Maven Build\n+ Unit Tests\n+ Integration Tests"]
    CI --> Frontend["pnpm install\n+ Vitest"]
    Backend --> JaCoCo["JaCoCo Report\n80% gate"]
    JaCoCo -->|"pass"| Deploy["Deploy"]
    JaCoCo -->|"fail"| Block["❌ Block Merge"]
    Frontend --> E2E["Playwright E2E\n(on main only)"]
    E2E --> Deploy
Branch pattern Tests run
Feature PR Backend unit + integration, Frontend Vitest
main All above + JaCoCo gate + Playwright E2E

2. Backend Testing

2.1 Unit Tests (JUnit 5 + Mockito)

Target: All service classes, especially compliance-critical code.

ComplianceService — Critical Path (100% coverage required)

TC Method Under Test Scenario Expected
TC-001 checkDistributionAllowed Adult at 50g monthly limit + 1g request QuotaExceededException(MONTHLY)
TC-002 checkDistributionAllowed Under-21 at 30g monthly limit + 1g request QuotaExceededException(MONTHLY)
TC-003 checkDistributionAllowed Adult at 25g daily limit + 0.5g request QuotaExceededException(DAILY)
TC-004 checkDistributionAllowed THC >10% for under-21 THCLimitExceededException
TC-005 checkDistributionAllowed Suspended member MemberSuspendedException
TC-006 checkDistributionAllowed Valid request within limits No exception
TC-007 checkDistributionAllowed New month resets quota No exception
TC-008 calculateRemainingQuota Mid-month with partial usage Correct remaining

Other Service Tests

Service Key Test Cases
DistributionService Create, validate batch availability, stock deduction
MemberService CRUD, status transitions, age calculation
StockService Batch management, movement tracking, low-stock alerts
ReportService Monthly report generation, CSV/PDF export
FinanceService Transaction recording, balance calculation
BankImportService MT940/CAMT053 parsing, auto-matching
AssemblyService Vote creation, ballot counting, quorum check
AuditService Event recording, immutability verification
NotificationService Dispatch, preference filtering, rate limiting

2.2 Integration Tests (Testcontainers)

Real PostgreSQL 16 in Docker — catches issues that H2/mocks hide:

@SpringBootTest
@Testcontainers
class DistributionIntegrationTest {

    @Container
    static PostgreSQLContainer<?> pg = new PostgreSQLContainer<>("postgres:16-alpine");

    @Test
    void createDistribution_validRequest_persistsAndUpdatesQuota() {
        // Given: member with remaining quota, batch with stock
        // When: POST /api/v1/distributions
        // Then: distribution persisted, quota updated, stock decremented
    }
}

Key integration test scenarios:

Area Test Cases
Auth flow Login → JWT → protected endpoint → 200
Token revocation Revoke → subsequent request → 401
Tenant isolation Tenant A data invisible to Tenant B
Flyway migrations All V1V36 apply cleanly to fresh DB
Stripe webhooks Payment success → subscription activated
Bank import Upload MT940 → parse → auto-match → transactions created
Report generation Generate monthly report → PDF valid

2.3 Coverage — JaCoCo Configuration

<!-- pom.xml -->
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <configuration>
        <rules>
            <rule>
                <element>BUNDLE</element>
                <limits>
                    <limit>
                        <counter>LINE</counter>
                        <value>COVEREDRATIO</value>
                        <minimum>0.80</minimum>
                    </limit>
                </limits>
            </rule>
            <rule>
                <element>CLASS</element>
                <includes>
                    <include>de.cannamanage.service.ComplianceService</include>
                </includes>
                <limits>
                    <limit>
                        <counter>LINE</counter>
                        <value>COVEREDRATIO</value>
                        <minimum>1.00</minimum>
                    </limit>
                </limits>
            </rule>
        </rules>
    </configuration>
</plugin>
Rule Target Threshold
Bundle (overall) All classes 80% line coverage
ComplianceService Single class 100% line coverage
Controllers All controllers 70% (integration tests cover the rest)

3. Frontend Testing

3.1 Unit Tests — Vitest + MSW

Config: vitest.config.ts with jsdom environment.

// Example: MemberList component test
import { render, screen } from '@testing-library/react';
import { server } from '@/mocks/server';
import { http, HttpResponse } from 'msw';

test('renders member list from API', async () => {
  server.use(
    http.get('/api/v1/members', () =>
      HttpResponse.json([{ id: 1, firstName: 'Max', lastName: 'Mustermann' }])
    )
  );

  render(<MemberList />);
  expect(await screen.findByText('Max Mustermann')).toBeInTheDocument();
});

MSW handler pattern: Mirrors the real API contract from src/types/api.ts — tests validate against the actual interface.

Area Key Test Cases
Components Render, user interaction, conditional display
Hooks React Query hooks with MSW responses
Forms Validation, submission, error display
Auth Protected route redirection, token refresh
i18n German + English text rendering

3.2 E2E Tests — Playwright

Config: playwright.config.ts — Chromium, Firefox, WebKit.

// Example: Distribution recording flow
test('admin records a distribution', async ({ page }) => {
  await page.goto('/dashboard/distributions');
  await page.click('[data-testid="new-distribution"]');
  
  // Step 1: Select member
  await page.fill('[data-testid="member-search"]', 'Max');
  await page.click('[data-testid="member-option-1"]');
  
  // Step 2: Quota check shown
  await expect(page.locator('[data-testid="remaining-quota"]')).toBeVisible();
  
  // Step 3: Select batch + amount
  await page.selectOption('[data-testid="batch-select"]', 'batch-001');
  await page.fill('[data-testid="amount"]', '5.0');
  
  // Step 4: Confirm
  await page.click('[data-testid="confirm-distribution"]');
  await expect(page.locator('[data-testid="success-toast"]')).toBeVisible();
});

E2E test coverage:

Flow What's tested
Login (admin) JWT auth, redirect to dashboard
Login (member) Session auth, redirect to portal
Distribution recording 4-step form, quota enforcement
Member management CRUD, search, filter
Stock management Add batch, view movements
Report generation Select type, generate, download
Staff invite Create invite, permission editor
Payment import Upload file, review matches, confirm

3.3 System Tests (SQL Seed + Playwright)

Full-stack tests that seed the database via SQL, then drive the application through the browser:

test.describe('System: Distribution Compliance', () => {
  test.beforeAll(async () => {
    // Seed database with member at 49g/month
    await seedDatabase('test-data/member-near-limit.sql');
  });

  test('blocks distribution exceeding monthly quota', async ({ page }) => {
    await loginAsAdmin(page);
    await page.goto('/dashboard/distributions');
    // Try to distribute 2g (would exceed 50g limit)
    // ...
    await expect(page.locator('[data-testid="quota-error"]')).toContainText('50g');
  });
});

4. Test Data Strategy

Environment Data Source Lifecycle
Unit tests Mocked (Mockito / MSW) Per-test
Integration tests Testcontainers (fresh DB each run) Per-class
E2E tests SQL seed files Per-suite
System tests SQL seed + API-driven setup Per-suite

Test Data Files

cannamanage-api/src/test/resources/
├── test-data/
│   ├── member-near-limit.sql
│   ├── full-club-setup.sql
│   ├── bank-import-mt940.txt
│   └── bank-import-camt053.xml

5. Quality Gates

Gate Threshold Blocks
JaCoCo overall ≥ 80% line PR merge
JaCoCo ComplianceService 100% line PR merge
Backend tests All pass PR merge
Frontend Vitest All pass PR merge
Playwright E2E All pass Deploy to prod
Build success mvn clean verify Everything

6. Running Tests Locally

Backend

# All tests
mvn clean verify

# Unit only (fast)
mvn test

# Integration only
mvn verify -DskipUnitTests

# Single test class
mvn test -Dtest=ComplianceServiceTest

# With coverage report
mvn verify -Pjacoco
open target/site/jacoco/index.html

Frontend

cd cannamanage-frontend

# Unit tests (Vitest)
pnpm test

# Watch mode
pnpm test:watch

# Coverage
pnpm test:coverage

# E2E (Playwright)
pnpm exec playwright test

# E2E with UI
pnpm exec playwright test --ui

# Specific test file
pnpm exec playwright test tests/distribution.spec.ts

7. Test Metrics (Current)

Metric Value
Total automated tests 500+
Backend unit tests ~250
Backend integration tests ~100
Frontend Vitest tests ~100
Playwright E2E tests ~50
JaCoCo overall coverage ~82%
ComplianceService coverage 100%
CI pipeline duration ~4 minutes
Flaky test rate < 1%