DEV Community

Bhaumik
Bhaumik

Posted on

(untitled)

TDD Industry Standard Guide — Full Stack R&D Reference

Scope: Node.js · NestJS · Express.js · React · Next.js · Angular · Python · Laravel

Audience: Engineering teams adopting or scaling TDD practices

Version: 2025 — reflects current ecosystem state


Part 1 — What Is TDD and How It Works

1.1 Core Philosophy

TDD (Test-Driven Development) is a development methodology where tests are written before the production code. It inverts the traditional flow — instead of writing code then checking if it works, you first define what "working" means.

Red → Green → Refactor cycle:

1. RED    — Write a failing test for a behavior that doesn't exist yet
2. GREEN  — Write the minimum code required to make that test pass
3. REFACTOR — Clean up the code without breaking the test
Enter fullscreen mode Exit fullscreen mode

This isn't just about testing — it's a design discipline. Forcing yourself to write tests first exposes bad API design, tight coupling, and unclear responsibilities before they're baked into code.

1.2 TDD vs BDD vs ATDD

Approach Who writes Language Focus
TDD Developer Code/assertions Unit behavior
BDD Dev + QA Gherkin (Given/When/Then) User scenarios
ATDD Dev + QA + Business Acceptance criteria System behavior

In practice, most production teams use TDD for units + BDD for integration/E2E. Pure ATDD is rare outside regulated industries.

1.3 The Test Pyramid (Industry Standard Model)

          /\
         /  \
        / E2E \          ~10% — Slow, expensive, brittle
       /--------\
      /Integration\      ~20% — Services, DB, APIs
     /--------------\
    /   Unit Tests   \   ~70% — Fast, isolated, numerous
   /------------------\
Enter fullscreen mode Exit fullscreen mode

Invert this ratio = test anti-pattern (too many E2E tests = slow CI, fragile suite).


Part 2 — Test Types and What to Cover

2.1 Unit Tests

  • Test a single function, class, or module in isolation
  • All dependencies are mocked/stubbed
  • Should run in < 50ms per test

Cover:

  • Pure functions (transformation, calculation, formatting)
  • Service layer business logic
  • Guards, interceptors, middlewares
  • Validators and DTOs
  • Utility helpers

2.2 Integration Tests

  • Test two or more real components together
  • May hit a real DB (test DB), real service layer, real HTTP handler
  • Slower than unit tests but critical for wiring validation

Cover:

  • Controller → Service → Repository chain
  • Database queries with real schema
  • Auth flows (token issuance + validation)
  • Event-driven pipelines (queue → handler)

2.3 E2E Tests

  • Test the full system from HTTP request to response
  • Often uses a real or in-memory database
  • Validates complete user workflows

Cover:

  • Critical user journeys (login, checkout, form submission)
  • API contract validation
  • Cross-service flows in microservices

2.4 Contract Tests (Underused but Valuable)

  • Tests API contracts between producer and consumer
  • Tool: Pact.js (Node), Pactflow (SaaS)
  • Essential in microservices architectures

2.5 Snapshot Tests

  • Capture rendered output and detect unintended changes
  • Best for UI components (React, Angular)
  • Overuse leads to meaningless "approve all snapshots" habit

2.6 Test Case Identification Strategy

Before writing tests, apply these techniques:

Equivalence Partitioning — Group inputs into classes that behave the same

Boundary Value Analysis — Test at edges (0, -1, max, max+1)

Decision Table Testing — Matrix of conditions vs outcomes

State Transition — For stateful flows (e.g., order status machine)

For each function/module ask:
  ✓ Happy path — expected input → expected output
  ✓ Edge cases — empty, null, zero, max values
  ✓ Error paths — invalid input, network fail, DB error
  ✓ Security paths — injection, unauthorized access, rate limits
  ✓ Concurrency — race conditions, duplicate requests
Enter fullscreen mode Exit fullscreen mode

Part 3 — Stack-Specific Setup

3.1 Node.js (Generic)

Packages:

{
  "devDependencies": {
    "jest": "^29.x",
    "ts-jest": "^29.x",
    "@types/jest": "^29.x",
    "supertest": "^6.x",
    "nock": "^13.x",
    "faker": "^8.x"
  }
}
Enter fullscreen mode Exit fullscreen mode

