agentleFS
nguyenthanhtatnguyenthanhtat/screen1-claude/skills/test-fully/SKILL.md

test-fully

Skill2 starsChanged 22 days agoMITView on GitHub

Generate comprehensive test suites for any codebase: unit, integration, end-to-end, and performance tests. Detects the existing test framework (Jest, Vitest, Pytest, JUnit, Go test, Playwright, etc.) and follows its conventions. Use when the user asks to write, add, or update tests for a file, module, or feature, or to raise test coverage.

  • Installs packages

The file

Show its rules and text

We split this skill into the rules it gives an agent

23 rules. About 0 are common, 14 are distinctive, and 9 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈14

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 9

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Compatibility: All major testing frameworks

    line 11
  2. Distinctive:

    When this skill is invoked, I will:

    line 42
  3. Distinctive:

    Read and understand the codebase structure

    line 45
  4. Very specific:

    Use beforeEach/afterEach for setup/cleanup

    line 482
  5. Very specific:

    Use jest.mock() for mocking modules

    line 483
  6. Very specific:

    Use jest.fn() for spy functions

    line 484
  7. Very specific:

    Use .toMatchSnapshot() for component testing

    line 485
  8. Very specific:

    Use .toMatchObject() for partial matching

    line 486
  9. Distinctive:

    Use fixtures for reusable setup

    line 510
  10. Very specific:

    Use @pytest.mark.parametrize for multiple inputs

    line 511
  11. Very specific:

    Use pytest.raises() for exception testing

    line 512
  12. Very specific:

    Use monkeypatch for mocking

    line 513
  13. Very specific:

    Use pytest-cov for coverage reports

    line 514
  14. Distinctive:

    When generating tests, ensure:

    line 549
  15. Distinctive:

    Test names describe what they test

    line 557
  16. Distinctive:

    Don't mock everything (test real code when possible)

    line 596
  17. Distinctive:

    Verify mock interactions when needed

    line 597
  18. Distinctive:

    When generating tests, provide:

    line 696
  19. Distinctive:

    When this skill is invoked:

    line 784
  20. Distinctive:

    Read the file(s) provided

    line 787
  21. Distinctive:

    Follow the framework's best practices

    line 797
  22. Distinctive:

    Use patterns from this skill document

    line 798
  23. Distinctive:

    Add clear descriptions and comments

    line 800

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Test Fully - Comprehensive Testing Skill

Version

  • Version: 1.0.0
  • Last Updated: 2025-02-10
  • Compatibility: All major testing frameworks

Purpose

Generate comprehensive test suites covering unit, integration, E2E, and performance testing for any codebase. Automatically detects testing frameworks and follows language-specific best practices.


How to Use This Skill

Quick Usage

# Test specific file
/test-fully src/utils/validator.js

# Test with focus on specific type
/test-fully --focus unit
/test-fully --focus integration
/test-fully --focus e2e
/test-fully --focus performance

# Test entire module
/test-fully src/features/auth/

# Update existing tests
/test-fully update tests for payment.js

Testing Strategy

When this skill is invoked, I will:

1. Code Analysis Phase

  • Read and understand the codebase structure
  • Identify all functions, methods, and components
  • Map dependencies and integration points
  • Detect existing patterns and conventions

2. Framework Detection Phase

Automatically identify the testing framework in use:

JavaScript/TypeScript:

  • Jest (check for jest.config.js, package.json scripts)
  • Vitest (check for vitest.config.ts)
  • Mocha + Chai (check for .mocharc.json)
  • Jasmine (check for jasmine.json)

Python:

  • pytest (check for pytest.ini, conftest.py)
  • unittest (check for test_*.py pattern)
  • nose2 (check for nose2.cfg)

Java:

  • JUnit 5 (check for @Test annotations, pom.xml)
  • JUnit 4 (check for older @Test imports)
  • TestNG (check for testng.xml)

Other Languages:

  • Go: testing package
  • Ruby: RSpec or Minitest
  • C#: xUnit, NUnit, or MSTest
  • PHP: PHPUnit
  • Rust: Built-in test framework

E2E Frameworks:

  • Playwright
  • Cypress
  • Selenium
  • Puppeteer

3. Test Generation Phase

Create tests covering:

A. Unit Tests

Focus: Individual functions/methods in isolation

Coverage Areas:

  • ✅ Happy path (valid inputs, expected outputs)
  • ✅ Edge cases (empty strings, null, undefined, zero, negative numbers)
  • ✅ Boundary conditions (min/max values, limits)
  • ✅ Type validation (wrong types, type coercion)
  • ✅ Error handling (exceptions, error messages)
  • ✅ State management (before/after state changes)
  • ✅ Side effects (external calls, mutations)

Example Patterns:

JavaScript (Jest):

describe('validateEmail', () => {
  // Happy path
  test('should return true for valid email', () => {
    expect(validateEmail('user@example.com')).toBe(true);
  });

  // Edge cases
  test('should return false for empty string', () => {
    expect(validateEmail('')).toBe(false);
  });

  test('should return false for null', () => {
    expect(validateEmail(null)).toBe(false);
  });

  // Boundary conditions
  test('should handle very long email addresses', () => {
    const longEmail = 'a'.repeat(100) + '@example.com';
    expect(validateEmail(longEmail)).toBe(true);
  });

  // Format validation
  test('should reject email without @', () => {
    expect(validateEmail('userexample.com')).toBe(false);
  });

  test('should reject email without domain', () => {
    expect(validateEmail('user@')).toBe(false);
  });
});

Python (pytest):

class TestValidateEmail:
    """Test email validation function"""

    # Happy path
    def test_valid_email(self):
        assert validate_email('user@example.com') is True

    # Edge cases
    def test_empty_string(self):
        assert validate_email('') is False

    def test_none_value(self):
        assert validate_email(None) is False

    # Boundary conditions
    def test_long_email(self):
        long_email = 'a' * 100 + '@example.com'
        assert validate_email(long_email) is True

    # Format validation
    @pytest.mark.parametrize('invalid_email', [
        'userexample.com',
        'user@',
        '@example.com',
        'user @example.com',
    ])
    def test_invalid_formats(self, invalid_email):
        assert validate_email(invalid_email) is False

B. Integration Tests

Focus: How components work together

Coverage Areas:

  • ✅ API endpoints with database
  • ✅ Service-to-service communication
  • ✅ Data flow between modules
  • ✅ External API integrations
  • ✅ Authentication flows
  • ✅ Transaction handling

Example Patterns:

JavaScript (Jest + Supertest):

describe('POST /api/users', () => {
  let db;

  beforeAll(async () => {
    db = await setupTestDatabase();
  });

  afterAll(async () => {
    await db.close();
  });

  beforeEach(async () => {
    await db.clear('users');
  });

  test('should create user and return 201', async () => {
    const userData = {
      email: 'test@example.com',
      name: 'Test User'
    };

    const response = await request(app)
      .post('/api/users')
      .send(userData)
      .expect(201);

    expect(response.body).toMatchObject({
      id: expect.any(String),
      email: userData.email,
      name: userData.name
    });

    // Verify database state
    const user = await db.findUserByEmail(userData.email);
    expect(user).toBeTruthy();
    expect(user.name).toBe(userData.name);
  });

  test('should return 400 for duplicate email', async () => {
    const userData = { email: 'test@example.com', name: 'User' };

    // Create first user
    await request(app).post('/api/users').send(userData);

    // Attempt duplicate
    const response = await request(app)
      .post('/api/users')
      .send(userData)
      .expect(400);

    expect(response.body.error).toContain('already exists');
  });
});

Python (pytest + Flask):

class TestUserAPI:
    @pytest.fixture(autouse=True)
    def setup(self, client, db):
        """Setup test database before each test"""
        self.client = client
        self.db = db
        db.clear_users()

    def test_create_user_success(self):
        """Should create user and return 201"""
        user_data = {
            'email': 'test@example.com',
            'name': 'Test User'
        }

        response = self.client.post('/api/users', json=user_data)

        assert response.status_code == 201
        data = response.get_json()
        assert 'id' in data
        assert data['email'] == user_data['email']

        # Verify database state
        user = self.db.find_user_by_email(user_data['email'])
        assert user is not None
        assert user.name == user_data['name']

    def test_create_user_duplicate_email(self):
        """Should return 400 for duplicate email"""
        user_data = {'email': 'test@example.com', 'name': 'User'}

        # Create first user
        self.client.post('/api/users', json=user_data)

        # Attempt duplicate
        response = self.client.post('/api/users', json=user_data)

        assert response.status_code == 400
        assert 'already exists' in response.get_json()['error']

