Skip to content
Back to skills

Nightgauge Test Gen

ASecurity

Generate comprehensive test suites with coverage analysis using parallel

  • 8 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 5, 2026
developmentjavascripttypescriptpythongojavabashtestinggitapiperformance

Works with

  • claude code
  • cursor
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned November 5, 2026

npx -y skills add nightgauge/nightgauge --skill nightgauge-test-gen --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Nightgauge Test Gen?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Nightgauge Test Gen
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/nightgauge-nightgauge-test-gen/badge)](https://www.skillsdirectory.com/skills/nightgauge-nightgauge-test-gen)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: nightgauge-test-gen
description: Generate comprehensive test suites with coverage analysis using parallel
  subagents. Supports Jest, Pytest, dotnet test, and Gradle. Use after
  /feature-dev or when any codebase needs better test coverage.
license: Apache-2.0
metadata:
  author: nightgauge
  version: "1.0.0"
  source: https://github.com/nightgauge/nightgauge
allowed-tools: Read Write Edit Glob Grep Bash Task AskUserQuestion
---

# Test Generation

> Generate comprehensive test suites with parallel subagents and coverage
> analysis

## Description

This skill generates comprehensive test suites by:

1. Analyzing source code to identify testable components
2. Detecting the test framework (Jest, Pytest, dotnet test, Gradle)
3. Spawning parallel subagents for unit, integration, and E2E tests
4. Analyzing coverage to identify gaps
5. Generating edge case tests automatically
6. Running tests to verify they pass

## Invocation

| Tool           | Command                             |
| -------------- | ----------------------------------- |
| Claude Code    | `/nightgauge:test-gen` (via plugin) |
| OpenAI Codex   | `$nightgauge-test-gen`              |
| GitHub Copilot | Invoke via Agent Skills             |
| Cursor         | Invoke via Agent Skills             |

## Arguments

```bash
# Generate tests for changed files (default)
/nightgauge:test-gen

# Target specific files
/nightgauge:test-gen --files "src/services/*.ts"

# Set coverage target
/nightgauge:test-gen --target-coverage 90

# Generate only specific test types
/nightgauge:test-gen --types unit,integration

# Skip E2E tests (faster)
/nightgauge:test-gen --skip-e2e

# Preview what would be generated
/nightgauge:test-gen --dry-run
```

## Prerequisites

- **Source code to test**: Either specify with `--files` or have uncommitted
  changes
- **Test framework**: Will be auto-detected or you'll be asked
- **Test runner**: npm test, pytest, dotnet test, or gradle test

## Philosophy

- **Coverage-driven** — Focus on untested code paths first
- **Framework-native** — Generate idiomatic tests for each framework
- **Edge-case aware** — Automatically test boundaries, nulls, errors
- **Non-destructive** — Ask before modifying existing tests
- **Parallel execution** — Spawn subagents for faster generation

---

## Workflow

### Phase 0: Environment Preflight

<!-- include: ../_shared/PREFLIGHT.md -->

---

### Phase 1: Context Inference

#### Step 1.1: Extract Issue from Branch

**CRITICAL**: This skill is stateless. Extract issue context from branch name:

```bash
# Get current branch
BRANCH=$(git branch --show-current)

# Extract issue number from branch (e.g., feat/42-description -> 42)
ISSUE_NUMBER=$(printf '%s\n' "$BRANCH" | grep -oE '[0-9]+' | head -1)

echo "Branch: $BRANCH"
echo "Issue: #$ISSUE_NUMBER"
```

#### Step 1.2: Parse Arguments

Check for provided arguments:

- `--files` - Specific files to generate tests for
- `--target-coverage` - Coverage percentage target (default: 80)
- `--types` - Comma-separated: unit, integration, e2e (default: all)
- `--skip-e2e` - Skip E2E tests
- `--dry-run` - Show plan without writing files

---

### Phase 2: Source Analysis

#### Step 2.1: Identify Target Files

If `--files` argument provided:

```bash
# Use the provided glob pattern
FILES=$(ls $FILES_ARG 2>/dev/null)
```

Otherwise, detect changed files:

```bash
# Get files changed compared to main
git diff --name-only $(git merge-base main HEAD)..HEAD

# Or get uncommitted changes
git diff --name-only HEAD
```

#### Step 2.2: Filter to Testable Code

Exclude non-testable files:

```bash
# Exclude test files, configs, docs, assets
printf '%s\n' "$FILES" | grep -v -E '(\.test\.|\.spec\.|__tests__|\.config\.|\.md$|\.json$|\.yaml$|\.yml$)'
```

#### Step 2.3: Analyze File Contents

For each target file:

1. Read the file content
2. Identify:
   - Functions/methods that need tests
   - Classes and their public interfaces
   - Exported modules/components
   - Dependencies to mock

#### Step 2.4: Report Analysis

```
Source Analysis Complete
========================
Files to test: 5
- src/services/UserService.ts (3 functions)
- src/services/PhotoService.ts (4 functions)
- src/utils/validation.ts (6 functions)
- src/routes/users.ts (5 endpoints)
- src/routes/photos.ts (3 endpoints)

Total testable units: 21
Existing tests: 8
Gap: 13 units (62% coverage gap)
```

---

### Phase 3: Framework Detection

#### Step 3.1: Detect Test Framework

Check for framework indicators:

**JavaScript/TypeScript:**

```bash
# Check package.json for test framework
cat package.json | grep -E '"jest"|"vitest"|"mocha"|"jasmine"'

# Check for config files
ls jest.config.* vitest.config.* .mocharc.* 2>/dev/null
```

**Python:**

```bash
# Check for pytest
cat pyproject.toml requirements.txt setup.py 2>/dev/null | grep -i pytest

# Check for unittest references
ls tests/test_*.py *_test.py 2>/dev/null
```

**.NET:**

```bash
# Check csproj for test framework
grep -r "xunit\|nunit\|mstest" *.csproj */*.csproj 2>/dev/null
```

**Java:**

```bash
# Check build files
cat build.gradle pom.xml 2>/dev/null | grep -E "junit|testng|spock"
```

#### Step 3.2: Confirm or Ask

If framework detected:

```
Detected test framework: Jest
Test command: npm test
Coverage command: npm run test:coverage

Proceeding with Jest test generation...
```

If not detected:

```json
{
  "questions": [
    {
      "question": "Could not auto-detect test framework. Which are you using?",
      "header": "Framework",
      "multiSelect": false,
      "options": [
        { "label": "Jest", "description": "JavaScript/TypeScript testing" },
        { "label": "Pytest", "description": "Python testing framework" },
        { "label": "xUnit/NUnit", "description": ".NET testing" },
        { "label": "JUnit/Gradle", "description": "Java testing" }
      ]
    }
  ]
}
```

#### Step 3.3: Set Framework Configuration

Based on detected framework, set:

- Test file naming pattern (`.test.ts`, `_test.py`, `Tests.cs`)
- Test directory structure (`__tests__/`, `tests/`, `*.Tests/`)
- Mocking library (jest.mock, unittest.mock, Moq, Mockito)
- Assertion style

---

### Phase 4: Parallel Test Generation

#### Step 4.1: Prepare Subagent Prompts

Create focused prompts for each test type:

**Unit Test Subagent:**

```
Generate unit tests for the following files:
[file list]

Requirements:
- Test each function/method in isolation
- Mock all external dependencies
- Cover happy path + error cases
- Use [framework] patterns
- Follow naming: should_[expected]_when_[condition]
```

**Integration Test Subagent:**

```
Generate integration tests for the following components:
[component list]

Requirements:
- Test component interactions
- Use real dependencies where practical
- Test data flow between components
- Cover API contracts
```

**E2E Test Subagent (if not skipped):**

```
Generate E2E tests for the following user flows:
[flow list]

Requirements:
- Test complete user journeys
- Set up and tear down test data
- Use appropriate E2E framework (Playwright, Cypress, etc.)
```

#### Step 4.2: Launch Parallel Subagents

**Subagent Model**: When spawning parallel subagents for test generation,
specify `model: "sonnet"` on each Task invocation to use a cost-optimized model.
Sonnet provides sufficient quality for test generation while reducing token
costs compared to Opus.

```
Launching test generation subagents...

[1/3] Unit Test Subagent: Running (model: sonnet)
[2/3] Integration Test Subagent: Running (model: sonnet)
[3/3] E2E Test Subagent: Running (model: sonnet, skipped if --skip-e2e)
```

Use the `Task` tool to spawn subagents with `model: "sonnet"`:

```
Launch 3 subagents in parallel:

1. Unit test generator (model: sonnet):
   - Focus: Individual functions
   - Scope: All target files
   - Output: test files in appropriate locations

2. Integration test generator (model: sonnet):
   - Focus: Component interactions
   - Scope: Service/route combinations
   - Output: integration test files

3. E2E test generator (model: sonnet, unless --skip-e2e):
   - Focus: User flows
   - Scope: Critical paths
   - Output: E2E test files
```

#### Step 4.3: Collect Results

Wait for all subagents to complete. Collect:

- Generated test files
- Test count per type
- Any warnings or issues

---

### Phase 5: Coverage Analysis

#### Step 5.1: Run Existing Tests with Coverage

```bash
# JavaScript/TypeScript
npm run test:coverage

# Python
pytest --cov=src --cov-report=json

# .NET
dotnet test --collect:"XPlat Code Coverage"

# Java/Gradle
./gradlew test jacocoTestReport
```

#### Step 5.2: Parse Coverage Report

Extract coverage data:

- Overall coverage percentage
- Per-file coverage
- Uncovered lines/branches
- Uncovered functions

#### Step 5.3: Identify Coverage Gaps

Compare to `--target-coverage` (default 80%):

```
Coverage Analysis
=================
Current coverage: 65%
Target coverage: 80%
Gap: 15%

Files needing attention:
- src/services/PhotoService.ts: 45% covered
  - Uncovered: uploadPhoto(), deletePhoto()
- src/utils/validation.ts: 50% covered
  - Uncovered: validateEmail(), validatePhone()
```

#### Step 5.4: Generate Additional Tests for Gaps

If coverage below target, generate tests specifically for uncovered code:

```
Generating tests for coverage gaps...
- PhotoService.uploadPhoto() -> tests/services/photo.test.ts
- PhotoService.deletePhoto() -> tests/services/photo.test.ts
- validation.validateEmail() -> tests/utils/validation.test.ts
```

---

### Phase 6: Edge Case Generation

#### Step 6.1: Identify Input Types

For each function, identify parameter types:

- String parameters
- Numeric parameters
- Boolean parameters
- Object/Array parameters
- Async operations

#### Step 6.2: Generate Edge Case Tests

**String Edge Cases:**

```typescript
// Empty string
expect(validate("")).toBe(false);

// Null/undefined
expect(validate(null)).toThrow();

// Unicode characters
expect(validate("héllo 世界")).toBe(true);

// Very long string
expect(validate("a".repeat(10000))).toBe(false);

// Special characters
expect(validate('<script>alert("xss")</script>')).toBe(false);
```

**Numeric Edge Cases:**

```typescript
// Zero
expect(calculate(0)).toBe(0);

// Negative
expect(calculate(-1)).toThrow();

// Very large
expect(calculate(Number.MAX_SAFE_INTEGER)).toBe(expected);

// Decimal precision
expect(calculate(0.1 + 0.2)).toBeCloseTo(0.3);

// NaN
expect(calculate(NaN)).toThrow();
```

**Collection Edge Cases:**

```typescript
// Empty array
expect(process([])).toEqual([]);

// Single item
expect(process([1])).toEqual([1]);

// Large array (performance)
expect(process(Array(1000).fill(1))).toBeDefined();
```

**Async Edge Cases:**

```typescript
// Timeout
jest.setTimeout(5000);
await expect(fetchWithTimeout()).rejects.toThrow("timeout");

// Network failure
mockFetch.mockRejectedValue(new Error("Network error"));
await expect(fetchData()).rejects.toThrow();
```

---

### Phase 7: Non-Destructive Check

#### Step 7.1: Check for Existing Test Files

```bash
# Find existing test files that would be modified
ls tests/**/*.test.ts tests/**/*.spec.ts 2>/dev/null
```

#### Step 7.2: Compare with Generated Tests

For each file that would be created/modified:

- Check if file already exists
- Compare generated content with existing
- Identify conflicts

#### Step 7.3: Ask User for Handling

If existing tests found:

```json
{
  "questions": [
    {
      "question": "Found existing test files that would be modified. How would you like to proceed?",
      "header": "Existing Tests",
      "multiSelect": false,
      "options": [
        {
          "label": "Add only",
          "description": "Append new tests to existing files, keep all existing tests"
        },
        {
          "label": "Replace",
          "description": "Overwrite existing test files completely"
        },
        {
          "label": "Create separate",
          "description": "Use .generated.test.ts naming to keep both"
        },
        {
          "label": "Review first",
          "description": "Show me a diff of what would change"
        }
      ]
    }
  ]
}
```

#### Step 7.4: If Dry Run

If `--dry-run` was specified:

```
DRY RUN - No files will be written

Would create:
- tests/services/UserService.test.ts (45 lines, 8 tests)
- tests/services/PhotoService.test.ts (62 lines, 12 tests)
- tests/utils/validation.test.ts (38 lines, 15 tests)

Would modify:
- tests/routes/users.test.ts (+25 lines, +5 tests)

Total: 170 lines, 40 tests

Run without --dry-run to apply changes.
```

Exit after dry run report.

---

### Phase 8: Write Test Files

#### Step 8.1: Create Test Directories

```bash
mkdir -p tests/unit tests/integration tests/e2e
```

#### Step 8.2: Write Unit Tests

For each source file, create/update test file:

```typescript
// tests/services/UserService.test.ts
import { UserService } from "../../src/services/UserService";
import { mockUserRepository } from "../mocks/repositories";

describe("UserService", () => {
  let service: UserService;

  beforeEach(() => {
    service = new UserService(mockUserRepository);
  });

  describe("createUser", () => {
    it("should create user when valid data provided", async () => {
      // Test implementation
    });

    it("should throw when email already exists", async () => {
      // Test implementation
    });
  });
});
```

#### Step 8.3: Write Integration Tests

```typescript
// tests/integration/user-workflow.test.ts
describe("User Workflow Integration", () => {
  it("should complete user registration flow", async () => {
    // Create user
    // Verify email
    // Login
    // Access protected resource
  });
});
```

#### Step 8.4: Write E2E Tests (if not skipped)

```typescript
// tests/e2e/user-registration.spec.ts
import { test, expect } from "@playwright/test";

test("user can register and login", async ({ page }) => {
  await page.goto("/register");
  await page.fill('[name="email"]', "test@example.com");
  // ...
});
```

#### Step 8.5: Report Progress

```
Progress: [3/5] files complete
✓ tests/services/UserService.test.ts - Created (8 tests)
✓ tests/services/PhotoService.test.ts - Created (12 tests)
✓ tests/utils/validation.test.ts - Created (15 tests)
⋯ tests/routes/users.test.ts - In progress
  tests/routes/photos.test.ts - Pending
```

---

### Phase 9: Test Execution

#### Step 9.1: Run All Tests

```bash
# Run test command
npm test

# Or with coverage
npm run test:coverage
```

#### Step 9.2: Check Results

Parse test output:

- Number of tests passed
- Number of tests failed
- Coverage percentage

#### Step 9.3: Handle Failures

If tests fail:

```
Test Execution Results
======================
✓ 35 tests passed
✗ 5 tests failed

Failures:
1. UserService.test.ts > createUser > should throw when email exists
   Expected: Error('Email already exists')
   Received: Error('Validation failed')

2. validation.test.ts > validatePhone > should accept international format
   Expected: true
   Received: false
```

#### Step 9.4: Fix Failing Tests

For each failure:

1. Determine if test expectation is wrong
2. If test is wrong, fix the test assertion
3. If implementation is wrong, note it but don't fix (out of scope)
4. Re-run affected tests

```
Fixing test issues...
- UserService.test.ts: Updated error message expectation
- validation.test.ts: Fixed phone regex pattern in test

Re-running tests...
✓ All 40 tests passed
```

---

### Phase 10: Summary

#### Step 10.1: Generate Final Report

```
┌─────────────────────────────────────────────────────────────────┐
│  TEST GENERATION COMPLETE                                       │
└─────────────────────────────────────────────────────────────────┘

Branch:  feat/42-user-photo-upload
Issue:   #42

## Tests Generated

| Type        | Files | Tests | Coverage Added |
|-------------|-------|-------|----------------|
| Unit        | 3     | 35    | +25%           |
| Integration | 1     | 5     | +5%            |
| E2E         | 1     | 3     | N/A            |
| Edge Cases  | -     | 12    | +5%            |
| **Total**   | **5** | **55**| **+35%**       |

## Coverage

Before: 45%
After:  80%
Target: 80% ✓

## Files Created/Modified

Created:
- tests/services/UserService.test.ts
- tests/services/PhotoService.test.ts
- tests/utils/validation.test.ts
- tests/integration/user-workflow.test.ts
- tests/e2e/user-registration.spec.ts

Modified:
- tests/routes/users.test.ts (+5 tests)

## Next Steps

1. Review generated tests
2. Run `/nightgauge:pr-create` to create pull request
3. Or commit manually: git add tests/ && git commit -m "[TEST][#42] Add comprehensive test suite"
```

---

### Self-Assessment Epilogue

<!-- include: ../_shared/SELF_ASSESSMENT_EPILOGUE.md -->

---

## Error Handling

### No Testable Files Found

```
Warning: No testable files found.

Options:
1. Specify files manually with --files "src/**/*.ts"
2. Check that source files exist in expected locations
3. Verify you have uncommitted changes to test
```

### Framework Not Supported

```
Warning: Test framework not recognized.

Detected: karma (not fully supported)

Options:
1. Proceed with generic test generation
2. Specify a supported framework manually
3. Add framework support (contribution welcome!)
```

### Coverage Tool Not Available

```
Warning: Could not run coverage analysis.

The coverage command failed or is not configured.

Proceeding without coverage-driven generation.
To enable, add coverage configuration to your project.
```

### Tests Keep Failing

```
Warning: Tests still failing after 3 fix attempts.

Remaining failures:
- validation.test.ts: validateEmail pattern mismatch

This may indicate a bug in the source code, not the test.

Options:
1. Skip this test for now (mark as .skip)
2. Review the implementation
3. Cancel test generation
```

---

## Integration with Pipeline

This skill fits between `/nightgauge:feature-dev` and
`/nightgauge:pr-create`:

```
/issue-pickup → /feature-planning → /feature-dev → /nightgauge:test-gen → /pr-create
                                                         ↑
                                                    YOU ARE HERE
```

**Input from /feature-dev**: Implemented code ready for testing **Output to
/pr-create**: Comprehensive test suite with passing tests

---

## Framework-Specific Notes

### Jest (JavaScript/TypeScript)

- Test files: `*.test.ts`, `*.spec.ts`
- Mocking: `jest.mock()`, `jest.spyOn()`
- Async: `async/await`, `.resolves`, `.rejects`

### Pytest (Python)

- Test files: `test_*.py`, `*_test.py`
- Mocking: `unittest.mock`, `pytest-mock`
- Fixtures: `@pytest.fixture`

### xUnit/NUnit (.NET)

- Test files: `*Tests.cs`
- Mocking: `Moq`, `NSubstitute`
- Assertions: `Assert.Equal()`, FluentAssertions

### JUnit/Gradle (Java)

- Test files: `*Test.java`
- Mocking: `Mockito`
- Assertions: `assertThat()`, `assertEquals()`

---

## Source

Part of the [Nightgauge](https://github.com/nightgauge/nightgauge) -
Issue-to-PR Pipeline.

Files in this skill

  • CHANGELOG.md1.1 KB
  • SKILL.md18.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.