jest.config.ts:

export default {
  preset: 'ts-jest',
  testEnvironment: 'node',
  roots: ['<rootDir>/src'],
  testMatch: ['**/*.spec.ts', '**/*.test.ts'],
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80
    }
  },
  collectCoverageFrom: ['src/**/*.ts', '!src/**/*.module.ts', '!src/main.ts']
}
Enter fullscreen mode Exit fullscreen mode

3.2 NestJS (Primary Recommendation for Node APIs)

Packages (built-in + additions):

{
  "devDependencies": {
    "@nestjs/testing": "^10.x",
    "jest": "^29.x",
    "ts-jest": "^29.x",
    "supertest": "^6.x",
    "@testcontainers/postgresql": "^10.x"
  }
}
Enter fullscreen mode Exit fullscreen mode

Unit Test — Service (Red → Green example):

// users.service.spec.ts — RED phase
describe('UsersService', () => {
  let service: UsersService;
  let repo: jest.Mocked<UserRepository>;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      providers: [
        UsersService,
        {
          provide: UserRepository,
          useValue: {
            findOne: jest.fn(),
            save: jest.fn(),
          }
        }
      ]
    }).compile();

    service = module.get(UsersService);
    repo = module.get(UserRepository);
  });

  it('should throw NotFoundException when user does not exist', async () => {
    repo.findOne.mockResolvedValue(null);
    await expect(service.findById('non-existent-id')).rejects.toThrow(NotFoundException);
  });
});
Enter fullscreen mode Exit fullscreen mode

Integration Test — Controller with real HTTP:

// users.e2e-spec.ts
describe('POST /users', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [AppModule]
    }).compile();
    app = module.createNestApplication();
    await app.init();
  });

  it('should create user and return 201', () => {
    return request(app.getHttpServer())
      .post('/users')
      .send({ email: 'test@example.com', password: 'securePass123' })
      .expect(201)
      .expect(res => {
        expect(res.body).toHaveProperty('id');
        expect(res.body.email).toBe('test@example.com');
      });
  });
});
Enter fullscreen mode Exit fullscreen mode

Testcontainers (Real DB in CI):

const container = await new PostgreSqlContainer('postgres:15').start();
// inject connection string into TypeORM config
Enter fullscreen mode Exit fullscreen mode

3.3 Express.js

// Minimal setup, no DI framework — use jest + supertest
import request from 'supertest';
import app from '../app'; // your express app

describe('GET /health', () => {
  it('returns 200 with status ok', async () => {
    const res = await request(app).get('/health');
    expect(res.status).toBe(200);
    expect(res.body.status).toBe('ok');
  });
});
Enter fullscreen mode Exit fullscreen mode

Key difference from NestJS: No built-in DI, so use dependency injection manually or use a light container like awilix for testability.


3.4 React.js

Packages:

{
  "devDependencies": {
    "@testing-library/react": "^14.x",
    "@testing-library/user-event": "^14.x",
    "@testing-library/jest-dom": "^6.x",
    "msw": "^2.x",
    "vitest": "^1.x"
  }
}
Enter fullscreen mode Exit fullscreen mode

Vitest is now preferred over Jest for React/Vite projects (2024+)

// LoginForm.test.tsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

describe('LoginForm', () => {
  it('should show error when email is invalid', async () => {
    render(<LoginForm onSubmit={jest.fn()} />);
    await userEvent.type(screen.getByLabelText('Email'), 'notvalid');
    await userEvent.click(screen.getByRole('button', { name: /submit/i }));
    expect(screen.getByText(/invalid email/i)).toBeInTheDocument();
  });
});
Enter fullscreen mode Exit fullscreen mode

MSW for API Mocking (industry standard):