C. End-to-End Tests

Focus: Complete user workflows

Coverage Areas:

  • ✅ User authentication flows
  • ✅ Multi-step processes (checkout, registration)
  • ✅ Form submissions
  • ✅ Navigation flows
  • ✅ Cross-page interactions

Example Patterns:

Playwright (TypeScript):

import { test, expect } from '@playwright/test';

test.describe('User Registration Flow', () => {
  test('should complete full registration process', async ({ page }) => {
    // Navigate to registration
    await page.goto('/register');

    // Fill registration form
    await page.fill('[data-testid="email-input"]', 'newuser@example.com');
    await page.fill('[data-testid="password-input"]', 'SecurePass123!');
    await page.fill('[data-testid="confirm-password"]', 'SecurePass123!');
    await page.fill('[data-testid="name-input"]', 'John Doe');

    // Submit form
    await page.click('[data-testid="submit-button"]');

    // Verify confirmation page
    await expect(page).toHaveURL(/.*\/welcome/);
    await expect(page.locator('h1')).toContainText('Welcome, John Doe');

    // Verify email sent (check for confirmation message)
    await expect(page.locator('.success-message')).toContainText(
      'verification email sent'
    );

    // Test logout
    await page.click('[data-testid="logout-button"]');
    await expect(page).toHaveURL('/login');
  });

  test('should show validation errors for invalid input', async ({ page }) => {
    await page.goto('/register');

    // Submit empty form
    await page.click('[data-testid="submit-button"]');

    // Check for validation errors
    await expect(page.locator('.error-email')).toBeVisible();
    await expect(page.locator('.error-password')).toBeVisible();
  });
});

Cypress (JavaScript):

describe('E-commerce Checkout Flow', () => {
  beforeEach(() => {
    cy.login('customer@example.com', 'password');
  });

  it('should complete purchase successfully', () => {
    // Add item to cart
    cy.visit('/products');
    cy.get('[data-testid="product-1"]').click();
    cy.get('[data-testid="add-to-cart"]').click();

    // Verify cart
    cy.get('[data-testid="cart-badge"]').should('contain', '1');

    // Go to checkout
    cy.get('[data-testid="cart-icon"]').click();
    cy.get('[data-testid="checkout-button"]').click();

    // Fill shipping information
    cy.get('#address').type('123 Main St');
    cy.get('#city').type('New York');
    cy.get('#zip').type('10001');

    // Continue to payment
    cy.get('[data-testid="continue-to-payment"]').click();

    // Fill payment (use test card)
    cy.get('#card-number').type('4242424242424242');
    cy.get('#expiry').type('12/25');
    cy.get('#cvv').type('123');

    // Submit order
    cy.get('[data-testid="place-order"]').click();

    // Verify success
    cy.url().should('include', '/order-confirmation');
    cy.get('[data-testid="order-number"]').should('be.visible');
    cy.get('.success-message').should('contain', 'Order placed successfully');
  });
});

D. Performance Tests

Focus: Speed, scalability, resource usage

Coverage Areas:

  • ✅ Load testing (concurrent users)
  • ✅ Stress testing (breaking points)
  • ✅ Response time benchmarks
  • ✅ Memory usage
  • ✅ Database query performance
  • ✅ API rate limits

Example Patterns:

JavaScript (Jest Performance):

describe('Performance Tests', () => {
  test('should process 10,000 records in under 1 second', () => {
    const records = generateMockRecords(10000);

    const startTime = performance.now();
    const result = processRecords(records);
    const endTime = performance.now();

    const duration = endTime - startTime;

    expect(result).toHaveLength(10000);
    expect(duration).toBeLessThan(1000); // Less than 1 second
  });

  test('should not leak memory', () => {
    const memBefore = process.memoryUsage().heapUsed;

    // Perform operation 1000 times
    for (let i = 0; i < 1000; i++) {
      processData(generateMockData());
    }

    // Force garbage collection if available
    if (global.gc) global.gc();

    const memAfter = process.memoryUsage().heapUsed;
    const memIncrease = memAfter - memBefore;

    // Memory increase should be minimal (< 10MB)
    expect(memIncrease).toBeLessThan(10 * 1024 * 1024);
  });
});

