All skills
asyrafhussin avatar

/testing-best-practices

@575c801

Unit testing, integration testing, and test-driven development principles. Use when writing tests, reviewing test code, improving test coverage, or setting up testing strategy. Triggers on "write tests", "review tests", "testing best practices", or "TDD".

Use this Skill: https://skilld.dev/gh/asyrafhussin/agent-skills/testing-best-practices

This session only. Nothing lands on disk.

rulesassert-specific.md

≈1.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Specific Assertions

Impact: HIGH (error message quality and test clarity)

Use the most specific assertion available for clearer tests and better error messages. Specific matchers express intent more clearly and produce more informative failure output than generic boolean comparisons.

Incorrect

// ❌ Bad: Generic assertions hide intent and produce poor error messages
describe('UserService', () => {
  test('returns user by id', async () => {
    const user = await userService.findById('user-123');

    // Too generic — doesn't express what we're checking
    expect(user !== null).toBe(true);
    expect(user.name !== undefined).toBe(true);
  });

  test('validates email format', () => {
    const result = validateEmail('invalid-email');

    // Loses context about what failed
    expect(result).toBe(false);
  });

  test('returns list of users', async () => {
    const users = await userService.findAll();

    // Doesn't verify structure
    expect(users.length > 0).toBe(true);
  });

  test('user has required properties', () => {
    const user = createUser({ name: 'John', email: 'john@example.com' });

    // Testing everything loosely
    expect(JSON.stringify(user).includes('John')).toBe(true);
  });

  test('throws error for invalid id', async () => {
    try {
      await userService.findById('');
      expect(true).toBe(false); // Force fail if no error
    } catch (error) {
      expect(error).toBeDefined();
    }
  });
});

Problems:

  • Boolean comparisons like expect(x !== null).toBe(true) produce unhelpful "expected true, got false" messages
  • JSON.stringify checks are fragile and do not verify structure
  • Try/catch for error testing misses the case where no error is thrown
  • Generic assertions do not communicate intent to readers

Correct

// ✅ Good: Specific assertions with clear intent
describe('UserService', () => {
  test('returns user by id', async () => {
    const user = await userService.findById('user-123');

    expect(user).not.toBeNull();
    expect(user).toHaveProperty('name');
  });

  test('returns null for non-existent user', async () => {
    const user = await userService.findById('non-existent');

    expect(user).toBeNull();
  });

  test('validates correct email format', () => {
    expect(validateEmail('valid@example.com')).toBe(true);
  });

  test('rejects email without @ symbol', () => {
    expect(validateEmail('invalid-email')).toBe(false);
  });

  test('returns array of users', async () => {
    const users = await userService.findAll();

    expect(users).toBeInstanceOf(Array);
    expect(users).not.toHaveLength(0);
  });

  test('returns users with expected structure', async () => {
    const users = await userService.findAll();

    expect(users).toEqual(
      expect.arrayContaining([
        expect.objectContaining({
          id: expect.any(String),
          name: expect.any(String),
          email: expect.stringContaining('@')
        })
      ])
    );
  });

  test('user contains all required properties', () => {
    const user = createUser({ name: 'John', email: 'john@example.com' });

    expect(user).toMatchObject({
      name: 'John',
      email: 'john@example.com'
    });
  });

  test('user has generated id', () => {
    const user = createUser({ name: 'John', email: 'john@example.com' });

    expect(user.id).toMatch(/^user-[a-z0-9]+$/);
  });

  test('throws ValidationError for empty id', async () => {
    await expect(userService.findById('')).rejects.toThrow(ValidationError);
  });

  test('throws error with descriptive message for empty id', async () => {
    await expect(userService.findById('')).rejects.toThrow('ID cannot be empty');
  });
});

Benefits:

  • When tests fail, the error output immediately explains what went wrong
  • Anyone reading the test knows exactly what is being verified
  • Assertions serve as executable specifications
  • Specific matchers work better with TypeScript for type safety
  • Easier to update tests when requirements change

Reference: Jest Docs — Using Matchers

Source: SKILL.md on GitHub

No alerts16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill provides comprehensive guidelines and best practices for unit testing, integration testing, and Test-Driven Development (TDD). It consists entirely of documentation and illustrative code examples using industry-standard tools like Jest and Vitest. No security risks or malicious patterns were detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    29 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 575c801. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 7 months ago
metadata
{
  "author": "agent-skills",
  "version": "2.0.0"
}

README badge

README badge for asyrafhussin/agent-skills/testing-best-practices