import { http, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';

const server = setupServer(
  http.get('/api/users', () => HttpResponse.json([{ id: 1, name: 'Bhaumik' }]))
);
Enter fullscreen mode Exit fullscreen mode

3.5 Next.js

Additional considerations:

  • Test Server Components differently from Client Components
  • Use @testing-library/react for client components
  • Use Playwright or Cypress for full E2E (including SSR flows)
// app/actions/create-user.test.ts (Server Action testing)
import { createUser } from './create-user';

it('should return validation error for short password', async () => {
  const result = await createUser({ email: 'a@b.com', password: '123' });
  expect(result.error).toBe('Password too short');
});
Enter fullscreen mode Exit fullscreen mode

3.6 Angular

Built-in: Jasmine + Karma (legacy) → now migrating to Jest + Vitest

// users.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideHttpClientTesting } from '@angular/common/http/testing';

describe('UsersComponent', () => {
  let component: UsersComponent;
  let fixture: ComponentFixture<UsersComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [UsersComponent],
      providers: [provideHttpClientTesting()]
    }).compileComponents();
    fixture = TestBed.createComponent(UsersComponent);
    component = fixture.componentInstance;
  });

  it('should display users from service', () => {
    expect(component).toBeTruthy();
  });
});
Enter fullscreen mode Exit fullscreen mode

Angular 17+ recommendation: Use @analogjs/vitest-angular for faster testing.


3.7 Python

Packages:

pytest
pytest-cov
pytest-asyncio
pytest-mock
factory-boy
httpx (for async API tests)
Enter fullscreen mode Exit fullscreen mode
# test_user_service.py
import pytest
from unittest.mock import AsyncMock
from app.services.user_service import UserService

@pytest.mark.asyncio
async def test_raises_not_found_when_user_missing():
    repo = AsyncMock()
    repo.find_by_id.return_value = None
    service = UserService(repo)

    with pytest.raises(UserNotFoundException):
        await service.get_user("missing-id")
Enter fullscreen mode Exit fullscreen mode

FastAPI integration test:

from httpx import AsyncClient
from app.main import app

@pytest.mark.asyncio
async def test_create_user_returns_201():
    async with AsyncClient(app=app, base_url="http://test") as client:
        response = await client.post("/users", json={"email": "a@b.com"})
    assert response.status_code == 201
Enter fullscreen mode Exit fullscreen mode

3.8 Laravel

Built-in: PHPUnit + Pest (recommended for modern projects)

// tests/Unit/UserServiceTest.php (Pest)
it('throws exception when user not found', function () {
    $repo = Mockery::mock(UserRepository::class);
    $repo->shouldReceive('findById')->andReturn(null);

    $service = new UserService($repo);
    expect(fn () => $service->getUser('abc'))->toThrow(UserNotFoundException::class);
});
Enter fullscreen mode Exit fullscreen mode
// Feature test (Integration)
it('creates user via API', function () {
    $response = $this->postJson('/api/users', [
        'email' => 'test@example.com',
        'password' => 'securePass123'
    ]);
    $response->assertStatus(201)->assertJsonStructure(['id', 'email']);
    $this->assertDatabaseHas('users', ['email' => 'test@example.com']);
});
Enter fullscreen mode Exit fullscreen mode

Part 4 — TDD Flow in Practice

4.1 Standard TDD Workflow

Feature Requirement
        │
        ▼
  Identify Test Cases
  (unit → integration → e2e)
        │
        ▼
   Write Failing Test ──────────────────────┐
        │                                   │
        ▼                                   │
   Run Test → FAIL (RED) ✓                  │
        │                                   │
        ▼                                   │
   Write Minimum Code to Pass               │
        │                                   │
        ▼                                   │
   Run Test → PASS (GREEN) ✓                │
        │                                   │
        ▼                                   │
   Refactor (extract, simplify, type)       │
        │                                   │
        ▼                                   │
   Run All Tests → PASS ✓                   │
        │                                   │
        ▼                                   │
   Next Test Case ──────────────────────────┘
        │
        ▼
   PR + CI enforces coverage gate
Enter fullscreen mode Exit fullscreen mode

4.2 TDD for New Projects

1. Set up test infrastructure FIRST (jest, coverage config, CI pipeline)
2. Define interfaces/contracts before implementations
3. Write service interface → test against interface → implement
4. Bottom-up: Repository → Service → Controller → E2E
5. Enforce coverage thresholds from day 1 (80% min)
6. Commit convention: test commits separate from feature commits
Enter fullscreen mode Exit fullscreen mode

4.3 TDD for Legacy Projects (Retroactive)

This is harder. Use the Strangler Fig Pattern:

1. Do NOT rewrite everything — add tests around existing code first
2. Identify critical paths → write characterization tests first
   (these capture CURRENT behavior, not ideal behavior)
