スキル一覧に戻る
vapvarun

testing

by vapvarun

Personal backup of Claude Code skills and plugins

4🍴 0📅 2026年1月22日
GitHubで見るManusで実行

SKILL.md


name: testing description: Write tests for JavaScript, React, PHP, and WordPress including unit tests, integration tests, and E2E tests. Use when writing tests, setting up testing frameworks, or debugging test failures.

Testing Skill

Instructions

When writing tests:

1. JavaScript Testing (Jest)

Setup:

// jest.config.js
module.exports = {
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
  collectCoverageFrom: ['src/**/*.{js,jsx}'],
};

Unit Test Example:

// utils.test.js
import { formatPrice, validateEmail } from './utils';

describe('formatPrice', () => {
  it('formats number as currency', () => {
    expect(formatPrice(1000)).toBe('$1,000.00');
  });

  it('handles zero', () => {
    expect(formatPrice(0)).toBe('$0.00');
  });

  it('handles negative numbers', () => {
    expect(formatPrice(-50)).toBe('-$50.00');
  });
});

describe('validateEmail', () => {
  it('returns true for valid email', () => {
    expect(validateEmail('user@example.com')).toBe(true);
  });

  it('returns false for invalid email', () => {
    expect(validateEmail('invalid')).toBe(false);
    expect(validateEmail('no@domain')).toBe(false);
  });
});

Async Test:

describe('fetchUser', () => {
  it('fetches user data', async () => {
    const user = await fetchUser(1);
    expect(user).toHaveProperty('name');
    expect(user.id).toBe(1);
  });

  it('throws on invalid id', async () => {
    await expect(fetchUser(-1)).rejects.toThrow('Invalid ID');
  });
});

Mocking:

// Mock module
jest.mock('./api');
import { fetchData } from './api';

fetchData.mockResolvedValue({ data: 'mocked' });

// Mock function
const mockCallback = jest.fn();
mockCallback.mockReturnValue(42);

// Verify calls
expect(mockCallback).toHaveBeenCalled();
expect(mockCallback).toHaveBeenCalledWith('arg1', 'arg2');
expect(mockCallback).toHaveBeenCalledTimes(2);

2. React Testing (React Testing Library)

Component Test:

import { render, screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Button from './Button';

describe('Button', () => {
  it('renders with label', () => {
    render(<Button>Click me</Button>);
    expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
  });

  it('calls onClick when clicked', async () => {
    const handleClick = jest.fn();
    render(<Button onClick={handleClick}>Click</Button>);

    await userEvent.click(screen.getByRole('button'));
    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  it('is disabled when loading', () => {
    render(<Button loading>Submit</Button>);
    expect(screen.getByRole('button')).toBeDisabled();
  });
});

Form Test:

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

describe('LoginForm', () => {
  it('submits form with valid data', async () => {
    const onSubmit = jest.fn();
    render(<LoginForm onSubmit={onSubmit} />);

    await userEvent.type(screen.getByLabelText(/email/i), 'user@example.com');
    await userEvent.type(screen.getByLabelText(/password/i), 'password123');
    await userEvent.click(screen.getByRole('button', { name: /log in/i }));

    await waitFor(() => {
      expect(onSubmit).toHaveBeenCalledWith({
        email: 'user@example.com',
        password: 'password123',
      });
    });
  });

  it('shows error for invalid email', async () => {
    render(<LoginForm onSubmit={jest.fn()} />);

    await userEvent.type(screen.getByLabelText(/email/i), 'invalid');
    await userEvent.click(screen.getByRole('button', { name: /log in/i }));

    expect(await screen.findByText(/invalid email/i)).toBeInTheDocument();
  });
});

3. PHP Testing (PHPUnit)

Setup:

<!-- phpunit.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php" colors="true">
    <testsuites>
        <testsuite name="Unit">
            <directory>tests/Unit</directory>
        </testsuite>
    </testsuites>
</phpunit>

Unit Test:

<?php
// tests/Unit/HelperTest.php
use PHPUnit\Framework\TestCase;

class HelperTest extends TestCase
{
    public function test_format_price_returns_formatted_string()
    {
        $result = format_price(1000);
        $this->assertEquals('$1,000.00', $result);
    }

    public function test_sanitize_title_removes_special_chars()
    {
        $result = sanitize_title('Hello World!');
        $this->assertEquals('hello-world', $result);
    }

    /**
     * @dataProvider emailProvider
     */
    public function test_validate_email($email, $expected)
    {
        $this->assertEquals($expected, validate_email($email));
    }

    public function emailProvider(): array
    {
        return [
            ['user@example.com', true],
            ['invalid', false],
            ['', false],
        ];
    }
}

4. WordPress Testing

Setup:

<?php
// tests/bootstrap.php
$_tests_dir = getenv('WP_TESTS_DIR') ?: '/tmp/wordpress-tests-lib';
require_once $_tests_dir . '/includes/functions.php';

function _manually_load_plugin() {
    require dirname(__DIR__) . '/plugin-name.php';
}
tests_add_filter('muplugins_loaded', '_manually_load_plugin');

require $_tests_dir . '/includes/bootstrap.php';

Plugin Test:

<?php
class PluginTest extends WP_UnitTestCase
{
    public function test_plugin_is_activated()
    {
        $this->assertTrue(is_plugin_active('plugin-name/plugin-name.php'));
    }

    public function test_custom_post_type_is_registered()
    {
        $this->assertTrue(post_type_exists('portfolio'));
    }

    public function test_shortcode_renders_content()
    {
        $output = do_shortcode('[my_shortcode]');
        $this->assertStringContainsString('expected-content', $output);
    }
}

5. E2E Testing (Playwright)

// tests/e2e/login.spec.js
import { test, expect } from '@playwright/test';

test.describe('Login Flow', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/login');
  });

  test('successful login redirects to dashboard', async ({ page }) => {
    await page.fill('[name="email"]', 'user@example.com');
    await page.fill('[name="password"]', 'password123');
    await page.click('button[type="submit"]');

    await expect(page).toHaveURL('/dashboard');
    await expect(page.locator('h1')).toContainText('Welcome');
  });

  test('invalid credentials show error', async ({ page }) => {
    await page.fill('[name="email"]', 'wrong@example.com');
    await page.fill('[name="password"]', 'wrongpassword');
    await page.click('button[type="submit"]');

    await expect(page.locator('.error')).toBeVisible();
    await expect(page.locator('.error')).toContainText('Invalid credentials');
  });
});

6. Test Structure

tests/
├── unit/           # Pure function tests
├── integration/    # Component interaction tests
├── e2e/           # Full user flow tests
├── fixtures/      # Test data
├── mocks/         # Mock implementations
└── helpers/       # Test utilities

7. Testing Best Practices

  • Test behavior, not implementation
  • One assertion per test (when practical)
  • Use descriptive test names
  • Arrange-Act-Assert pattern
  • Don't test external libraries
  • Keep tests fast and isolated
  • Use factories for test data
  • Mock external dependencies
  • Aim for 80%+ coverage on critical paths
  • Run tests in CI/CD

8. Common Matchers

// Jest/Vitest
expect(value).toBe(exact);
expect(value).toEqual(deepEqual);
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeNull();
expect(value).toContain(item);
expect(value).toHaveLength(3);
expect(value).toMatch(/regex/);
expect(fn).toThrow(Error);
expect(fn).toHaveBeenCalled();

スコア

総合スコア

50/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です