Python (pytest + locust for load testing):

from locust import HttpUser, task, between

class APILoadTest(HttpUser):
    wait_time = between(1, 3)

    @task(3)  # Weight: 3x more frequent
    def get_users(self):
        """Test GET /api/users endpoint"""
        self.client.get("/api/users")

    @task(1)
    def create_user(self):
        """Test POST /api/users endpoint"""
        self.client.post("/api/users", json={
            "email": f"user{random.randint(1, 10000)}@example.com",
            "name": "Test User"
        })

    @task(2)
    def search_users(self):
        """Test search functionality"""
        self.client.get(f"/api/users/search?q=test")

# Run with: locust -f test_load.py --users 100 --spawn-rate 10

Framework-Specific Best Practices

Jest (JavaScript/TypeScript)

Test Organization:

// src/utils/__tests__/validator.test.js
// or
// src/utils/validator.spec.js

// Use describe blocks for grouping
describe('Module: validator', () => {
  describe('Function: validateEmail', () => {
    test('should ...', () => {});
  });

  describe('Function: validatePhone', () => {
    test('should ...', () => {});
  });
});

Common Patterns:

  • Use beforeEach/afterEach for setup/cleanup
  • Use jest.mock() for mocking modules
  • Use jest.fn() for spy functions
  • Use .toMatchSnapshot() for component testing
  • Use .toMatchObject() for partial matching

pytest (Python)

Test Organization:

# tests/test_validator.py
# or
# tests/unit/test_validator.py

class TestValidateEmail:
    """Group related tests in classes"""

    @pytest.fixture
    def sample_email(self):
        """Reusable test data"""
        return "test@example.com"

    def test_valid_email(self, sample_email):
        """Test description"""
        assert validate_email(sample_email) is True

Common Patterns:

  • Use fixtures for reusable setup
  • Use @pytest.mark.parametrize for multiple inputs
  • Use pytest.raises() for exception testing
  • Use monkeypatch for mocking
  • Use pytest-cov for coverage reports

JUnit (Java)

Test Organization:

// src/test/java/com/example/ValidatorTest.java

@DisplayName("Email Validator Tests")
class ValidatorTest {

    @BeforeEach
    void setUp() {
        // Setup before each test
    }

    @Test
    @DisplayName("Should return true for valid email")
    void testValidEmail() {
        assertTrue(Validator.validateEmail("user@example.com"));
    }

    @ParameterizedTest
    @ValueSource(strings = {"invalid", "@example.com", "user@"})
    @DisplayName("Should return false for invalid emails")
    void testInvalidEmails(String email) {
        assertFalse(Validator.validateEmail(email));
    }
}

Test Quality Checklist

When generating tests, ensure:

✅ Test Independence

  • Each test can run alone
  • Tests don't depend on execution order
  • Proper cleanup in afterEach/teardown

✅ Clear Naming

  • Test names describe what they test
  • Use "should" statements
  • Include expected behavior

Good:

test('should return 404 when user not found', () => {});
test('should throw ValidationError for negative amounts', () => {});

Bad:

test('test1', () => {});
test('user test', () => {});

✅ Arrange-Act-Assert Pattern

test('should calculate discount correctly', () => {
  // Arrange: Setup test data
  const price = 100;
  const discountPercent = 10;

  // Act: Execute the function
  const result = calculateDiscount(price, discountPercent);

  // Assert: Verify the result
  expect(result).toBe(90);
});

✅ Comprehensive Coverage

  • Test happy paths
  • Test error paths
  • Test edge cases
  • Test boundary conditions

✅ Appropriate Mocking

  • Mock external dependencies (APIs, databases)
  • Don't mock everything (test real code when possible)
  • Verify mock interactions when needed

✅ Meaningful Assertions

// Good: Specific assertions
expect(user.email).toBe('test@example.com');
expect(response.status).toBe(200);

// Bad: Vague assertions
expect(user).toBeTruthy();
expect(response).toBeDefined();

Common Testing Patterns

