--- file_type: "instructions" title: "Quality Assurance Standards" description: "Comprehensive testing, validation, and quality assurance standards for all GitHub repository code and automation" version: "v1.0" last_updated: "2025-12-07" owners: ["GitHub Community Health Team"] tags: ["testing", "quality", "jest", "playwright", "coverage", "ci-cd"] applyTo: ["**/*.{test,spec}.{js,ts,jsx,tsx}", "**/__tests__/**/*"] status: "active" stability: "stable" domain: "generic" --- # Quality Assurance Standards You are a quality assurance strategist. Follow our testing and validation standards to plan and enforce coverage across code and automation. Avoid untested changes, skipped QA gates, or undocumented deviations from the testing pyramid. ## Overview Applies to testing and QA across code, automation, and workflows. Covers strategy, coverage targets, unit/integration/e2e testing, CI/CD integration, and quality gates. Excludes language-specific linting rules (see `linting.instructions.md`). ## General Rules - Follow the testing pyramid distribution and coverage targets. - Keep tests automated and reproducible; integrate with CI. - Document deviations and avoid merging untested changes. - Use appropriate frameworks (Jest, Playwright, etc.) per layer. ## Detailed Guidance - Use the sections below for strategy, layer guidance, CI integration, and quality gates. - Align test configs with repository scripts and workflows. ## Examples - **Good:** 70/20/10 unit/integration/e2e split with coverage gates, CI enforcement, and documented acceptance criteria. - **Avoid:** Skipping tests for changes or reducing coverage without approvals. ## Validation - Run project test suites (`npm run test`, `npm run test:js`, Playwright, etc.) and check coverage thresholds. - Verify CI pipelines enforce tests and quality gates. - Ensure test configs and scripts match documentation. ## Table of Contents - [Testing Strategy](#testing-strategy) - [Testing Pyramid](#testing-pyramid) - [Coverage Requirements](#coverage-requirements) - [Unit Testing (Jest)](#unit-testing-jest) - [Configuration](#jest-configuration) - [Writing Tests](#writing-unit-tests) - [Best Practices](#unit-test-best-practices) - [Integration Testing](#integration-testing) - [End-to-End Testing](#end-to-end-testing) - [CI/CD Integration](#cicd-integration) - [Quality Gates](#quality-gates) - [References](#references) --- ## Testing Strategy ### Testing Pyramid ```mermaid graph TD A[E2E Tests
User Workflows] --> B[Integration Tests
Component Interaction] B --> C[Unit Tests
Pure Functions & Logic] C --> D[Static Analysis
Linting & Type Checking] classDef e2e fill:#ffebee classDef integration fill:#fff3e0 classDef unit fill:#e8f5e8 classDef static fill:#e1f5fe class A e2e class B integration class C unit class D static ``` **Test Layer Distribution:** - **Unit Tests**: 70% of test coverage (fast, isolated) - **Integration Tests**: 20% of test coverage (component interaction) - **E2E Tests**: 10% of test coverage (critical user paths) ### Coverage Requirements | Code Type | Minimum Coverage | Target Coverage | | ----------------------- | ---------------- | --------------- | | Critical business logic | 90% | 95% | | Automation scripts | 85% | 90% | | Utility functions | 80% | 85% | | UI components | 75% | 80% | | **Overall project** | **75%** | **85%** | --- ## Unit Testing (Jest) [Jest](https://jestjs.io/) is the primary unit testing framework for JavaScript and TypeScript code. ### Jest Configuration **Config Files:** - Main config: [`jest.config.js`](../jest.config.js) or [`jest.config.cjs`](../jest.config.cjs) - Setup: `jest.setup.js` for global test setup - Helpers: `tests/test-helpers.js` for shared utilities **NPM Scripts:** ```json { "scripts": { "test": "npm run test:js", "test:js": "jest --coverage --forceExit --detectOpenHandles", "test:watch": "jest --watch", "test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand" } } ``` **Setup:** ```bash npm install --save-dev jest @types/jest babel-jest ``` **Example Configuration:** ```javascript // jest.config.js module.exports = { testEnvironment: "node", coverageDirectory: "coverage", collectCoverageFrom: [ "scripts/**/*.js", "!scripts/**/*.test.js", "!**/node_modules/**", ], coverageThreshold: { global: { branches: 75, functions: 75, lines: 75, statements: 75, }, }, testMatch: ["**/__tests__/**/*.test.js", "**/*.test.js", "**/*.spec.js"], }; ``` ### Writing Unit Tests **Test Structure (Arrange-Act-Assert):** ```javascript describe("Module/Function Name", () => { // Setup beforeEach(() => { // Test setup - runs before each test }); // Teardown afterEach(() => { // Cleanup - runs after each test }); it("should do something specific", () => { // Arrange - setup test data const input = "test"; // Act - execute the function const result = functionUnderTest(input); // Assert - verify the result expect(result).toBe("expected"); }); it("should handle edge case", () => { // Test edge cases expect(functionUnderTest("")).toBe(""); expect(functionUnderTest(null)).toBe(null); }); it("should throw error for invalid input", () => { // Test error handling expect(() => { functionUnderTest(undefined); }).toThrow("Invalid input"); }); }); ``` **Testing GitHub Actions Scripts:** ```javascript describe("Label Sync Utility", () => { const { syncLabels } = require("../scripts/agents/includes/label-sync"); beforeEach(() => { jest.clearAllMocks(); }); it("should sync labels from configuration", async () => { // Arrange const mockConfig = { labels: [ { name: "bug", color: "d73a4a" }, { name: "enhancement", color: "a2eeef" }, ], }; // Act const result = await syncLabels(mockConfig); // Assert expect(result.created).toHaveLength(2); expect(result.created).toContain("bug"); expect(result.created).toContain("enhancement"); }); it("should handle sync errors gracefully", async () => { // Arrange const invalidConfig = { labels: null }; // Act & Assert await expect(syncLabels(invalidConfig)).rejects.toThrow( "Invalid configuration", ); }); }); ``` ### Unit Test Best Practices **DO:** - ✅ Write descriptive test names that explain intent - ✅ Follow Arrange-Act-Assert pattern - ✅ Test one thing per test case - ✅ Use meaningful assertions - ✅ Mock external dependencies (APIs, file system) - ✅ Keep tests fast (< 100ms per test) - ✅ Avoid test interdependencies - ✅ Test error conditions and edge cases - ✅ Use `describe` blocks to group related tests **DON'T:** - ❌ Test implementation details - ❌ Share state between tests - ❌ Use real network calls - ❌ Write overly complex test setups - ❌ Ignore failing tests - ❌ Test third-party library code --- ## Integration Testing Integration tests verify that components work correctly together. **Example: API Integration Test** ```javascript describe("GitHub API Integration", () => { it("should fetch and process repository data", async () => { // Arrange const mockOctokit = createMockOctokit(); // Act const data = await fetchRepositoryData("owner", "repo"); // Assert expect(data).toHaveProperty("name"); expect(data).toHaveProperty("labels"); expect(data.labels).toBeInstanceOf(Array); }); it("should handle rate limiting", async () => { // Test rate limit handling const result = await fetchWithRetry("/api/endpoint"); expect(result.retries).toBeGreaterThan(0); }); }); ``` **Workflow Integration Test:** ```javascript describe("Labeling Workflow Integration", () => { it("should apply labels based on file changes", () => { // Arrange const changedFiles = [ "scripts/agents/labeling.agent.js", "tests/labeling.test.js", ]; // Act const labels = determineLabels(changedFiles); // Assert expect(labels).toContain("area:agents"); expect(labels).toContain("lang:javascript"); expect(labels).toContain("type:automation"); }); }); ``` --- ## End-to-End Testing E2E tests validate critical user workflows and interactions. **When to Write E2E Tests:** - Critical user journeys (issue creation, PR submission) - Multi-step workflows (labeling → project sync → notification) - Integration with external systems (GitHub Actions, APIs) - UI interactions (if applicable) **E2E Test Example:** ```javascript describe("Issue Lifecycle E2E", () => { it("should complete full issue workflow", async () => { // 1. Create issue const issue = await createIssue({ title: "Test Issue", body: "Test description", labels: ["bug"], }); // 2. Verify labeling workflow ran await waitForWorkflow("labeling.yml"); // 3. Check labels applied correctly const updatedIssue = await getIssue(issue.number); expect(updatedIssue.labels).toContainEqual( expect.objectContaining({ name: "status:needs-triage" }), ); // 4. Verify project sync const projectItem = await getProjectItem(issue.number); expect(projectItem.status).toBe("Triage"); }); }); ``` --- ## CI/CD Integration ### Test Execution Flow ```mermaid sequenceDiagram participant Dev as Developer participant Local as Local Tests participant CI as CI Pipeline participant QA as Quality Gates Dev->>Local: Run Tests Locally Local->>Dev: Results & Coverage Dev->>CI: Push Changes CI->>CI: Lint Code CI->>CI: Run Unit Tests CI->>CI: Run Integration Tests CI->>CI: Generate Coverage CI->>QA: Check Quality Gates QA->>CI: Pass/Fail Status ``` ### GitHub Actions Workflow ```yaml name: Quality Assurance on: [pull_request, push] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: npm ci - run: npm run lint:all test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: npm ci - run: npm test - uses: codecov/codecov-action@v3 with: files: ./coverage/coverage-final.json integration: runs-on: ubuntu-latest needs: [lint, test] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 - run: npm ci - run: npm run test:integration ``` ### Coverage Reporting **Upload Coverage:** ```yaml - uses: codecov/codecov-action@v3 with: files: ./coverage/coverage-final.json fail_ci_if_error: true ``` **Coverage Badge:** ```markdown ![Coverage](https://codecov.io/gh/owner/repo/branch/main/graph/badge.svg) ``` --- ## Quality Gates Quality gates must pass before merging: ### Pre-Merge Checklist - [ ] All tests pass (unit, integration, E2E) - [ ] Code coverage meets minimum thresholds (75%) - [ ] All linting checks pass - [ ] No console errors or warnings - [ ] Security scan passed - [ ] Documentation updated - [ ] New code has corresponding tests - [ ] Breaking changes documented ### Automated Enforcement ```javascript // jest.config.js - Enforce coverage thresholds coverageThreshold: { global: { branches: 75, functions: 75, lines: 75, statements: 75 } } ``` ### Manual Review Checklist **For Code Reviewers:** - [ ] Tests cover happy path and error cases - [ ] Tests are clear and maintainable - [ ] No flaky or random test failures - [ ] Mock data is realistic - [ ] Test names describe behavior - [ ] No commented-out tests - [ ] No skipped tests without justification --- ## Troubleshooting ### Common Issues **Tests fail locally but pass in CI:** ```bash # Check Node.js version matches CI node --version # Should match .nvmrc or workflow # Clean install dependencies rm -rf node_modules package-lock.json npm ci # Clear Jest cache npm test -- --clearCache ``` **Coverage below threshold:** ```bash # Generate detailed coverage report npm test -- --coverage # View coverage report open coverage/lcov-report/index.html # Identify uncovered files npm test -- --coverage --collectCoverageFrom='scripts/**/*.js' ``` **Flaky tests:** - Investigate timing-related issues - Add proper waits and assertions - Check for race conditions - Use deterministic test data - Avoid shared state between tests **Test timeout:** ```javascript // Increase timeout for slow tests jest.setTimeout(10000); // Or per-test it("slow test", async () => { // test code }, 10000); ``` --- ## Test Organization ``` tests/ ├── README.md # Testing documentation ├── jest.setup.js # Jest global setup ├── test-helpers.js # Shared test utilities ├── __tests__/ # Unit tests │ ├── labeling.test.js │ ├── reporting.test.js │ └── utils.test.js ├── integration/ # Integration tests │ └── workflow-integration.test.js └── e2e/ # End-to-end tests └── issue-lifecycle.e2e.test.js ``` *This document consolidates quality assurance standards for GitHub community health repositories. All code must be tested and validated before merge.* --- ## References - [instructions.instructions.md](./instructions.instructions.md) - [instructions.instructions.md](instructions.instructions.md) - [instructions.instructions.md](instructions.instructions.md) - [coding-standards.instructions.md](coding-standards.instructions.md) - [linting.instructions.md](linting.instructions.md) - [workflows.instructions.md](workflows.instructions.md) - [languages.instructions.md](languages.instructions.md) - [test workflows](../.github/workflows/test*.yml) - [Jest Documentation](https://jestjs.io/) - [Jest Best Practices](https://jestjs.io/docs/best-practices) - [Testing Library](https://testing-library.com/) - [Test Pyramid](https://martinfowler.com/articles/practical-test-pyramid.html) - [AAA Pattern](https://automationpanda.com/2020/07/07/arrange-act-assert-a-pattern-for-writing-good-tests/) - [Istanbul Coverage](https://istanbul.js.org/) - [Codecov](https://about.codecov.io/)