3. Refactor module by module, protected by characterization tests
4. Replace legacy code with TDD-developed replacements incrementally
5. Track coverage per module — set increasing baselines per sprint
Enter fullscreen mode Exit fullscreen mode

Tool: Istanbul/c8 (JS), Coverage.py (Python), Xdebug (PHP)

Use --coverage-threshold flags per directory for gradual enforcement.


Part 5 — AI-Assisted TDD: The Wrapper System

This is your key architectural challenge: how do you ensure AI-generated code also meets your TDD standards?

5.1 The Problem

AI tools (Cursor, GitHub Copilot, Claude) generate code without context of your test standards. Developers may accept generated code without tests, leading to:

  • Inconsistent test naming conventions
  • Missing edge case coverage
  • Wrong test granularity
  • Tests that don't follow AAA (Arrange-Act-Assert) pattern

5.2 The Solution: TDD Standards Wrapper System

Layer 1 — Project-Level Rules File (.cursorrules or CLAUDE.md)

# TDD Contract — All Code Generated Must Follow These Rules

## Test Requirements
- Every function/method must have a corresponding .spec.ts file
- Tests follow AAA: Arrange → Act → Assert — labeled with comments
- Unit tests must mock ALL external dependencies
- No test should depend on another test's state
- Minimum one test per: happy path, error path, edge case

## Naming Convention
- Test file: [module].spec.ts (unit) / [module].e2e-spec.ts (integration)
- Describe block: class/function name
- It block: "should [expected behavior] when [condition]"

## Coverage Gate
- Lines: 80%, Branches: 75%, Functions: 80%
- New modules must not lower global coverage

## Test Structure Template
describe('[ModuleName]', () => {
  // Setup
  beforeEach(() => { /* setup */ });
  afterEach(() => { /* cleanup */ });

  describe('[methodName]', () => {
    it('should [behavior] when [condition]', () => {
      // Arrange
      // Act
      // Assert
    });
  });
});
Enter fullscreen mode Exit fullscreen mode

Layer 2 — AI Prompt Wrapper (System Prompt / Custom Instructions)

When using Claude/Cursor for code generation, prefix with:

You are a senior engineer following strict TDD standards.
For every code change you make:
1. First output the test file (.spec.ts) using Jest + AAA pattern
2. Then output the implementation file
3. All external deps must be mocked in unit tests
4. Follow naming: "should [behavior] when [condition]"
5. Include: happy path, null/undefined edge case, error case
6. Do NOT write implementation before the test
Enter fullscreen mode Exit fullscreen mode

Store this as:

  • /prompts/tdd-code-gen.md — for manual use
  • Cursor .cursorrules — auto-injected to all AI interactions
  • VS Code snippet — for quick scaffold generation

Layer 3 — Pre-commit Hooks (Enforcement)

// package.json
{
  "lint-staged": {
    "src/**/*.ts": ["jest --findRelatedTests --passWithNoTests --coverage"]
  },
  "husky": {
    "pre-commit": "lint-staged",
    "pre-push": "jest --coverage --coverageThreshold='{\"global\":{\"lines\":80}}'"
  }
}
Enter fullscreen mode Exit fullscreen mode

Layer 4 — CI Pipeline Gate

# .github/workflows/test.yml
- name: Run Tests with Coverage
  run: |
    npm run test:cov
    # Fail if coverage drops below threshold
    npx jest --coverage --coverageThreshold='{"global":{"lines":80,"branches":75}}'
Enter fullscreen mode Exit fullscreen mode

Layer 5 — ESLint Test Rules

// eslint plugin: eslint-plugin-jest
{
  "plugins": ["jest"],
  "rules": {
    "jest/expect-expect": "error",
    "jest/no-disabled-tests": "warn",
    "jest/no-focused-tests": "error",
    "jest/valid-expect": "error",
    "jest/consistent-test-it": ["error", { "fn": "it" }]
  }
}
Enter fullscreen mode Exit fullscreen mode

Part 6 — Test Generation: Manual vs Automated

6.1 Manual Generation (AI-Assisted, Human-Reviewed)

Workflow:

  1. Developer writes interface/type → prompts AI for test scaffold
  2. AI generates test file using prompt wrapper (Layer 2)
  3. Developer reviews, adds domain-specific edge cases
  4. AI fills implementation given tests

Cursor workflow:

