Derived Modular Arch
Concepts

Testing

Where to colocate unit, integration, and e2e tests in a DMA project.

DMA defines placement of tests relative to modules, but doesn't pick the runner, coverage thresholds, or pyramid. One rule: the test lives next to the code it protects.

Unit tests — colocate

File *.test.ts (or *.spec.ts) — in the same folder as the implementation:

features/checkout/
├── checkout.store.ts
├── checkout.store.test.ts      # store — internal
└── public/
    └── checkout-page.tsx

services/cart/public/
├── cart.ts
└── cart.test.ts                # service public API

shared/lib/
├── format-currency.ts
└── format-currency.test.ts

dma check scans test files too — imports in *.test.ts / *.spec.ts enter the same graph as production code. Same rules: public-api, feature-to-feature, layer-direction, and the rest.

What to test directly

CodeTest via
Internal store, composablerelative import in the same module
services/*/public/*import public file
shared/lib/*import helper

What not to do

  • Import another module's internals from a test — the gate fails the same as in production. Test through public/ or colocate the test inside the module with a relative import.
  • Root __tests__/ for the whole project — tests don't move with the module on refactor.

Component tests

SFC / React component tests — colocate next to the component:

features/catalog/public/
├── catalog-page.tsx
└── catalog-page.test.tsx       # optional

Runner of choice: Vitest + Testing Library, @vue/test-utils, @testing-library/svelte. DMA examples' runnable tests are mostly pure TS (stores, services, lib) — no DOM harness.

Integration / route tests

Thin composition root (app/, routes/) — place for wiring checks if needed. More often — a separate folder at the app root:

apps/web/
├── src/
├── e2e/                        # Playwright, Cypress
└── playwright.config.ts

E2E doesn't colocate inside features/ — they cross multiple modules and routes.

Monorepo

Unit tests stay in the app package (apps/web/src/...). Workspace package tests — inside the package. dma check analyzes one graph per root (app or discovered package); graphs are not merged across the monorepo. See Monorepo.

Examples in the repo

ExampleRunnerColocate
vite-reactVitest*.test.ts next to stores, cart, lib
next-appBun teststores + format-currency
sveltekit-routesViteststores, cart, lib
astro-pagesBun teststores, cart, lib
vue-viteViteststores, composables, cart

What's next

On this page