Pattern 1: Testing Async Code

JavaScript (Jest):

test('should fetch user data', async () => {
  const data = await fetchUser(123);
  expect(data.name).toBe('John Doe');
});

test('should handle fetch errors', async () => {
  await expect(fetchUser(999)).rejects.toThrow('User not found');
});

Pattern 2: Testing with Mocks

JavaScript (Jest):

// Mock external API
jest.mock('../services/api');

test('should call API with correct parameters', async () => {
  const mockFetch = api.fetchData.mockResolvedValue({ data: 'test' });

  await getData('users');

  expect(mockFetch).toHaveBeenCalledWith('users');
  expect(mockFetch).toHaveBeenCalledTimes(1);
});

Pattern 3: Testing React Components

JavaScript (React Testing Library):

import { render, screen, fireEvent } from '@testing-library/react';

test('should update count when button clicked', () => {
  render(<Counter />);

  const button = screen.getByRole('button', { name: /increment/i });
  const count = screen.getByTestId('count');

  expect(count).toHaveTextContent('0');

  fireEvent.click(button);

  expect(count).toHaveTextContent('1');
});

Pattern 4: Testing with Database

Python (pytest + SQLAlchemy):

@pytest.fixture
def db_session():
    """Create test database session"""
    engine = create_engine('sqlite:///:memory:')
    Base.metadata.create_all(engine)
    Session = sessionmaker(bind=engine)
    session = Session()

    yield session

    session.close()

def test_create_user(db_session):
    """Should create user in database"""
    user = User(email='test@example.com', name='Test')
    db_session.add(user)
    db_session.commit()

    saved_user = db_session.query(User).filter_by(email='test@example.com').first()
    assert saved_user is not None
    assert saved_user.name == 'Test'

Output Format

When generating tests, provide:

1. Test Files

tests/
├── unit/
│   ├── test_validator.py
│   └── test_calculator.py
├── integration/
│   └── test_api.py
└── e2e/
    └── test_user_flow.spec.ts

2. Test Code

  • Complete, runnable test files
  • Proper imports and setup
  • Clear test names and descriptions
  • Helpful comments

3. Setup Instructions

# Install dependencies
npm install --save-dev jest @testing-library/react

# Run tests
npm test

# Run with coverage
npm test -- --coverage

# Run specific test file
npm test -- validator.test.js

4. Coverage Report

File              | % Stmts | % Branch | % Funcs | % Lines
------------------|---------|----------|---------|--------
validator.js      |   95.0  |   88.0   |  100.0  |   95.0
calculator.js     |   80.0  |   75.0   |   80.0  |   80.0

5. Coverage Gaps

Identify untested areas:

  • Missing error handling tests
  • Uncovered edge cases
  • Integration points without tests

Anti-Patterns to Avoid

❌ Testing Implementation Details

// Bad: Testing internal state
expect(component.state.count).toBe(1);

// Good: Testing behavior
expect(screen.getByText('Count: 1')).toBeInTheDocument();

❌ Overly Brittle Tests

// Bad: Exact string matching
expect(message).toBe('Error: User john@example.com not found in database table users');

// Good: Flexible matching
expect(message).toContain('not found');

❌ Testing Too Much at Once

// Bad: One giant test
test('should handle entire user lifecycle', () => {
  // 100 lines of test code...
});

// Good: Split into focused tests
test('should create user', () => {});
test('should update user', () => {});
test('should delete user', () => {});

Instructions

When this skill is invoked:

  1. Analyze the code
    • Read the file(s) provided
    • Understand the logic and dependencies
    • Identify testing framework in use
  2. Plan the test strategy
    • Determine which test types are needed (unit/integration/e2e)
    • Identify critical paths to test
    • Note external dependencies to mock
  3. Generate comprehensive tests
    • Follow the framework's best practices
    • Use patterns from this skill document
    • Cover happy paths, edge cases, and errors
    • Add clear descriptions and comments
  4. Provide execution instructions
    • Show how to install test dependencies
    • Provide commands to run tests
    • Explain how to check coverage
  5. Report gaps
    • Identify areas that need additional testing
    • Suggest improvements to test coverage
    • Note any limitations or assumptions

Now, please help me test the following code comprehensively:

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.