1. Create users.service.ts with method signatures only
2. Cmd+K: "Generate TDD tests for this service following .cursorrules"
3. Review + commit test file
4. Cmd+K: "Implement service methods to make these tests pass"
5. Run tests → iterate
Enter fullscreen mode Exit fullscreen mode

6.2 Automated Generation Tools

Tool Language Type Notes
Copilot Test Agent All AI-gen GitHub Copilot feature
CodiumAI / Qodo JS/TS/Python AI-gen unit Best for auto unit test gen
diffblue Cover Java AI Enterprise Java only
Pynguin Python Search-based Academic, generates pytest
TestPilot JS AI Microsoft Research tool
jest-auto-spies TS Helper Auto-generates spy objects

CodiumAI/Qodo is the current industry leader for automatic test generation in JS/TS/Python. It analyzes function signatures and generates multiple test cases automatically.

6.3 Scaffold Generation CLI (Custom Team Tool)

Build your own test scaffold generator:

// scripts/generate-test.ts
import { execSync } from 'child_process';
import * as fs from 'fs';

const moduleName = process.argv[2]; // e.g., "users"

const template = `
import { Test } from '@nestjs/testing';
import { ${toPascalCase(moduleName)}Service } from './${moduleName}.service';

describe('${toPascalCase(moduleName)}Service', () => {
  let service: ${toPascalCase(moduleName)}Service;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      providers: [${toPascalCase(moduleName)}Service]
    }).compile();
    service = module.get(${toPascalCase(moduleName)}Service);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });
});
`;

fs.writeFileSync(`src/${moduleName}/${moduleName}.service.spec.ts`, template);
console.log(`✓ Test scaffold created: ${moduleName}.service.spec.ts`);
Enter fullscreen mode Exit fullscreen mode
// package.json
{
  "scripts": {
    "generate:test": "ts-node scripts/generate-test.ts"
  }
}
Enter fullscreen mode Exit fullscreen mode

Usage: npm run generate:test users


Part 7 — Team Alignment & Standards

7.1 Developer Onboarding Doc (1-pager)

Every new developer should receive this contract:

TDD Contract — [Team Name]

1. No PR is merged without tests
2. Tests are written BEFORE implementation (or alongside for legacy)
3. Test naming: "should [behavior] when [condition]"
4. Pyramid ratio: 70% unit / 20% integration / 10% E2E
5. Coverage gate: 80% enforced in CI — PRs that drop coverage are blocked
6. Mocks: use jest.fn() / jest.spyOn() for external deps
7. Test data: use factory functions, never hardcoded magic values
8. AI-generated code must include AI-generated tests (use .cursorrules)
9. Failing tests in main branch = P0 incident
10. Review tests as carefully as implementation — they ARE documentation
Enter fullscreen mode Exit fullscreen mode

7.2 PR Review Checklist for Tests

□ Does every new function have at least one test?
□ Are failure/error paths tested?
□ Are external deps properly mocked?
□ Do tests follow AAA pattern?
□ Are test descriptions meaningful (not "it works")?
□ Is there test data factory used (no magic strings)?
□ Does coverage remain above threshold?
□ Are integration tests using real DB (testcontainers) or proper mocks?
Enter fullscreen mode Exit fullscreen mode

7.3 Test Factory Pattern (Team Standard)

// test/factories/user.factory.ts
import { faker } from '@faker-js/faker';

export const createUserDto = (overrides = {}) => ({
  id: faker.string.uuid(),
  email: faker.internet.email(),
  name: faker.person.fullName(),
  createdAt: new Date(),
  ...overrides
});

// Usage in tests:
const user = createUserDto({ email: 'specific@test.com' });
Enter fullscreen mode Exit fullscreen mode

Part 8 — Package Ecosystem Summary

JavaScript / TypeScript

Package Purpose Verdict
Jest Test runner + assertions Industry standard for Node/NestJS
Vitest Vite-native test runner Preferred for React/Next.js/Vite
Supertest HTTP integration testing Standard for Express/NestJS
MSW API mock server (browser + Node) Industry standard for React
Testcontainers Real DB in Docker for tests Best for integration tests
@faker-js/faker Test data generation Standard
jest-mock-extended TypeScript-aware auto-mocking Recommended for NestJS
Pact.js Consumer-driven contract tests Microservices only
Playwright E2E browser testing Now preferred over Cypress
Cypress E2E browser testing Still strong, but Playwright winning

Python

Package Purpose
pytest Standard test runner
pytest-cov Coverage
pytest-asyncio Async test support
factory-boy Test data factories
respx / httpx HTTP mocking for async
pytest-mock Mock integration

Laravel / PHP

Package Purpose
Pest Modern test framework (recommended)
PHPUnit Legacy but still supported
Mockery Mocking
Laravel Dusk Browser E2E

Part 9 — What the Industry Is Doing Now

9.1 Current Trends (2024–2025)

AI-assisted test generation is mainstream now. GitHub Copilot, Cursor, and Qodo are being used to scaffold tests. The shift is: AI writes first drafts, engineers review and enforce standards.

Vitest is winning in frontend. For Vite-based projects (Vite + React, Next.js app router), Vitest is significantly faster than Jest due to native ESM support and Vite transform reuse.

Testcontainers adoption is rising. Instead of mocking DB entirely, teams spin up real PostgreSQL/Redis/MongoDB containers in CI via Testcontainers. Tests are more realistic but still isolated.

Contract testing in microservices is growing. Pact and Pactflow adoption is increasing as teams feel the pain of mismatched API contracts between services.

Playwright over Cypress for E2E. Playwright's multi-browser support, built-in parallelism, and better CI performance has made it the new default.

Test coverage as a PR gate, not a metric. Teams are moving away from tracking coverage as a KPI toward using it purely as a blocking threshold.

9.2 What Most Teams Actually Do

Reality check — not everyone does pure TDD:

Approach Prevalence Notes
Test-after (write code then test) ~50% of teams Pragmatic, but riskier
TDD on critical paths only ~30% of teams Balanced approach
Pure TDD ~10% of teams Often fintech, healthcare
No tests ~10% of teams Startups pre-product-market-fit

The pragmatic hybrid is most common: TDD for services/domain logic, integration tests for DB layer, Playwright for critical user flows.


Part 10 — Future Scope and Roadmap

10.1 Your Adoption Plan

Phase 1 — Foundation (Week 1–2)

  • Configure Jest/Vitest per stack
  • Set up coverage thresholds in CI
  • Add pre-commit hooks (Husky + lint-staged)
  • Create .cursorrules with TDD prompt wrapper
  • Create test factory templates per module

Phase 2 — Culture (Week 3–4)

  • PR checklist enforcement
  • Onboarding doc for new devs
  • First "TDD session" — pair-program a feature end-to-end
  • Retroactive coverage tracking for legacy modules

Phase 3 — Automation (Month 2)

  • Build test scaffold generator CLI
  • Evaluate Qodo/CodiumAI for auto test gen
  • Integrate Testcontainers for integration tests
  • Add contract tests for any inter-service APIs

Phase 4 — Maturity (Month 3+)

  • Coverage reports in PR comments (via jest-coverage-comment action)
  • Mutation testing with Stryker (tests your tests)
  • Test quality metrics (flakiness tracking, test execution time)

10.2 Mutation Testing (Advanced)

Mutation testing checks if your tests are actually meaningful:

npm install --save-dev @stryker-mutator/core @stryker-mutator/jest-runner
npx stryker run
Enter fullscreen mode Exit fullscreen mode

Stryker introduces small bugs ("mutants") into your code and checks if your tests catch them. Mutation score > 70% means your tests have real value.


Appendix: Quick Reference

TDD Command Cheat Sheet

# NestJS
npm run test              # unit tests
npm run test:e2e          # integration/e2e tests  
npm run test:cov          # with coverage report

# React/Next.js (Vitest)
npx vitest                # watch mode
npx vitest run --coverage # single run with coverage

# Python
pytest tests/ -v --cov=app --cov-report=html

# Laravel
php artisan test --coverage
./vendor/bin/pest --coverage
Enter fullscreen mode Exit fullscreen mode

Coverage Report Integration (GitHub Actions)

- uses: ArtiomTr/jest-coverage-report-action@v2
  with:
    test-script: npm run test:cov
    threshold: 80
Enter fullscreen mode Exit fullscreen mode

Guide maintained by engineering team. Update when packages release major versions or architectural patterns shift.

Top comments (0)